@@ -75,6 +75,8 @@ struct plugins *plugins_new(const tal_t *ctx, struct log_book *log_book,
75
75
p -> plugin_idx = 0 ;
76
76
p -> dev_builtin_plugins_unimportant = false;
77
77
p -> want_db_transaction = true;
78
+ p -> subscriptions = tal (p , struct plugin_subscription_htable );
79
+ plugin_subscription_htable_init (p -> subscriptions );
78
80
79
81
return p ;
80
82
}
@@ -86,13 +88,13 @@ static void plugin_check_subscriptions(struct plugins *plugins,
86
88
struct plugin * plugin )
87
89
{
88
90
for (size_t i = 0 ; i < tal_count (plugin -> subscriptions ); i ++ ) {
89
- const char * topic = plugin -> subscriptions [i ];
90
- if (!streq (topic , "*" )
91
- && !notifications_have_topic (plugins , topic ))
91
+ struct plugin_subscription * sub = & plugin -> subscriptions [i ];
92
+ if (!streq (sub -> topic , "*" )
93
+ && !notifications_have_topic (plugins , sub -> topic ))
92
94
log_unusual (
93
95
plugin -> log ,
94
96
"topic '%s' is not a known notification topic" ,
95
- topic );
97
+ sub -> topic );
96
98
}
97
99
}
98
100
@@ -273,6 +275,12 @@ static void destroy_plugin(struct plugin *p)
273
275
/* Now free all the requests */
274
276
tal_free (reqs );
275
277
278
+ /* Remove any topics from the hash table */
279
+ for (size_t i = 0 ; i < tal_count (p -> subscriptions ); i ++ ) {
280
+ plugin_subscription_htable_del (p -> plugins -> subscriptions ,
281
+ & p -> subscriptions [i ]);
282
+ }
283
+
276
284
/* If this was last one manifests were waiting for, handle deps */
277
285
if (p -> plugin_state == AWAITING_GETMANIFEST_RESPONSE )
278
286
check_plugins_manifests (p -> plugins );
@@ -1474,13 +1482,13 @@ static const char *plugin_subscriptions_add(struct plugin *plugin,
1474
1482
plugin -> subscriptions = NULL ;
1475
1483
return NULL ;
1476
1484
}
1477
- plugin -> subscriptions = tal_arr (plugin , char * , 0 );
1485
+ plugin -> subscriptions = tal_arr (plugin , struct plugin_subscription , 0 );
1478
1486
if (subscriptions -> type != JSMN_ARRAY ) {
1479
1487
return tal_fmt (plugin , "\"result.subscriptions\" is not an array" );
1480
1488
}
1481
1489
1482
1490
json_for_each_arr (i , s , subscriptions ) {
1483
- char * topic ;
1491
+ struct plugin_subscription sub ;
1484
1492
if (s -> type != JSMN_STRING ) {
1485
1493
return tal_fmt (plugin ,
1486
1494
"result.subscriptions[%zu] is not a string: '%.*s'" , i ,
@@ -1492,9 +1500,17 @@ static const char *plugin_subscriptions_add(struct plugin *plugin,
1492
1500
* manifest, without checking that they exist, since
1493
1501
* later plugins may also emit notifications of custom
1494
1502
* types that we don't know about yet. */
1495
- topic = json_strdup (plugin , plugin -> buffer , s );
1496
- tal_arr_expand (& plugin -> subscriptions , topic );
1503
+ sub .topic = json_strdup (plugin , plugin -> buffer , s );
1504
+ sub .owner = plugin ;
1505
+ tal_arr_expand (& plugin -> subscriptions , sub );
1497
1506
}
1507
+
1508
+ /* Now they won't move with reallocation, we can add to htable */
1509
+ for (i = 0 ; i < tal_count (plugin -> subscriptions ); i ++ ) {
1510
+ plugin_subscription_htable_add (plugin -> plugins -> subscriptions ,
1511
+ & plugin -> subscriptions [i ]);
1512
+ }
1513
+
1498
1514
return NULL ;
1499
1515
}
1500
1516
@@ -2438,9 +2454,9 @@ static bool plugin_subscriptions_contains(struct plugin *plugin,
2438
2454
const char * method )
2439
2455
{
2440
2456
for (size_t i = 0 ; i < tal_count (plugin -> subscriptions ); i ++ ) {
2441
- if (streq (method , plugin -> subscriptions [i ])
2457
+ if (streq (method , plugin -> subscriptions [i ]. topic )
2442
2458
|| is_asterix_notification (method ,
2443
- plugin -> subscriptions [i ]))
2459
+ plugin -> subscriptions [i ]. topic ))
2444
2460
return true;
2445
2461
}
2446
2462
@@ -2449,23 +2465,29 @@ static bool plugin_subscriptions_contains(struct plugin *plugin,
2449
2465
2450
2466
bool plugins_anyone_cares (struct plugins * plugins , const char * method )
2451
2467
{
2452
- struct plugin * p ;
2468
+ struct plugin_subscription_htable_iter it ;
2453
2469
2454
2470
if (!plugins )
2455
2471
return false;
2456
2472
2457
- list_for_each (& plugins -> plugins , p , list ) {
2458
- if (plugin_subscriptions_contains (p , method ))
2459
- return true;
2460
- }
2461
- return false;
2473
+ if (plugin_subscription_htable_getfirst (plugins -> subscriptions ,
2474
+ method , & it ) != NULL )
2475
+ return true;
2476
+
2477
+ /* Wildcards cover everything except "log" */
2478
+ if (streq (method , "log" ))
2479
+ return false;
2480
+ return plugin_subscription_htable_getfirst (plugins -> subscriptions ,
2481
+ "*" , & it ) != NULL ;
2462
2482
}
2463
2483
2464
2484
bool plugin_single_notify (struct plugin * p ,
2465
2485
const struct jsonrpc_notification * n TAKES )
2466
2486
{
2467
2487
bool interested ;
2468
- if (p -> plugin_state == INIT_COMPLETE && plugin_subscriptions_contains (p , n -> method )) {
2488
+
2489
+ if (p -> plugin_state == INIT_COMPLETE
2490
+ && plugin_subscriptions_contains (p , n -> method )) {
2469
2491
plugin_send (p , json_stream_dup (p , n -> stream , p -> log ));
2470
2492
interested = true;
2471
2493
} else
@@ -2480,15 +2502,37 @@ bool plugin_single_notify(struct plugin *p,
2480
2502
void plugins_notify (struct plugins * plugins ,
2481
2503
const struct jsonrpc_notification * n TAKES )
2482
2504
{
2483
- struct plugin * p ;
2505
+ struct plugin_subscription_htable_iter it ;
2484
2506
2485
2507
if (taken (n ))
2486
2508
tal_steal (tmpctx , n );
2487
2509
2488
2510
/* If we're shutting down, ld->plugins will be NULL */
2489
- if (plugins ) {
2490
- list_for_each (& plugins -> plugins , p , list ) {
2491
- plugin_single_notify (p , n );
2511
+ if (!plugins )
2512
+ return ;
2513
+
2514
+ for (struct plugin_subscription * sub
2515
+ = plugin_subscription_htable_getfirst (plugins -> subscriptions ,
2516
+ n -> method , & it );
2517
+ sub != NULL ;
2518
+ sub = plugin_subscription_htable_getnext (plugins -> subscriptions ,
2519
+ n -> method , & it )) {
2520
+ if (sub -> owner -> plugin_state != INIT_COMPLETE )
2521
+ continue ;
2522
+ plugin_send (sub -> owner , json_stream_dup (sub -> owner , n -> stream , sub -> owner -> log ));
2523
+ }
2524
+
2525
+ /* "log" doesn't go to wildcards */
2526
+ if (!streq (n -> method , "log" )) {
2527
+ for (struct plugin_subscription * sub
2528
+ = plugin_subscription_htable_getfirst (plugins -> subscriptions ,
2529
+ "*" , & it );
2530
+ sub != NULL ;
2531
+ sub = plugin_subscription_htable_getnext (plugins -> subscriptions ,
2532
+ "*" , & it )) {
2533
+ if (sub -> owner -> plugin_state != INIT_COMPLETE )
2534
+ continue ;
2535
+ plugin_send (sub -> owner , json_stream_dup (sub -> owner , n -> stream , sub -> owner -> log ));
2492
2536
}
2493
2537
}
2494
2538
}
0 commit comments