@@ -130,21 +130,22 @@ static struct ly_set plugins_extensions = {0};
130
130
/**
131
131
* @brief Iterate over list of loaded plugins of the given @p type.
132
132
*
133
+ * @param[in] ctx The context for which the plugin is searched for
133
134
* @param[in] type Type of the plugins to iterate.
134
135
* @param[in,out] index The iterator - set to 0 for the first call.
135
136
* @return The plugin records, NULL if no more record is available.
136
137
*/
137
138
static struct lyplg_record *
138
- plugins_iter (enum LYPLG type , uint32_t * index )
139
+ plugins_iter (const struct ly_ctx * ctx , enum LYPLG type , uint32_t * index )
139
140
{
140
- struct ly_set * plugins ;
141
+ const struct ly_set * plugins ;
141
142
142
143
assert (index );
143
144
144
145
if (type == LYPLG_EXTENSION ) {
145
- plugins = & plugins_extensions ;
146
+ plugins = ctx ? & ctx -> plugins_extensions : & plugins_extensions ;
146
147
} else {
147
- plugins = & plugins_types ;
148
+ plugins = ctx ? & ctx -> plugins_types : & plugins_types ;
148
149
}
149
150
150
151
if (* index == plugins -> count ) {
@@ -156,15 +157,15 @@ plugins_iter(enum LYPLG type, uint32_t *index)
156
157
}
157
158
158
159
static void *
159
- lyplg_record_find (enum LYPLG type , const char * module , const char * revision , const char * name )
160
+ lyplg_record_find (const struct ly_ctx * ctx , enum LYPLG type , const char * module , const char * revision , const char * name )
160
161
{
161
162
uint32_t i = 0 ;
162
163
struct lyplg_record * item ;
163
164
164
165
assert (module );
165
166
assert (name );
166
167
167
- while ((item = plugins_iter (type , & i )) != NULL ) {
168
+ while ((item = plugins_iter (ctx , type , & i )) != NULL ) {
168
169
if (!strcmp (item -> module , module ) && !strcmp (item -> name , name )) {
169
170
if (item -> revision && revision && strcmp (item -> revision , revision )) {
170
171
continue ;
@@ -180,47 +181,77 @@ lyplg_record_find(enum LYPLG type, const char *module, const char *revision, con
180
181
}
181
182
182
183
struct lyplg_type *
183
- lyplg_type_plugin_find (const char * module , const char * revision , const char * name )
184
+ lyplg_type_plugin_find (const struct ly_ctx * ctx , const char * module , const char * revision , const char * name )
184
185
{
185
- struct lyplg_record * record ;
186
+ struct lyplg_record * record = NULL ;
187
+
188
+ if (ctx ) {
189
+ /* try to find context specific plugin */
190
+ record = lyplg_record_find (ctx , LYPLG_TYPE , module , revision , name );
191
+ }
192
+
193
+ if (!record ) {
194
+ /* try to find shared plugin */
195
+ record = lyplg_record_find (NULL , LYPLG_TYPE , module , revision , name );
196
+ }
186
197
187
- record = lyplg_record_find (LYPLG_TYPE , module , revision , name );
188
198
return record ? & ((struct lyplg_type_record * )record )-> plugin : NULL ;
189
199
}
190
200
191
201
struct lyplg_ext_record *
192
- lyplg_ext_record_find (const char * module , const char * revision , const char * name )
202
+ lyplg_ext_record_find (const struct ly_ctx * ctx , const char * module , const char * revision , const char * name )
193
203
{
194
- return lyplg_record_find (LYPLG_EXTENSION , module , revision , name );
204
+ struct lyplg_ext_record * record = NULL ;
205
+
206
+ if (ctx ) {
207
+ /* try to find context specific plugin */
208
+ record = lyplg_record_find (ctx , LYPLG_EXTENSION , module , revision , name );
209
+ }
210
+
211
+ if (!record ) {
212
+ /* try to find shared plugin */
213
+ record = lyplg_record_find (NULL , LYPLG_EXTENSION , module , revision , name );
214
+ }
215
+
216
+ return record ;
195
217
}
196
218
197
219
/**
198
220
* @brief Insert the provided extension plugin records into the internal set of extension plugins for use by libyang.
199
221
*
222
+ * @param[in] ctx The context to which the plugin should be associated with. If NULL, the plugin is considered to be shared
223
+ * between all existing contexts.
224
+ * @param[in] type The type of plugins records
200
225
* @param[in] recs An array of plugin records provided by the plugin implementation. The array must be terminated by a zeroed
201
226
* record.
202
227
* @return LY_SUCCESS in case of success
203
228
* @return LY_EINVAL for invalid information in @p recs.
204
229
* @return LY_EMEM in case of memory allocation failure.
205
230
*/
206
231
static LY_ERR
207
- plugins_insert (enum LYPLG type , const void * recs )
232
+ plugins_insert (struct ly_ctx * ctx , enum LYPLG type , const void * recs )
208
233
{
234
+ struct ly_set * plugins ;
235
+
209
236
if (!recs ) {
210
237
return LY_SUCCESS ;
211
238
}
212
239
213
240
if (type == LYPLG_EXTENSION ) {
214
241
const struct lyplg_ext_record * rec = (const struct lyplg_ext_record * )recs ;
215
242
243
+ plugins = ctx ? & ctx -> plugins_extensions : & plugins_extensions ;
244
+
216
245
for (uint32_t i = 0 ; rec [i ].name ; i ++ ) {
217
- LY_CHECK_RET (ly_set_add (& plugins_extensions , (void * )& rec [i ], 0 , NULL ));
246
+ LY_CHECK_RET (ly_set_add (plugins , (void * )& rec [i ], 0 , NULL ));
218
247
}
219
248
} else { /* LYPLG_TYPE */
220
249
const struct lyplg_type_record * rec = (const struct lyplg_type_record * )recs ;
221
250
251
+ plugins = ctx ? & ctx -> plugins_types : & plugins_types ;
252
+
222
253
for (uint32_t i = 0 ; rec [i ].name ; i ++ ) {
223
- LY_CHECK_RET (ly_set_add (& plugins_types , (void * )& rec [i ], 0 , NULL ));
254
+ LY_CHECK_RET (ly_set_add (plugins , (void * )& rec [i ], 0 , NULL ));
224
255
}
225
256
}
226
257
@@ -329,7 +360,7 @@ plugins_load(void *dlhandler, const char *pathname, enum LYPLG type)
329
360
}
330
361
331
362
/* ... and load all the types plugins */
332
- LY_CHECK_RET (plugins_insert (type , plugins ));
363
+ LY_CHECK_RET (plugins_insert (NULL , type , plugins ));
333
364
}
334
365
335
366
return LY_SUCCESS ;
@@ -457,48 +488,48 @@ lyplg_init(ly_bool builtin_type_plugins_only)
457
488
}
458
489
459
490
/* internal types */
460
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_binary ), error );
461
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_bits ), error );
462
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_boolean ), error );
463
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_decimal64 ), error );
464
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_empty ), error );
465
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_enumeration ), error );
466
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_identityref ), error );
467
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_instanceid ), error );
468
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_integer ), error );
469
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_leafref ), error );
470
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_string ), error );
471
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_union ), error );
491
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_binary ), error );
492
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_bits ), error );
493
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_boolean ), error );
494
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_decimal64 ), error );
495
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_empty ), error );
496
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_enumeration ), error );
497
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_identityref ), error );
498
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_instanceid ), error );
499
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_integer ), error );
500
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_leafref ), error );
501
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_string ), error );
502
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_union ), error );
472
503
473
504
if (!builtin_type_plugins_only ) {
474
505
/* yang */
475
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_instanceid_keys ), error );
506
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_instanceid_keys ), error );
476
507
477
508
/* ietf-inet-types */
478
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_ipv4_address ), error );
479
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_ipv4_address_no_zone ), error );
480
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_ipv6_address ), error );
481
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_ipv6_address_no_zone ), error );
482
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_ipv4_prefix ), error );
483
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_ipv6_prefix ), error );
509
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_ipv4_address ), error );
510
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_ipv4_address_no_zone ), error );
511
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_ipv6_address ), error );
512
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_ipv6_address_no_zone ), error );
513
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_ipv4_prefix ), error );
514
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_ipv6_prefix ), error );
484
515
485
516
/* ietf-yang-types */
486
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_date_and_time ), error );
487
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_hex_string ), error );
488
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_xpath10 ), error );
517
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_date_and_time ), error );
518
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_hex_string ), error );
519
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_xpath10 ), error );
489
520
490
521
/* ietf-netconf-acm */
491
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_node_instanceid ), error );
522
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_node_instanceid ), error );
492
523
493
524
/* lyds_tree */
494
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_TYPE , plugins_lyds_tree ), error );
525
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_TYPE , plugins_lyds_tree ), error );
495
526
496
527
/* internal extensions */
497
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_EXTENSION , plugins_metadata ), error );
498
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_EXTENSION , plugins_nacm ), error );
499
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_EXTENSION , plugins_yangdata ), error );
500
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_EXTENSION , plugins_schema_mount ), error );
501
- LY_CHECK_GOTO (ret = plugins_insert (LYPLG_EXTENSION , plugins_structure ), error );
528
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_EXTENSION , plugins_metadata ), error );
529
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_EXTENSION , plugins_nacm ), error );
530
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_EXTENSION , plugins_yangdata ), error );
531
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_EXTENSION , plugins_schema_mount ), error );
532
+ LY_CHECK_GOTO (ret = plugins_insert (NULL , LYPLG_EXTENSION , plugins_structure ), error );
502
533
}
503
534
504
535
#ifndef STATIC
@@ -562,3 +593,60 @@ lyplg_add(const char *pathname)
562
593
return ret ;
563
594
#endif
564
595
}
596
+
597
+ /**
598
+ * @brief Manually load an extension plugins from memory
599
+ *
600
+ * Note, that a plugin can be loaded only if there is at least one context. The loaded plugins are connected with the
601
+ * existence of a context. When all the contexts are destroyed, all the plugins are unloaded.
602
+ *
603
+ * @param[in] ctx The context to which the plugin should be associated with. If NULL, the plugin is considered to be shared
604
+ * between all existing contexts.
605
+ * @param[in] version The version of plugin records.
606
+ * @param[in] type The type of plugins records.
607
+ * @param[in] recs An array of plugin records provided by the plugin implementation. The array must be terminated by a zeroed
608
+ * record.
609
+ *
610
+ * @return LY_SUCCESS if the plugins with compatible version were successfully loaded.
611
+ * @return LY_EDENIED in case there is no context and the plugin cannot be loaded.
612
+ * @return LY_EINVAL when recs is NULL or the plugin contains invalid content for this libyang version.
613
+ */
614
+ static LY_ERR
615
+ lyplg_add_plugin (struct ly_ctx * ctx , uint32_t version , enum LYPLG type , const void * recs )
616
+ {
617
+ LY_ERR ret = LY_SUCCESS ;
618
+
619
+ LY_CHECK_ARG_RET (NULL , recs , LY_EINVAL );
620
+
621
+ if (version != plugins_load_info [type ].apiver ) {
622
+ LOGERR (ctx , LY_EINVAL , "Adding user %s plugin failed, wrong API version - %d expected, %d found." ,
623
+ plugins_load_info [type ].id , plugins_load_info [type ].apiver , version );
624
+ return LY_EINVAL ;
625
+ }
626
+
627
+ /* works only in case a context exists */
628
+ pthread_mutex_lock (& plugins_guard );
629
+ if (!context_refcount ) {
630
+ /* no context */
631
+ pthread_mutex_unlock (& plugins_guard );
632
+ LOGERR (NULL , LY_EDENIED , "To add a plugin, at least one context must exists." );
633
+ return LY_EDENIED ;
634
+ }
635
+
636
+ plugins_insert (ctx , type , recs );
637
+ pthread_mutex_unlock (& plugins_guard );
638
+
639
+ return ret ;
640
+ }
641
+
642
+ LIBYANG_API_DEF LY_ERR
643
+ lyplg_add_extension_plugin (struct ly_ctx * ctx , uint32_t version , const struct lyplg_ext_record * recs )
644
+ {
645
+ return lyplg_add_plugin (ctx , version , LYPLG_EXTENSION , recs );
646
+ }
647
+
648
+ LIBYANG_API_DEF LY_ERR
649
+ lyplg_add_type_plugin (struct ly_ctx * ctx , uint32_t version , const struct lyplg_type_record * recs )
650
+ {
651
+ return lyplg_add_plugin (ctx , version , LYPLG_TYPE , recs );
652
+ }
0 commit comments