@@ -130,21 +130,22 @@ static struct ly_set plugins_extensions = {0};
130130/**
131131 * @brief Iterate over list of loaded plugins of the given @p type.
132132 *
133+ * @param[in] ctx The context for which the plugin is searched for
133134 * @param[in] type Type of the plugins to iterate.
134135 * @param[in,out] index The iterator - set to 0 for the first call.
135136 * @return The plugin records, NULL if no more record is available.
136137 */
137138static 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 )
139140{
140- struct ly_set * plugins ;
141+ const struct ly_set * plugins ;
141142
142143 assert (index );
143144
144145 if (type == LYPLG_EXTENSION ) {
145- plugins = & plugins_extensions ;
146+ plugins = ctx ? & ctx -> plugins_extensions : & plugins_extensions ;
146147 } else {
147- plugins = & plugins_types ;
148+ plugins = ctx ? & ctx -> plugins_types : & plugins_types ;
148149 }
149150
150151 if (* index == plugins -> count ) {
@@ -156,15 +157,15 @@ plugins_iter(enum LYPLG type, uint32_t *index)
156157}
157158
158159static 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 )
160161{
161162 uint32_t i = 0 ;
162163 struct lyplg_record * item ;
163164
164165 assert (module );
165166 assert (name );
166167
167- while ((item = plugins_iter (type , & i )) != NULL ) {
168+ while ((item = plugins_iter (ctx , type , & i )) != NULL ) {
168169 if (!strcmp (item -> module , module ) && !strcmp (item -> name , name )) {
169170 if (item -> revision && revision && strcmp (item -> revision , revision )) {
170171 continue ;
@@ -180,47 +181,77 @@ lyplg_record_find(enum LYPLG type, const char *module, const char *revision, con
180181}
181182
182183struct 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 )
184185{
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+ }
186197
187- record = lyplg_record_find (LYPLG_TYPE , module , revision , name );
188198 return record ? & ((struct lyplg_type_record * )record )-> plugin : NULL ;
189199}
190200
191201struct 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 )
193203{
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 ;
195217}
196218
197219/**
198220 * @brief Insert the provided extension plugin records into the internal set of extension plugins for use by libyang.
199221 *
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
200225 * @param[in] recs An array of plugin records provided by the plugin implementation. The array must be terminated by a zeroed
201226 * record.
202227 * @return LY_SUCCESS in case of success
203228 * @return LY_EINVAL for invalid information in @p recs.
204229 * @return LY_EMEM in case of memory allocation failure.
205230 */
206231static LY_ERR
207- plugins_insert (enum LYPLG type , const void * recs )
232+ plugins_insert (struct ly_ctx * ctx , enum LYPLG type , const void * recs )
208233{
234+ struct ly_set * plugins ;
235+
209236 if (!recs ) {
210237 return LY_SUCCESS ;
211238 }
212239
213240 if (type == LYPLG_EXTENSION ) {
214241 const struct lyplg_ext_record * rec = (const struct lyplg_ext_record * )recs ;
215242
243+ plugins = ctx ? & ctx -> plugins_extensions : & plugins_extensions ;
244+
216245 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 ));
218247 }
219248 } else { /* LYPLG_TYPE */
220249 const struct lyplg_type_record * rec = (const struct lyplg_type_record * )recs ;
221250
251+ plugins = ctx ? & ctx -> plugins_types : & plugins_types ;
252+
222253 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 ));
224255 }
225256 }
226257
@@ -329,7 +360,7 @@ plugins_load(void *dlhandler, const char *pathname, enum LYPLG type)
329360 }
330361
331362 /* ... and load all the types plugins */
332- LY_CHECK_RET (plugins_insert (type , plugins ));
363+ LY_CHECK_RET (plugins_insert (NULL , type , plugins ));
333364 }
334365
335366 return LY_SUCCESS ;
@@ -457,48 +488,48 @@ lyplg_init(ly_bool builtin_type_plugins_only)
457488 }
458489
459490 /* 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 );
472503
473504 if (!builtin_type_plugins_only ) {
474505 /* 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 );
476507
477508 /* 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 );
484515
485516 /* 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 );
489520
490521 /* 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 );
492523
493524 /* 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 );
495526
496527 /* 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 );
502533 }
503534
504535#ifndef STATIC
@@ -562,3 +593,60 @@ lyplg_add(const char *pathname)
562593 return ret ;
563594#endif
564595}
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