@@ -75,6 +75,8 @@ struct plugins *plugins_new(const tal_t *ctx, struct log_book *log_book,
7575 p -> plugin_idx = 0 ;
7676 p -> dev_builtin_plugins_unimportant = false;
7777 p -> want_db_transaction = true;
78+ p -> subscriptions = tal (p , struct plugin_subscription_htable );
79+ plugin_subscription_htable_init (p -> subscriptions );
7880
7981 return p ;
8082}
@@ -86,13 +88,13 @@ static void plugin_check_subscriptions(struct plugins *plugins,
8688 struct plugin * plugin )
8789{
8890 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 ))
9294 log_unusual (
9395 plugin -> log ,
9496 "topic '%s' is not a known notification topic" ,
95- topic );
97+ sub -> topic );
9698 }
9799}
98100
@@ -273,6 +275,12 @@ static void destroy_plugin(struct plugin *p)
273275 /* Now free all the requests */
274276 tal_free (reqs );
275277
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+
276284 /* If this was last one manifests were waiting for, handle deps */
277285 if (p -> plugin_state == AWAITING_GETMANIFEST_RESPONSE )
278286 check_plugins_manifests (p -> plugins );
@@ -1474,13 +1482,13 @@ static const char *plugin_subscriptions_add(struct plugin *plugin,
14741482 plugin -> subscriptions = NULL ;
14751483 return NULL ;
14761484 }
1477- plugin -> subscriptions = tal_arr (plugin , char * , 0 );
1485+ plugin -> subscriptions = tal_arr (plugin , struct plugin_subscription , 0 );
14781486 if (subscriptions -> type != JSMN_ARRAY ) {
14791487 return tal_fmt (plugin , "\"result.subscriptions\" is not an array" );
14801488 }
14811489
14821490 json_for_each_arr (i , s , subscriptions ) {
1483- char * topic ;
1491+ struct plugin_subscription sub ;
14841492 if (s -> type != JSMN_STRING ) {
14851493 return tal_fmt (plugin ,
14861494 "result.subscriptions[%zu] is not a string: '%.*s'" , i ,
@@ -1492,9 +1500,17 @@ static const char *plugin_subscriptions_add(struct plugin *plugin,
14921500 * manifest, without checking that they exist, since
14931501 * later plugins may also emit notifications of custom
14941502 * 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 );
14971506 }
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+
14981514 return NULL ;
14991515}
15001516
@@ -2438,9 +2454,9 @@ static bool plugin_subscriptions_contains(struct plugin *plugin,
24382454 const char * method )
24392455{
24402456 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 )
24422458 || is_asterix_notification (method ,
2443- plugin -> subscriptions [i ]))
2459+ plugin -> subscriptions [i ]. topic ))
24442460 return true;
24452461 }
24462462
@@ -2449,23 +2465,29 @@ static bool plugin_subscriptions_contains(struct plugin *plugin,
24492465
24502466bool plugins_anyone_cares (struct plugins * plugins , const char * method )
24512467{
2452- struct plugin * p ;
2468+ struct plugin_subscription_htable_iter it ;
24532469
24542470 if (!plugins )
24552471 return false;
24562472
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 ;
24622482}
24632483
24642484bool plugin_single_notify (struct plugin * p ,
24652485 const struct jsonrpc_notification * n TAKES )
24662486{
24672487 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 )) {
24692491 plugin_send (p , json_stream_dup (p , n -> stream , p -> log ));
24702492 interested = true;
24712493 } else
@@ -2480,15 +2502,37 @@ bool plugin_single_notify(struct plugin *p,
24802502void plugins_notify (struct plugins * plugins ,
24812503 const struct jsonrpc_notification * n TAKES )
24822504{
2483- struct plugin * p ;
2505+ struct plugin_subscription_htable_iter it ;
24842506
24852507 if (taken (n ))
24862508 tal_steal (tmpctx , n );
24872509
24882510 /* 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 ));
24922536 }
24932537 }
24942538}
0 commit comments