sorcery.c 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2012 - 2013, Digium, Inc.
  5. *
  6. * Joshua Colp <jcolp@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Sorcery Data Access Layer API
  21. *
  22. * \author Joshua Colp <jcolp@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <support_level>core</support_level>
  26. ***/
  27. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include "asterisk/logger.h"
  30. #include "asterisk/sorcery.h"
  31. #include "asterisk/astobj2.h"
  32. #include "asterisk/format.h"
  33. #include "asterisk/format_cap.h"
  34. #include "asterisk/strings.h"
  35. #include "asterisk/config_options.h"
  36. #include "asterisk/netsock2.h"
  37. #include "asterisk/module.h"
  38. #include "asterisk/taskprocessor.h"
  39. #include "asterisk/threadpool.h"
  40. #include "asterisk/json.h"
  41. /* To prevent DEBUG_FD_LEAKS from interfering with things we undef open and close */
  42. #undef open
  43. #undef close
  44. /*! \brief Number of buckets for wizards (should be prime for performance reasons) */
  45. #define WIZARD_BUCKETS 7
  46. /*! \brief Number of buckets for types (should be prime for performance reasons) */
  47. #define TYPE_BUCKETS 53
  48. /*! \brief Number of buckets for instances (should be prime for performance reasons) */
  49. #define INSTANCE_BUCKETS 17
  50. /*! \brief Number of buckets for object fields (should be prime for performance reasons) */
  51. #define OBJECT_FIELD_BUCKETS 29
  52. #define NOTIFY_GENERIC_OBSERVERS(container, type, callback, ...) ({ \
  53. struct ao2_iterator i = ao2_iterator_init(container, 0); \
  54. struct type *observer; \
  55. ao2_rdlock(container); \
  56. while ((observer = ao2_iterator_next(&i))) { \
  57. if (observer->callbacks->callback) { \
  58. observer->callbacks->callback(__VA_ARGS__); \
  59. } \
  60. ao2_cleanup(observer); \
  61. } \
  62. ao2_unlock(container); \
  63. ao2_iterator_cleanup(&i); \
  64. })
  65. #define NOTIFY_GLOBAL_OBSERVERS(container, callback, ...) \
  66. NOTIFY_GENERIC_OBSERVERS(container, sorcery_global_observer, callback, __VA_ARGS__)
  67. #define NOTIFY_INSTANCE_OBSERVERS(container, callback, ...) \
  68. NOTIFY_GENERIC_OBSERVERS(container, sorcery_instance_observer, callback, __VA_ARGS__)
  69. #define NOTIFY_WIZARD_OBSERVERS(container, callback, ...) \
  70. NOTIFY_GENERIC_OBSERVERS(container, sorcery_wizard_observer, callback, __VA_ARGS__)
  71. /*! \brief Thread pool for observers */
  72. static struct ast_threadpool *threadpool;
  73. /*! \brief Structure for internal sorcery object information */
  74. struct ast_sorcery_object {
  75. /*! \brief Unique identifier of this object */
  76. char *id;
  77. /*! \brief Type of object */
  78. char type[MAX_OBJECT_TYPE];
  79. /*! \brief Optional object destructor */
  80. ao2_destructor_fn destructor;
  81. /*! \brief Extended object fields */
  82. struct ast_variable *extended;
  83. };
  84. /*! \brief Structure for registered object type */
  85. struct ast_sorcery_object_type {
  86. /*! \brief Unique name of the object type */
  87. char name[MAX_OBJECT_TYPE];
  88. /*! \brief Optional transformation callback */
  89. sorcery_transform_handler transform;
  90. /*! \brief Optional object set apply callback */
  91. sorcery_apply_handler apply;
  92. /*! \brief Optional object copy callback */
  93. sorcery_copy_handler copy;
  94. /*! \brief Optional object diff callback */
  95. sorcery_diff_handler diff;
  96. /*! \brief Wizard instances */
  97. struct ao2_container *wizards;
  98. /*! \brief Object fields */
  99. struct ao2_container *fields;
  100. /*! \brief Configuration framework general information */
  101. struct aco_info *info;
  102. /*! \brief Configuration framework file information */
  103. struct aco_file *file;
  104. /*! \brief Type details */
  105. struct aco_type type;
  106. /*! \brief Observers */
  107. struct ao2_container *observers;
  108. /*! \brief Serializer for observers */
  109. struct ast_taskprocessor *serializer;
  110. /*! \brief Specifies if object type is reloadable or not */
  111. unsigned int reloadable:1;
  112. };
  113. /*! \brief Structure for registered object type observer */
  114. struct ast_sorcery_object_type_observer {
  115. /*! \brief Pointer to the observer implementation */
  116. const struct ast_sorcery_observer *callbacks;
  117. };
  118. /*! \brief Structure used for observer invocations */
  119. struct sorcery_observer_invocation {
  120. /*! \brief Pointer to the object type */
  121. struct ast_sorcery_object_type *object_type;
  122. /*! \brief Pointer to the object */
  123. void *object;
  124. };
  125. /*! \brief Structure for registered object field */
  126. struct ast_sorcery_object_field {
  127. /*! \brief Name of the field */
  128. char name[MAX_OBJECT_FIELD];
  129. /*! \brief The compiled name regex if name is a regex */
  130. regex_t *name_regex;
  131. /*! \brief Callback function for translation of a single value */
  132. sorcery_field_handler handler;
  133. /*! \brief Callback function for translation of multiple values */
  134. sorcery_fields_handler multiple_handler;
  135. /*! \brief Position of the field */
  136. intptr_t args[];
  137. };
  138. /*! \brief Structure for an internal wizard instance */
  139. struct ast_sorcery_internal_wizard {
  140. /*! \brief Wizard interface itself */
  141. struct ast_sorcery_wizard callbacks;
  142. /*! \brief Observers */
  143. struct ao2_container *observers;
  144. };
  145. /*! \brief Structure for a wizard instance which operates on objects */
  146. struct ast_sorcery_object_wizard {
  147. /*! \brief Wizard interface itself */
  148. struct ast_sorcery_internal_wizard *wizard;
  149. /*! \brief Unique data for the wizard */
  150. void *data;
  151. /*! \brief Wizard is acting as an object cache */
  152. unsigned int caching:1;
  153. };
  154. /*! \brief Full structure for sorcery */
  155. struct ast_sorcery {
  156. /*! \brief Container for known object types */
  157. struct ao2_container *types;
  158. /*! \brief Observers */
  159. struct ao2_container *observers;
  160. /*! \brief The name of the module owning this sorcery instance */
  161. char module_name[0];
  162. };
  163. /*! \brief Structure for passing load/reload details */
  164. struct sorcery_load_details {
  165. /*! \brief Sorcery structure in use */
  166. const struct ast_sorcery *sorcery;
  167. /*! \brief Type of object being loaded */
  168. const char *type;
  169. /*! \brief Whether this is a reload or not */
  170. unsigned int reload:1;
  171. };
  172. /*! \brief Registered sorcery wizards */
  173. static struct ao2_container *wizards;
  174. /* The following 3 observer wrappers must name their
  175. * external observer 'callbacks' and it must be
  176. * the first member of the structure. Common macros
  177. * and container callbacks depend on it.
  178. */
  179. /*! \brief A global observer wrapper */
  180. struct sorcery_global_observer {
  181. const struct ast_sorcery_global_observer *callbacks;
  182. };
  183. /*! \brief An instance observer wrapper */
  184. struct sorcery_instance_observer {
  185. const struct ast_sorcery_instance_observer *callbacks;
  186. };
  187. /*! \brief A wizard observer wrapper */
  188. struct sorcery_wizard_observer {
  189. const struct ast_sorcery_wizard_observer *callbacks;
  190. };
  191. /*! \brief Registered global observers */
  192. struct ao2_container *observers;
  193. /*! \brief Registered sorcery instances */
  194. static struct ao2_container *instances;
  195. static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
  196. {
  197. int *field = (int *)(obj + args[0]);
  198. return (ast_asprintf(buf, "%d", *field) < 0) ? -1 : 0;
  199. }
  200. static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
  201. {
  202. unsigned int *field = (unsigned int *)(obj + args[0]);
  203. return (ast_asprintf(buf, "%u", *field) < 0) ? -1 : 0;
  204. }
  205. static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
  206. {
  207. double *field = (double *)(obj + args[0]);
  208. return (ast_asprintf(buf, "%f", *field) < 0) ? -1 : 0;
  209. }
  210. static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
  211. {
  212. ast_string_field *field = (const char **)(obj + args[0]);
  213. return !(*buf = ast_strdup(*field)) ? -1 : 0;
  214. }
  215. static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
  216. {
  217. unsigned int *field = (unsigned int *)(obj + args[0]);
  218. return !(*buf = ast_strdup(*field ? "true" : "false")) ? -1 : 0;
  219. }
  220. static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
  221. {
  222. struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + args[0]);
  223. return !(*buf = ast_strdup(ast_sockaddr_stringify(field))) ? -1 : 0;
  224. }
  225. static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
  226. {
  227. char *field = (char *)(obj + args[0]);
  228. return !(*buf = ast_strdup(field)) ? -1 : 0;
  229. }
  230. static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
  231. {
  232. struct ast_str *codec_buf = ast_str_alloca(64);
  233. struct ast_format_cap **cap = (struct ast_format_cap **)(obj + args[0]);
  234. return !(*buf = ast_strdup(ast_format_cap_get_names(*cap, &codec_buf)));
  235. }
  236. static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
  237. {
  238. switch(type) {
  239. case OPT_BOOL_T: return bool_handler_fn;
  240. case OPT_CHAR_ARRAY_T: return chararray_handler_fn;
  241. case OPT_CODEC_T: return codec_handler_fn;
  242. case OPT_DOUBLE_T: return double_handler_fn;
  243. case OPT_INT_T: return int_handler_fn;
  244. case OPT_SOCKADDR_T: return sockaddr_handler_fn;
  245. case OPT_STRINGFIELD_T: return stringfield_handler_fn;
  246. case OPT_UINT_T: return uint_handler_fn;
  247. default:
  248. case OPT_CUSTOM_T: return NULL;
  249. }
  250. return NULL;
  251. }
  252. /*! \brief Hashing function for sorcery wizards */
  253. static int sorcery_wizard_hash(const void *obj, const int flags)
  254. {
  255. const struct ast_sorcery_internal_wizard *object;
  256. const char *key;
  257. switch (flags & OBJ_SEARCH_MASK) {
  258. case OBJ_SEARCH_KEY:
  259. key = obj;
  260. break;
  261. case OBJ_SEARCH_OBJECT:
  262. object = obj;
  263. key = object->callbacks.name;
  264. break;
  265. default:
  266. ast_assert(0);
  267. return 0;
  268. }
  269. return ast_str_hash(key);
  270. }
  271. /*! \brief Comparator function for sorcery wizards */
  272. static int sorcery_wizard_cmp(void *obj, void *arg, int flags)
  273. {
  274. const struct ast_sorcery_internal_wizard *object_left = obj;
  275. const struct ast_sorcery_internal_wizard *object_right = arg;
  276. const char *right_key = arg;
  277. int cmp;
  278. switch (flags & OBJ_SEARCH_MASK) {
  279. case OBJ_SEARCH_OBJECT:
  280. right_key = object_right->callbacks.name;
  281. /* Fall through */
  282. case OBJ_SEARCH_KEY:
  283. cmp = strcmp(object_left->callbacks.name, right_key);
  284. break;
  285. case OBJ_SEARCH_PARTIAL_KEY:
  286. cmp = strncmp(object_left->callbacks.name, right_key, strlen(right_key));
  287. break;
  288. default:
  289. cmp = 0;
  290. break;
  291. }
  292. if (cmp) {
  293. return 0;
  294. }
  295. return CMP_MATCH;
  296. }
  297. /*! \brief Hashing function for sorcery wizards */
  298. static int object_type_field_hash(const void *obj, const int flags)
  299. {
  300. const struct ast_sorcery_object_field *object_field;
  301. const char *key;
  302. switch (flags & OBJ_SEARCH_MASK) {
  303. case OBJ_SEARCH_KEY:
  304. key = obj;
  305. break;
  306. case OBJ_SEARCH_OBJECT:
  307. object_field = obj;
  308. key = object_field->name;
  309. break;
  310. default:
  311. ast_assert(0);
  312. return 0;
  313. }
  314. return ast_str_hash(key);
  315. }
  316. static int object_type_field_cmp(void *obj, void *arg, int flags)
  317. {
  318. const struct ast_sorcery_object_field *field_left = obj;
  319. const struct ast_sorcery_object_field *field_right = arg;
  320. const char *right_key = arg;
  321. int cmp;
  322. switch (flags & OBJ_SEARCH_MASK) {
  323. case OBJ_SEARCH_OBJECT:
  324. right_key = field_right->name;
  325. /* Fall through */
  326. case OBJ_SEARCH_KEY:
  327. cmp = strcmp(field_left->name, right_key);
  328. break;
  329. case OBJ_SEARCH_PARTIAL_KEY:
  330. cmp = strncmp(field_left->name, right_key, strlen(right_key));
  331. break;
  332. default:
  333. cmp = 0;
  334. break;
  335. }
  336. if (cmp) {
  337. return 0;
  338. }
  339. return CMP_MATCH;
  340. }
  341. /*! \brief Cleanup function for graceful shutdowns */
  342. static void sorcery_cleanup(void)
  343. {
  344. ast_threadpool_shutdown(threadpool);
  345. threadpool = NULL;
  346. ao2_cleanup(wizards);
  347. wizards = NULL;
  348. ao2_cleanup(observers);
  349. observers = NULL;
  350. ao2_cleanup(instances);
  351. instances = NULL;
  352. }
  353. /*! \brief Compare function for sorcery instances */
  354. static int sorcery_instance_cmp(void *obj, void *arg, int flags)
  355. {
  356. const struct ast_sorcery *object_left = obj;
  357. const struct ast_sorcery *object_right = arg;
  358. const char *right_key = arg;
  359. int cmp;
  360. switch (flags & OBJ_SEARCH_MASK) {
  361. case OBJ_SEARCH_OBJECT:
  362. right_key = object_right->module_name;
  363. /* Fall through */
  364. case OBJ_SEARCH_KEY:
  365. cmp = strcmp(object_left->module_name, right_key);
  366. break;
  367. case OBJ_SEARCH_PARTIAL_KEY:
  368. cmp = strncmp(object_left->module_name, right_key, strlen(right_key));
  369. break;
  370. default:
  371. cmp = 0;
  372. break;
  373. }
  374. if (cmp) {
  375. return 0;
  376. }
  377. return CMP_MATCH;
  378. }
  379. /*! \brief Hashing function for sorcery instances */
  380. static int sorcery_instance_hash(const void *obj, const int flags)
  381. {
  382. const struct ast_sorcery *object;
  383. const char *key;
  384. switch (flags & OBJ_SEARCH_MASK) {
  385. case OBJ_SEARCH_KEY:
  386. key = obj;
  387. break;
  388. case OBJ_SEARCH_OBJECT:
  389. object = obj;
  390. key = object->module_name;
  391. break;
  392. default:
  393. ast_assert(0);
  394. return 0;
  395. }
  396. return ast_str_hash(key);
  397. }
  398. int ast_sorcery_init(void)
  399. {
  400. struct ast_threadpool_options options = {
  401. .version = AST_THREADPOOL_OPTIONS_VERSION,
  402. .auto_increment = 1,
  403. .max_size = 0,
  404. .idle_timeout = 60,
  405. .initial_size = 0,
  406. };
  407. ast_assert(wizards == NULL);
  408. if (!(threadpool = ast_threadpool_create("Sorcery", NULL, &options))) {
  409. threadpool = NULL;
  410. return -1;
  411. }
  412. if (!(wizards = ao2_container_alloc(WIZARD_BUCKETS, sorcery_wizard_hash, sorcery_wizard_cmp))) {
  413. ast_threadpool_shutdown(threadpool);
  414. return -1;
  415. }
  416. observers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, NULL, NULL);
  417. if (!observers) {
  418. sorcery_cleanup();
  419. return -1;
  420. }
  421. instances = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, INSTANCE_BUCKETS,
  422. sorcery_instance_hash, sorcery_instance_cmp);
  423. if (!instances) {
  424. sorcery_cleanup();
  425. return -1;
  426. }
  427. ast_register_cleanup(sorcery_cleanup);
  428. return 0;
  429. }
  430. static void sorcery_internal_wizard_destructor(void *obj)
  431. {
  432. struct ast_sorcery_internal_wizard *wizard = obj;
  433. ao2_cleanup(wizard->observers);
  434. }
  435. int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
  436. {
  437. struct ast_sorcery_internal_wizard *wizard;
  438. int res = -1;
  439. ast_assert(!ast_strlen_zero(interface->name));
  440. ao2_lock(wizards);
  441. if ((wizard = ao2_find(wizards, interface->name, OBJ_KEY | OBJ_NOLOCK))) {
  442. ast_log(LOG_WARNING, "Attempted to register sorcery wizard '%s' twice\n",
  443. interface->name);
  444. goto done;
  445. }
  446. if (!(wizard = ao2_alloc(sizeof(*wizard), sorcery_internal_wizard_destructor))) {
  447. goto done;
  448. }
  449. wizard->callbacks = *interface;
  450. wizard->callbacks.module = module;
  451. wizard->observers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, NULL, NULL);
  452. if (!wizard->observers) {
  453. goto done;
  454. }
  455. ao2_link_flags(wizards, wizard, OBJ_NOLOCK);
  456. res = 0;
  457. ast_verb(2, "Sorcery registered wizard '%s'\n", interface->name);
  458. NOTIFY_GLOBAL_OBSERVERS(observers, wizard_registered,
  459. interface->name, interface);
  460. done:
  461. ao2_cleanup(wizard);
  462. ao2_unlock(wizards);
  463. return res;
  464. }
  465. int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
  466. {
  467. struct ast_sorcery_internal_wizard *wizard =
  468. interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL;
  469. if (wizard) {
  470. NOTIFY_GLOBAL_OBSERVERS(observers, wizard_unregistering, wizard->callbacks.name, &wizard->callbacks);
  471. ao2_unlink(wizards, wizard);
  472. ao2_ref(wizard, -1);
  473. ast_verb(2, "Sorcery unregistered wizard '%s'\n", interface->name);
  474. return 0;
  475. } else {
  476. return -1;
  477. }
  478. }
  479. /*! \brief Internal callback function for removing a generic observer */
  480. static int sorcery_generic_observer_remove(void *obj, void *arg, int flags)
  481. {
  482. const struct sorcery_global_observer *observer = obj;
  483. return (observer->callbacks == arg) ? CMP_MATCH | CMP_STOP : 0;
  484. }
  485. int ast_sorcery_global_observer_add(const struct ast_sorcery_global_observer *callbacks)
  486. {
  487. struct sorcery_global_observer *cb;
  488. cb = ao2_alloc(sizeof(*cb), NULL);
  489. if (!cb) {
  490. return -1;
  491. }
  492. cb->callbacks = callbacks;
  493. ao2_link(observers, cb);
  494. ao2_ref(cb, -1);
  495. return 0;
  496. }
  497. void ast_sorcery_global_observer_remove(
  498. const struct ast_sorcery_global_observer *callbacks)
  499. {
  500. ao2_callback(observers, OBJ_NODATA | OBJ_UNLINK, sorcery_generic_observer_remove, (void *)callbacks);
  501. }
  502. int ast_sorcery_instance_observer_add(struct ast_sorcery *sorcery,
  503. const struct ast_sorcery_instance_observer *callbacks)
  504. {
  505. struct sorcery_instance_observer *cb;
  506. cb = ao2_alloc(sizeof(*cb), NULL);
  507. if (!cb) {
  508. return -1;
  509. }
  510. cb->callbacks = callbacks;
  511. ao2_link(sorcery->observers, cb);
  512. ao2_ref(cb, -1);
  513. return 0;
  514. }
  515. void ast_sorcery_instance_observer_remove(struct ast_sorcery *sorcery,
  516. const struct ast_sorcery_instance_observer *callbacks)
  517. {
  518. ao2_callback(sorcery->observers, OBJ_NODATA | OBJ_UNLINK, sorcery_generic_observer_remove, (void *)callbacks);
  519. }
  520. int ast_sorcery_wizard_observer_add(struct ast_sorcery_wizard *interface,
  521. const struct ast_sorcery_wizard_observer *callbacks)
  522. {
  523. RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
  524. interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
  525. ao2_cleanup);
  526. if (wizard) {
  527. struct sorcery_wizard_observer *cb;
  528. cb = ao2_alloc(sizeof(*cb), NULL);
  529. if (!cb) {
  530. return -1;
  531. }
  532. cb->callbacks = callbacks;
  533. ao2_link(wizard->observers, cb);
  534. ao2_ref(cb, -1);
  535. return 0;
  536. }
  537. return -1;
  538. }
  539. void ast_sorcery_wizard_observer_remove(struct ast_sorcery_wizard *interface,
  540. const struct ast_sorcery_wizard_observer *callbacks)
  541. {
  542. RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
  543. interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
  544. ao2_cleanup);
  545. if (wizard) {
  546. ao2_callback(wizard->observers, OBJ_NODATA | OBJ_UNLINK, sorcery_generic_observer_remove, (void *)callbacks);
  547. }
  548. }
  549. /*! \brief Destructor called when sorcery structure is destroyed */
  550. static void sorcery_destructor(void *obj)
  551. {
  552. struct ast_sorcery *sorcery = obj;
  553. if (sorcery->observers) {
  554. NOTIFY_GLOBAL_OBSERVERS(observers, instance_destroying, sorcery->module_name, sorcery);
  555. }
  556. ao2_cleanup(sorcery->observers);
  557. ao2_cleanup(sorcery->types);
  558. }
  559. /*! \brief Hashing function for sorcery types */
  560. static int sorcery_type_hash(const void *obj, const int flags)
  561. {
  562. const struct ast_sorcery_object_type *object;
  563. const char *key;
  564. switch (flags & OBJ_SEARCH_MASK) {
  565. case OBJ_SEARCH_KEY:
  566. key = obj;
  567. break;
  568. case OBJ_SEARCH_OBJECT:
  569. object = obj;
  570. key = object->name;
  571. break;
  572. default:
  573. ast_assert(0);
  574. return 0;
  575. }
  576. return ast_str_hash(key);
  577. }
  578. /*! \brief Comparator function for sorcery types */
  579. static int sorcery_type_cmp(void *obj, void *arg, int flags)
  580. {
  581. const struct ast_sorcery_object_type *object_left = obj;
  582. const struct ast_sorcery_object_type *object_right = arg;
  583. const char *right_key = arg;
  584. int cmp;
  585. switch (flags & OBJ_SEARCH_MASK) {
  586. case OBJ_SEARCH_OBJECT:
  587. right_key = object_right->name;
  588. /* Fall through */
  589. case OBJ_SEARCH_KEY:
  590. cmp = strcmp(object_left->name, right_key);
  591. break;
  592. case OBJ_SEARCH_PARTIAL_KEY:
  593. cmp = strncmp(object_left->name, right_key, strlen(right_key));
  594. break;
  595. default:
  596. cmp = 0;
  597. break;
  598. }
  599. if (cmp) {
  600. return 0;
  601. }
  602. return CMP_MATCH;
  603. }
  604. struct ast_sorcery *__ast_sorcery_open(const char *module_name)
  605. {
  606. struct ast_sorcery *sorcery;
  607. ast_assert(module_name != NULL);
  608. ao2_wrlock(instances);
  609. if ((sorcery = ao2_find(instances, module_name, OBJ_SEARCH_KEY | OBJ_NOLOCK))) {
  610. goto done;
  611. }
  612. if (!(sorcery = ao2_alloc(sizeof(*sorcery) + strlen(module_name) + 1, sorcery_destructor))) {
  613. goto done;
  614. }
  615. if (!(sorcery->types = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, TYPE_BUCKETS, sorcery_type_hash, sorcery_type_cmp))) {
  616. ao2_ref(sorcery, -1);
  617. sorcery = NULL;
  618. goto done;
  619. }
  620. if (!(sorcery->observers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, NULL, NULL))) {
  621. ao2_ref(sorcery, -1);
  622. sorcery = NULL;
  623. goto done;
  624. }
  625. strcpy(sorcery->module_name, module_name); /* Safe */
  626. if (__ast_sorcery_apply_config(sorcery, module_name, module_name) == AST_SORCERY_APPLY_FAIL) {
  627. ast_log(LOG_ERROR, "Error attempting to apply configuration %s to sorcery.\n", module_name);
  628. ao2_cleanup(sorcery);
  629. sorcery = NULL;
  630. goto done;
  631. }
  632. ao2_link_flags(instances, sorcery, OBJ_NOLOCK);
  633. NOTIFY_GLOBAL_OBSERVERS(observers, instance_created, module_name, sorcery);
  634. done:
  635. ao2_unlock(instances);
  636. return sorcery;
  637. }
  638. /*! \brief Search function for sorcery instances */
  639. struct ast_sorcery *ast_sorcery_retrieve_by_module_name(const char *module_name)
  640. {
  641. return ao2_find(instances, module_name, OBJ_SEARCH_KEY);
  642. }
  643. /*! \brief Destructor function for object types */
  644. static void sorcery_object_type_destructor(void *obj)
  645. {
  646. struct ast_sorcery_object_type *object_type = obj;
  647. ao2_cleanup(object_type->wizards);
  648. ao2_cleanup(object_type->fields);
  649. ao2_cleanup(object_type->observers);
  650. if (object_type->info) {
  651. aco_info_destroy(object_type->info);
  652. ast_free(object_type->info);
  653. }
  654. ast_free(object_type->file);
  655. ast_taskprocessor_unreference(object_type->serializer);
  656. }
  657. /*! \brief Internal function which allocates an object type structure */
  658. static struct ast_sorcery_object_type *sorcery_object_type_alloc(const char *type, const char *module)
  659. {
  660. struct ast_sorcery_object_type *object_type;
  661. char uuid[AST_UUID_STR_LEN];
  662. if (!(object_type = ao2_alloc(sizeof(*object_type), sorcery_object_type_destructor))) {
  663. return NULL;
  664. }
  665. /* Order matters for object wizards */
  666. if (!(object_type->wizards = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, sorcery_wizard_cmp))) {
  667. ao2_ref(object_type, -1);
  668. return NULL;
  669. }
  670. if (!(object_type->fields = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, OBJECT_FIELD_BUCKETS,
  671. object_type_field_hash, object_type_field_cmp))) {
  672. ao2_ref(object_type, -1);
  673. return NULL;
  674. }
  675. if (!(object_type->observers = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, 1, NULL, NULL))) {
  676. ao2_ref(object_type, -1);
  677. return NULL;
  678. }
  679. if (!(object_type->info = ast_calloc(1, sizeof(*object_type->info) + 2 * sizeof(object_type->info->files[0])))) {
  680. ao2_ref(object_type, -1);
  681. return NULL;
  682. }
  683. if (!(object_type->file = ast_calloc(1, sizeof(*object_type->file) + 2 * sizeof(object_type->file->types[0])))) {
  684. ao2_ref(object_type, -1);
  685. return NULL;
  686. }
  687. if (!ast_uuid_generate_str(uuid, sizeof(uuid))) {
  688. ao2_ref(object_type, -1);
  689. return NULL;
  690. }
  691. if (!(object_type->serializer = ast_threadpool_serializer(uuid, threadpool))) {
  692. ao2_ref(object_type, -1);
  693. return NULL;
  694. }
  695. object_type->info->files[0] = object_type->file;
  696. object_type->info->files[1] = NULL;
  697. object_type->info->module = module;
  698. ast_copy_string(object_type->name, type, sizeof(object_type->name));
  699. return object_type;
  700. }
  701. /*! \brief Object wizard destructor */
  702. static void sorcery_object_wizard_destructor(void *obj)
  703. {
  704. struct ast_sorcery_object_wizard *object_wizard = obj;
  705. if (object_wizard->data) {
  706. object_wizard->wizard->callbacks.close(object_wizard->data);
  707. }
  708. if (object_wizard->wizard) {
  709. ast_module_unref(object_wizard->wizard->callbacks.module);
  710. }
  711. ao2_cleanup(object_wizard->wizard);
  712. }
  713. /*! \brief Internal function which creates an object type and adds a wizard mapping */
  714. enum ast_sorcery_apply_result __ast_sorcery_apply_wizard_mapping(struct ast_sorcery *sorcery,
  715. const char *type, const char *module, const char *name, const char *data, unsigned int caching)
  716. {
  717. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  718. RAII_VAR(struct ast_sorcery_internal_wizard *, wizard, ao2_find(wizards, name, OBJ_KEY), ao2_cleanup);
  719. RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, ao2_alloc(sizeof(*object_wizard), sorcery_object_wizard_destructor), ao2_cleanup);
  720. int created = 0;
  721. if (!wizard) {
  722. ast_log(LOG_ERROR, "Wizard '%s' could not be applied to object type '%s' as it was not found\n",
  723. name, type);
  724. return AST_SORCERY_APPLY_FAIL;
  725. } else if (!object_wizard) {
  726. return AST_SORCERY_APPLY_FAIL;
  727. }
  728. if (!object_type) {
  729. if (!(object_type = sorcery_object_type_alloc(type, module))) {
  730. return AST_SORCERY_APPLY_FAIL;
  731. }
  732. created = 1;
  733. }
  734. if (!created) {
  735. struct ast_sorcery_wizard *found;
  736. found = ao2_find(object_type->wizards, wizard, OBJ_SEARCH_OBJECT);
  737. if (found) {
  738. ast_debug(1, "Wizard %s already applied to object type %s\n",
  739. wizard->callbacks.name, object_type->name);
  740. ao2_cleanup(found);
  741. return AST_SORCERY_APPLY_DUPLICATE;
  742. }
  743. }
  744. if (wizard->callbacks.open && !(object_wizard->data = wizard->callbacks.open(data))) {
  745. return AST_SORCERY_APPLY_FAIL;
  746. }
  747. ast_module_ref(wizard->callbacks.module);
  748. object_wizard->wizard = ao2_bump(wizard);
  749. object_wizard->caching = caching;
  750. ao2_link(object_type->wizards, object_wizard);
  751. if (created) {
  752. ao2_link(sorcery->types, object_type);
  753. }
  754. NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, wizard_mapped,
  755. sorcery->module_name, sorcery, type, &wizard->callbacks, data, object_wizard->data);
  756. return AST_SORCERY_APPLY_SUCCESS;
  757. }
  758. enum ast_sorcery_apply_result __ast_sorcery_apply_config(struct ast_sorcery *sorcery, const char *name, const char *module)
  759. {
  760. struct ast_flags flags = { 0 };
  761. struct ast_config *config = ast_config_load2("sorcery.conf", "sorcery", flags);
  762. struct ast_variable *mapping;
  763. int res = AST_SORCERY_APPLY_SUCCESS;
  764. if (!config) {
  765. return AST_SORCERY_APPLY_NO_CONFIGURATION;
  766. }
  767. if (config == CONFIG_STATUS_FILEINVALID) {
  768. return AST_SORCERY_APPLY_FAIL;
  769. }
  770. for (mapping = ast_variable_browse(config, name); mapping; mapping = mapping->next) {
  771. RAII_VAR(char *, mapping_name, ast_strdup(mapping->name), ast_free);
  772. RAII_VAR(char *, mapping_value, ast_strdup(mapping->value), ast_free);
  773. char *options = mapping_name;
  774. char *type = strsep(&options, "/");
  775. char *data = mapping_value;
  776. char *wizard = strsep(&data, ",");
  777. unsigned int caching = 0;
  778. /* If no object type or wizard exists just skip, nothing we can do */
  779. if (ast_strlen_zero(type) || ast_strlen_zero(wizard)) {
  780. continue;
  781. }
  782. /* If the wizard is configured as a cache treat it as such */
  783. if (!ast_strlen_zero(options) && strstr(options, "cache")) {
  784. caching = 1;
  785. }
  786. /* Any error immediately causes us to stop */
  787. if (__ast_sorcery_apply_wizard_mapping(sorcery, type, module, wizard, data, caching) == AST_SORCERY_APPLY_FAIL) {
  788. res = AST_SORCERY_APPLY_FAIL;
  789. break;
  790. }
  791. }
  792. ast_config_destroy(config);
  793. return res;
  794. }
  795. enum ast_sorcery_apply_result __ast_sorcery_apply_default(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name, const char *data)
  796. {
  797. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  798. /* Defaults can not be added if any existing mapping exists */
  799. if (object_type) {
  800. return AST_SORCERY_APPLY_DEFAULT_UNNECESSARY;
  801. }
  802. return __ast_sorcery_apply_wizard_mapping(sorcery, type, module, name, data, 0);
  803. }
  804. static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  805. {
  806. return ast_sorcery_object_set_extended(obj, var->name, var->value);
  807. }
  808. static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
  809. {
  810. const struct ast_sorcery_object_details *details = obj;
  811. if (details->object->extended) {
  812. *fields = ast_variables_dup(details->object->extended);
  813. } else {
  814. *fields = NULL;
  815. }
  816. return 0;
  817. }
  818. int __ast_sorcery_object_register(struct ast_sorcery *sorcery, const char *type, unsigned int hidden, unsigned int reloadable, aco_type_item_alloc alloc, sorcery_transform_handler transform, sorcery_apply_handler apply)
  819. {
  820. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  821. if (!object_type || object_type->type.item_alloc) {
  822. return -1;
  823. }
  824. object_type->type.name = object_type->name;
  825. object_type->type.type = ACO_ITEM;
  826. object_type->type.category = ".?";
  827. object_type->type.item_alloc = alloc;
  828. object_type->type.hidden = hidden;
  829. object_type->reloadable = reloadable;
  830. object_type->transform = transform;
  831. object_type->apply = apply;
  832. object_type->file->types[0] = &object_type->type;
  833. object_type->file->types[1] = NULL;
  834. if (aco_info_init(object_type->info)) {
  835. return -1;
  836. }
  837. if (ast_sorcery_object_fields_register(sorcery, type, "^@", sorcery_extended_config_handler, sorcery_extended_fields_handler)) {
  838. return -1;
  839. }
  840. NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, object_type_registered,
  841. sorcery->module_name, sorcery, type);
  842. return 0;
  843. }
  844. void ast_sorcery_object_set_copy_handler(struct ast_sorcery *sorcery, const char *type, sorcery_copy_handler copy)
  845. {
  846. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  847. if (!object_type) {
  848. return;
  849. }
  850. object_type->copy = copy;
  851. }
  852. void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char *type, sorcery_diff_handler diff)
  853. {
  854. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  855. if (!object_type) {
  856. return;
  857. }
  858. object_type->diff = diff;
  859. }
  860. static void sorcery_object_field_destructor(void *obj)
  861. {
  862. struct ast_sorcery_object_field *object_field = obj;
  863. if (object_field->name_regex) {
  864. regfree(object_field->name_regex);
  865. ast_free(object_field->name_regex);
  866. }
  867. }
  868. int ast_sorcery_object_fields_register(struct ast_sorcery *sorcery, const char *type, const char *regex, aco_option_handler config_handler, sorcery_fields_handler sorcery_handler)
  869. {
  870. #define MAX_REGEX_ERROR_LEN 128
  871. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  872. RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
  873. int rc;
  874. if (!object_type || !object_type->type.item_alloc || !config_handler
  875. || !(object_field = ao2_alloc(sizeof(*object_field), sorcery_object_field_destructor))) {
  876. return -1;
  877. }
  878. ast_copy_string(object_field->name, regex, sizeof(object_field->name));
  879. object_field->multiple_handler = sorcery_handler;
  880. if (!(object_field->name_regex = ast_calloc(1, sizeof(regex_t)))) {
  881. return -1;
  882. }
  883. if ((rc = regcomp(object_field->name_regex, regex, REG_EXTENDED | REG_NOSUB))) {
  884. char *regerr = ast_alloca(MAX_REGEX_ERROR_LEN);
  885. regerror(rc, object_field->name_regex, regerr, MAX_REGEX_ERROR_LEN);
  886. ast_log(LOG_ERROR, "Regular expression '%s' failed to compile: %s\n", regex, regerr);
  887. return -1;
  888. }
  889. ao2_link(object_type->fields, object_field);
  890. __aco_option_register(object_type->info, regex, ACO_REGEX, object_type->file->types, "", OPT_CUSTOM_T, config_handler, 0, 1, 0);
  891. return 0;
  892. }
  893. int __ast_sorcery_object_field_register(struct ast_sorcery *sorcery, const char *type, const char *name, const char *default_val, enum aco_option_type opt_type,
  894. aco_option_handler config_handler, sorcery_field_handler sorcery_handler, sorcery_fields_handler multiple_handler, unsigned int flags, unsigned int no_doc, unsigned int alias, size_t argc, ...)
  895. {
  896. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  897. RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
  898. int pos;
  899. va_list args;
  900. if (!strcmp(type, "id") || !object_type || !object_type->type.item_alloc) {
  901. return -1;
  902. }
  903. if (!sorcery_handler) {
  904. sorcery_handler = sorcery_field_default_handler(opt_type);
  905. }
  906. if (!(object_field = ao2_alloc(sizeof(*object_field) + argc * sizeof(object_field->args[0]), NULL))) {
  907. return -1;
  908. }
  909. ast_copy_string(object_field->name, name, sizeof(object_field->name));
  910. object_field->handler = sorcery_handler;
  911. object_field->multiple_handler = multiple_handler;
  912. va_start(args, argc);
  913. for (pos = 0; pos < argc; pos++) {
  914. object_field->args[pos] = va_arg(args, size_t);
  915. }
  916. va_end(args);
  917. if (!alias) {
  918. ao2_link(object_type->fields, object_field);
  919. }
  920. /* TODO: Improve this hack */
  921. if (!argc) {
  922. __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc);
  923. } else if (argc == 1) {
  924. __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
  925. object_field->args[0]);
  926. } else if (argc == 2) {
  927. __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
  928. object_field->args[0], object_field->args[1]);
  929. } else if (argc == 3) {
  930. __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
  931. object_field->args[0], object_field->args[1], object_field->args[2]);
  932. } else {
  933. ast_assert(0); /* The hack... she does us no good for this */
  934. }
  935. return 0;
  936. }
  937. /*! \brief Retrieves whether or not the type is reloadable */
  938. static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
  939. {
  940. RAII_VAR(struct ast_sorcery_object_type *, object_type,
  941. ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  942. return object_type && object_type->reloadable;
  943. }
  944. static int sorcery_wizard_load(void *obj, void *arg, int flags)
  945. {
  946. struct ast_sorcery_object_wizard *wizard = obj;
  947. struct sorcery_load_details *details = arg;
  948. void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
  949. load = !details->reload ? wizard->wizard->callbacks.load : wizard->wizard->callbacks.reload;
  950. if (load) {
  951. NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loading,
  952. wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
  953. load(wizard->data, details->sorcery, details->type);
  954. NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loaded,
  955. wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
  956. }
  957. return 0;
  958. }
  959. /*! \brief Destructor for observer invocation */
  960. static void sorcery_observer_invocation_destroy(void *obj)
  961. {
  962. struct sorcery_observer_invocation *invocation = obj;
  963. ao2_cleanup(invocation->object_type);
  964. ao2_cleanup(invocation->object);
  965. }
  966. /*! \brief Allocator function for observer invocation */
  967. static struct sorcery_observer_invocation *sorcery_observer_invocation_alloc(struct ast_sorcery_object_type *object_type, void *object)
  968. {
  969. struct sorcery_observer_invocation *invocation = ao2_alloc(sizeof(*invocation), sorcery_observer_invocation_destroy);
  970. if (!invocation) {
  971. return NULL;
  972. }
  973. ao2_ref(object_type, +1);
  974. invocation->object_type = object_type;
  975. if (object) {
  976. ao2_ref(object, +1);
  977. invocation->object = object;
  978. }
  979. return invocation;
  980. }
  981. /*! \brief Internal callback function which notifies an individual observer that an object type has been loaded */
  982. static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
  983. {
  984. const struct ast_sorcery_object_type_observer *observer = obj;
  985. if (observer->callbacks->loaded) {
  986. observer->callbacks->loaded(arg);
  987. }
  988. return 0;
  989. }
  990. /*! \brief Internal callback function which notifies observers that an object type has been loaded */
  991. static int sorcery_observers_notify_loaded(void *data)
  992. {
  993. struct sorcery_observer_invocation *invocation = data;
  994. ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_loaded, invocation->object_type->name);
  995. ao2_cleanup(invocation);
  996. return 0;
  997. }
  998. static int sorcery_object_load(void *obj, void *arg, int flags)
  999. {
  1000. struct ast_sorcery_object_type *type = obj;
  1001. struct sorcery_load_details *details = arg;
  1002. if (!type->type.item_alloc) {
  1003. return 0;
  1004. }
  1005. details->type = type->name;
  1006. if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
  1007. ast_log(LOG_NOTICE, "Type '%s' is not reloadable, maintaining previous values\n",
  1008. details->type);
  1009. return 0;
  1010. }
  1011. NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loading,
  1012. details->sorcery->module_name, details->sorcery, type->name, details->reload);
  1013. ao2_callback(type->wizards, OBJ_NODATA, sorcery_wizard_load, details);
  1014. NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loaded,
  1015. details->sorcery->module_name, details->sorcery, type->name, details->reload);
  1016. if (ao2_container_count(type->observers)) {
  1017. struct sorcery_observer_invocation *invocation;
  1018. invocation = sorcery_observer_invocation_alloc(type, NULL);
  1019. if (invocation
  1020. && ast_taskprocessor_push(type->serializer, sorcery_observers_notify_loaded,
  1021. invocation)) {
  1022. ao2_cleanup(invocation);
  1023. }
  1024. }
  1025. return 0;
  1026. }
  1027. void ast_sorcery_load(const struct ast_sorcery *sorcery)
  1028. {
  1029. struct sorcery_load_details details = {
  1030. .sorcery = sorcery,
  1031. .reload = 0,
  1032. };
  1033. NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
  1034. sorcery->module_name, sorcery, 0);
  1035. ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
  1036. NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loaded,
  1037. sorcery->module_name, sorcery, 0);
  1038. }
  1039. void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
  1040. {
  1041. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  1042. struct sorcery_load_details details = {
  1043. .sorcery = sorcery,
  1044. .reload = 0,
  1045. };
  1046. if (!object_type) {
  1047. return;
  1048. }
  1049. sorcery_object_load(object_type, &details, 0);
  1050. }
  1051. void ast_sorcery_reload(const struct ast_sorcery *sorcery)
  1052. {
  1053. struct sorcery_load_details details = {
  1054. .sorcery = sorcery,
  1055. .reload = 1,
  1056. };
  1057. NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
  1058. sorcery->module_name, sorcery, 1);
  1059. ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
  1060. NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loaded,
  1061. sorcery->module_name, sorcery, 1);
  1062. }
  1063. void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
  1064. {
  1065. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  1066. struct sorcery_load_details details = {
  1067. .sorcery = sorcery,
  1068. .reload = 1,
  1069. };
  1070. if (!object_type) {
  1071. return;
  1072. }
  1073. sorcery_object_load(object_type, &details, 0);
  1074. }
  1075. void ast_sorcery_ref(struct ast_sorcery *sorcery)
  1076. {
  1077. ao2_ref(sorcery, +1);
  1078. }
  1079. static struct ast_variable *get_single_field_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
  1080. {
  1081. struct ast_variable *tmp = NULL;
  1082. char *buf = NULL;
  1083. if (!object_field->handler) {
  1084. return NULL;
  1085. }
  1086. if (!(object_field->handler(object, object_field->args, &buf))) {
  1087. tmp = ast_variable_new(object_field->name, S_OR(buf, ""), "");
  1088. }
  1089. ast_free(buf);
  1090. return tmp;
  1091. }
  1092. static struct ast_variable *get_multiple_fields_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
  1093. {
  1094. struct ast_variable *tmp = NULL;
  1095. if (!object_field->multiple_handler) {
  1096. return NULL;
  1097. }
  1098. if (object_field->multiple_handler(object, &tmp)) {
  1099. ast_variables_destroy(tmp);
  1100. tmp = NULL;
  1101. }
  1102. return tmp;
  1103. }
  1104. struct ast_variable *ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery,
  1105. const void *object, enum ast_sorcery_field_handler_flags flags)
  1106. {
  1107. const struct ast_sorcery_object_details *details = object;
  1108. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
  1109. struct ao2_iterator i;
  1110. struct ast_sorcery_object_field *object_field;
  1111. struct ast_variable *head = NULL;
  1112. struct ast_variable *tail = NULL;
  1113. if (!object_type) {
  1114. return NULL;
  1115. }
  1116. i = ao2_iterator_init(object_type->fields, 0);
  1117. for (; (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
  1118. struct ast_variable *tmp;
  1119. switch (flags) {
  1120. case AST_HANDLER_PREFER_LIST:
  1121. if ((tmp = get_multiple_fields_as_var_list(object, object_field)) ||
  1122. (tmp = get_single_field_as_var_list(object, object_field))) {
  1123. break;
  1124. }
  1125. continue;
  1126. case AST_HANDLER_PREFER_STRING:
  1127. if ((tmp = get_single_field_as_var_list(object, object_field)) ||
  1128. (tmp = get_multiple_fields_as_var_list(object, object_field))) {
  1129. break;
  1130. }
  1131. continue;
  1132. case AST_HANDLER_ONLY_LIST:
  1133. if ((tmp = get_multiple_fields_as_var_list(object, object_field))) {
  1134. break;
  1135. }
  1136. continue;
  1137. case AST_HANDLER_ONLY_STRING:
  1138. if ((tmp = get_single_field_as_var_list(object, object_field))) {
  1139. break;
  1140. }
  1141. continue;
  1142. default:
  1143. continue;
  1144. }
  1145. tail = ast_variable_list_append_hint(&head, tail, tmp);
  1146. }
  1147. ao2_iterator_destroy(&i);
  1148. return head;
  1149. }
  1150. struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object)
  1151. {
  1152. const struct ast_sorcery_object_details *details = object;
  1153. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
  1154. struct ao2_iterator i;
  1155. struct ast_sorcery_object_field *object_field;
  1156. struct ast_json *json = ast_json_object_create();
  1157. int res = 0;
  1158. if (!object_type || !json) {
  1159. return NULL;
  1160. }
  1161. i = ao2_iterator_init(object_type->fields, 0);
  1162. for (; !res && (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
  1163. if (object_field->multiple_handler) {
  1164. struct ast_variable *tmp = NULL;
  1165. struct ast_variable *field;
  1166. if ((res = object_field->multiple_handler(object, &tmp))) {
  1167. ast_variables_destroy(tmp);
  1168. ao2_ref(object_field, -1);
  1169. break;
  1170. }
  1171. for (field = tmp; field; field = field->next) {
  1172. struct ast_json *value = ast_json_string_create(field->value);
  1173. if (!value || ast_json_object_set(json, field->name, value)) {
  1174. res = -1;
  1175. break;
  1176. }
  1177. }
  1178. ast_variables_destroy(tmp);
  1179. } else if (object_field->handler) {
  1180. char *buf = NULL;
  1181. struct ast_json *value = NULL;
  1182. if ((res = object_field->handler(object, object_field->args, &buf))
  1183. || !(value = ast_json_string_create(buf))
  1184. || ast_json_object_set(json, object_field->name, value)) {
  1185. res = -1;
  1186. }
  1187. ast_free(buf);
  1188. } else {
  1189. continue;
  1190. }
  1191. }
  1192. ao2_iterator_destroy(&i);
  1193. /* If any error occurs we destroy the JSON object so a partial objectset is not returned */
  1194. if (res) {
  1195. ast_json_unref(json);
  1196. json = NULL;
  1197. }
  1198. return json;
  1199. }
  1200. int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
  1201. {
  1202. const struct ast_sorcery_object_details *details = object;
  1203. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
  1204. RAII_VAR(struct ast_variable *, transformed, NULL, ast_variables_destroy);
  1205. struct ast_variable *field;
  1206. int res = 0;
  1207. if (!object_type) {
  1208. return -1;
  1209. }
  1210. if (object_type->transform && (transformed = object_type->transform(objectset))) {
  1211. field = transformed;
  1212. } else {
  1213. field = objectset;
  1214. }
  1215. for (; field; field = field->next) {
  1216. if ((res = aco_process_var(&object_type->type, details->object->id, field, object))) {
  1217. break;
  1218. }
  1219. }
  1220. if (!res && object_type->apply) {
  1221. res = object_type->apply(sorcery, object);
  1222. }
  1223. return res;
  1224. }
  1225. int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
  1226. {
  1227. const struct ast_variable *field;
  1228. int res = 0;
  1229. *changes = NULL;
  1230. /* Unless the ast_variable list changes when examined... it can't differ from itself */
  1231. if (original == modified) {
  1232. return 0;
  1233. }
  1234. for (field = modified; field; field = field->next) {
  1235. const char *old_value = ast_variable_find_in_list(original, field->name);
  1236. if (!old_value || strcmp(old_value, field->value)) {
  1237. struct ast_variable *tmp;
  1238. if (!(tmp = ast_variable_new(field->name, field->value, ""))) {
  1239. res = -1;
  1240. break;
  1241. }
  1242. tmp->next = *changes;
  1243. *changes = tmp;
  1244. }
  1245. }
  1246. /* If an error occurred do not return a partial changeset */
  1247. if (res) {
  1248. ast_variables_destroy(*changes);
  1249. *changes = NULL;
  1250. }
  1251. return res;
  1252. }
  1253. static void sorcery_object_destructor(void *object)
  1254. {
  1255. struct ast_sorcery_object_details *details = object;
  1256. if (details->object->destructor) {
  1257. details->object->destructor(object);
  1258. }
  1259. ast_variables_destroy(details->object->extended);
  1260. ast_free(details->object->id);
  1261. }
  1262. void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
  1263. {
  1264. void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
  1265. struct ast_sorcery_object_details *details = object;
  1266. if (!object) {
  1267. return NULL;
  1268. }
  1269. details->object = object + size;
  1270. details->object->destructor = destructor;
  1271. return object;
  1272. }
  1273. void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
  1274. {
  1275. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  1276. struct ast_sorcery_object_details *details;
  1277. if (!object_type || !object_type->type.item_alloc ||
  1278. !(details = object_type->type.item_alloc(id))) {
  1279. return NULL;
  1280. }
  1281. if (ast_strlen_zero(id)) {
  1282. char uuid[AST_UUID_STR_LEN];
  1283. ast_uuid_generate_str(uuid, sizeof(uuid));
  1284. details->object->id = ast_strdup(uuid);
  1285. } else {
  1286. details->object->id = ast_strdup(id);
  1287. }
  1288. ast_copy_string(details->object->type, type, sizeof(details->object->type));
  1289. if (aco_set_defaults(&object_type->type, id, details)) {
  1290. ao2_ref(details, -1);
  1291. return NULL;
  1292. }
  1293. return details;
  1294. }
  1295. void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
  1296. {
  1297. const struct ast_sorcery_object_details *details = object;
  1298. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
  1299. struct ast_sorcery_object_details *copy = ast_sorcery_alloc(sorcery, details->object->type, details->object->id);
  1300. RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy);
  1301. int res = 0;
  1302. if (!copy) {
  1303. return NULL;
  1304. } else if (object_type->copy) {
  1305. res = object_type->copy(object, copy);
  1306. } else if ((objectset = ast_sorcery_objectset_create(sorcery, object))) {
  1307. res = ast_sorcery_objectset_apply(sorcery, copy, objectset);
  1308. } else {
  1309. /* No native copy available and could not create an objectset, this copy has failed */
  1310. res = -1;
  1311. }
  1312. if (res) {
  1313. ao2_cleanup(copy);
  1314. copy = NULL;
  1315. }
  1316. return copy;
  1317. }
  1318. int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
  1319. {
  1320. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, ast_sorcery_object_get_type(original), OBJ_KEY), ao2_cleanup);
  1321. *changes = NULL;
  1322. if (strcmp(ast_sorcery_object_get_type(original), ast_sorcery_object_get_type(modified))) {
  1323. return -1;
  1324. }
  1325. if (original == modified) {
  1326. return 0;
  1327. } else if (!object_type->diff) {
  1328. RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
  1329. RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
  1330. objectset1 = ast_sorcery_objectset_create(sorcery, original);
  1331. objectset2 = ast_sorcery_objectset_create(sorcery, modified);
  1332. return ast_sorcery_changeset_create(objectset1, objectset2, changes);
  1333. } else {
  1334. return object_type->diff(original, modified, changes);
  1335. }
  1336. }
  1337. /*! \brief Structure used when calling create, update, or delete */
  1338. struct sorcery_details {
  1339. /*! \brief Pointer to the sorcery instance */
  1340. const struct ast_sorcery *sorcery;
  1341. /*! \brief Pointer to the object itself */
  1342. void *obj;
  1343. };
  1344. /*! \brief Internal function used to create an object in caching wizards */
  1345. static int sorcery_cache_create(void *obj, void *arg, int flags)
  1346. {
  1347. const struct ast_sorcery_object_wizard *object_wizard = obj;
  1348. const struct sorcery_details *details = arg;
  1349. if (!object_wizard->caching || !object_wizard->wizard->callbacks.create) {
  1350. return 0;
  1351. }
  1352. object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj);
  1353. return 0;
  1354. }
  1355. void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
  1356. {
  1357. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  1358. void *object = NULL;
  1359. struct ao2_iterator i;
  1360. struct ast_sorcery_object_wizard *wizard;
  1361. unsigned int cached = 0;
  1362. if (!object_type || ast_strlen_zero(id)) {
  1363. return NULL;
  1364. }
  1365. i = ao2_iterator_init(object_type->wizards, 0);
  1366. for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
  1367. if (wizard->wizard->callbacks.retrieve_id &&
  1368. !(object = wizard->wizard->callbacks.retrieve_id(sorcery, wizard->data, object_type->name, id))) {
  1369. continue;
  1370. }
  1371. cached = wizard->caching;
  1372. ao2_ref(wizard, -1);
  1373. break;
  1374. }
  1375. ao2_iterator_destroy(&i);
  1376. if (!cached && object) {
  1377. ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
  1378. }
  1379. return object;
  1380. }
  1381. void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
  1382. {
  1383. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  1384. void *object = NULL;
  1385. struct ao2_iterator i;
  1386. struct ast_sorcery_object_wizard *wizard;
  1387. unsigned int cached = 0;
  1388. if (!object_type) {
  1389. return NULL;
  1390. }
  1391. /* If returning multiple objects create a container to store them in */
  1392. if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
  1393. if (!(object = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
  1394. return NULL;
  1395. }
  1396. }
  1397. /* Inquire with the available wizards for retrieval */
  1398. i = ao2_iterator_init(object_type->wizards, 0);
  1399. for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
  1400. if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
  1401. if (wizard->wizard->callbacks.retrieve_multiple) {
  1402. wizard->wizard->callbacks.retrieve_multiple(sorcery, wizard->data, object_type->name, object, fields);
  1403. }
  1404. } else if (fields && wizard->wizard->callbacks.retrieve_fields) {
  1405. if (wizard->wizard->callbacks.retrieve_fields) {
  1406. object = wizard->wizard->callbacks.retrieve_fields(sorcery, wizard->data, object_type->name, fields);
  1407. }
  1408. }
  1409. if ((flags & AST_RETRIEVE_FLAG_MULTIPLE) || !object) {
  1410. continue;
  1411. }
  1412. cached = wizard->caching;
  1413. ao2_ref(wizard, -1);
  1414. break;
  1415. }
  1416. ao2_iterator_destroy(&i);
  1417. /* If we are returning a single object and it came from a non-cache source create it in any caches */
  1418. if (!(flags & AST_RETRIEVE_FLAG_MULTIPLE) && !cached && object) {
  1419. ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
  1420. }
  1421. return object;
  1422. }
  1423. struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
  1424. {
  1425. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  1426. struct ao2_container *objects;
  1427. struct ao2_iterator i;
  1428. struct ast_sorcery_object_wizard *wizard;
  1429. if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
  1430. return NULL;
  1431. }
  1432. i = ao2_iterator_init(object_type->wizards, 0);
  1433. for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
  1434. if (!wizard->wizard->callbacks.retrieve_regex) {
  1435. continue;
  1436. }
  1437. wizard->wizard->callbacks.retrieve_regex(sorcery, wizard->data, object_type->name, objects, regex);
  1438. }
  1439. ao2_iterator_destroy(&i);
  1440. return objects;
  1441. }
  1442. /*! \brief Internal function which returns if the wizard has created the object */
  1443. static int sorcery_wizard_create(void *obj, void *arg, int flags)
  1444. {
  1445. const struct ast_sorcery_object_wizard *object_wizard = obj;
  1446. const struct sorcery_details *details = arg;
  1447. if (!object_wizard->wizard->callbacks.create) {
  1448. ast_assert(0);
  1449. ast_log(LOG_ERROR, "Sorcery wizard '%s' doesn't contain a 'create' virtual function.\n",
  1450. object_wizard->wizard->callbacks.name);
  1451. return 0;
  1452. }
  1453. return (!object_wizard->caching && !object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj)) ? CMP_MATCH | CMP_STOP : 0;
  1454. }
  1455. /*! \brief Internal callback function which notifies an individual observer that an object has been created */
  1456. static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
  1457. {
  1458. const struct ast_sorcery_object_type_observer *observer = obj;
  1459. if (observer->callbacks->created) {
  1460. observer->callbacks->created(arg);
  1461. }
  1462. return 0;
  1463. }
  1464. /*! \brief Internal callback function which notifies observers that an object has been created */
  1465. static int sorcery_observers_notify_create(void *data)
  1466. {
  1467. struct sorcery_observer_invocation *invocation = data;
  1468. ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_create, invocation->object);
  1469. ao2_cleanup(invocation);
  1470. return 0;
  1471. }
  1472. int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
  1473. {
  1474. const struct ast_sorcery_object_details *details = object;
  1475. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
  1476. RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
  1477. struct sorcery_details sdetails = {
  1478. .sorcery = sorcery,
  1479. .obj = object,
  1480. };
  1481. if (!object_type) {
  1482. return -1;
  1483. }
  1484. if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_create, &sdetails)) &&
  1485. ao2_container_count(object_type->observers)) {
  1486. struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
  1487. if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_create, invocation)) {
  1488. ao2_cleanup(invocation);
  1489. }
  1490. }
  1491. return object_wizard ? 0 : -1;
  1492. }
  1493. /*! \brief Internal callback function which notifies an individual observer that an object has been updated */
  1494. static int sorcery_observer_notify_update(void *obj, void *arg, int flags)
  1495. {
  1496. const struct ast_sorcery_object_type_observer *observer = obj;
  1497. if (observer->callbacks->updated) {
  1498. observer->callbacks->updated(arg);
  1499. }
  1500. return 0;
  1501. }
  1502. /*! \brief Internal callback function which notifies observers that an object has been updated */
  1503. static int sorcery_observers_notify_update(void *data)
  1504. {
  1505. struct sorcery_observer_invocation *invocation = data;
  1506. ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_update, invocation->object);
  1507. ao2_cleanup(invocation);
  1508. return 0;
  1509. }
  1510. /*! \brief Internal function which returns if a wizard has updated the object */
  1511. static int sorcery_wizard_update(void *obj, void *arg, int flags)
  1512. {
  1513. const struct ast_sorcery_object_wizard *object_wizard = obj;
  1514. const struct sorcery_details *details = arg;
  1515. return (object_wizard->wizard->callbacks.update && !object_wizard->wizard->callbacks.update(details->sorcery, object_wizard->data, details->obj) &&
  1516. !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
  1517. }
  1518. int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
  1519. {
  1520. const struct ast_sorcery_object_details *details = object;
  1521. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
  1522. RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
  1523. struct sorcery_details sdetails = {
  1524. .sorcery = sorcery,
  1525. .obj = object,
  1526. };
  1527. if (!object_type) {
  1528. return -1;
  1529. }
  1530. if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_update, &sdetails)) &&
  1531. ao2_container_count(object_type->observers)) {
  1532. struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
  1533. if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_update, invocation)) {
  1534. ao2_cleanup(invocation);
  1535. }
  1536. }
  1537. return object_wizard ? 0 : -1;
  1538. }
  1539. /*! \brief Internal callback function which notifies an individual observer that an object has been deleted */
  1540. static int sorcery_observer_notify_delete(void *obj, void *arg, int flags)
  1541. {
  1542. const struct ast_sorcery_object_type_observer *observer = obj;
  1543. if (observer->callbacks->deleted) {
  1544. observer->callbacks->deleted(arg);
  1545. }
  1546. return 0;
  1547. }
  1548. /*! \brief Internal callback function which notifies observers that an object has been deleted */
  1549. static int sorcery_observers_notify_delete(void *data)
  1550. {
  1551. struct sorcery_observer_invocation *invocation = data;
  1552. ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_delete, invocation->object);
  1553. ao2_cleanup(invocation);
  1554. return 0;
  1555. }
  1556. /*! \brief Internal function which returns if a wizard has deleted the object */
  1557. static int sorcery_wizard_delete(void *obj, void *arg, int flags)
  1558. {
  1559. const struct ast_sorcery_object_wizard *object_wizard = obj;
  1560. const struct sorcery_details *details = arg;
  1561. return (object_wizard->wizard->callbacks.delete && !object_wizard->wizard->callbacks.delete(details->sorcery, object_wizard->data, details->obj) &&
  1562. !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
  1563. }
  1564. int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
  1565. {
  1566. const struct ast_sorcery_object_details *details = object;
  1567. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
  1568. RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
  1569. struct sorcery_details sdetails = {
  1570. .sorcery = sorcery,
  1571. .obj = object,
  1572. };
  1573. if (!object_type) {
  1574. return -1;
  1575. }
  1576. if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_delete, &sdetails)) &&
  1577. ao2_container_count(object_type->observers)) {
  1578. struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
  1579. if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_delete, invocation)) {
  1580. ao2_cleanup(invocation);
  1581. }
  1582. }
  1583. return object_wizard ? 0 : -1;
  1584. }
  1585. void ast_sorcery_unref(struct ast_sorcery *sorcery)
  1586. {
  1587. if (sorcery) {
  1588. /* One ref for what we just released, the other for the instances container. */
  1589. ao2_wrlock(instances);
  1590. if (ao2_ref(sorcery, -1) == 2) {
  1591. ao2_unlink_flags(instances, sorcery, OBJ_NOLOCK);
  1592. }
  1593. ao2_unlock(instances);
  1594. }
  1595. }
  1596. const char *ast_sorcery_object_get_id(const void *object)
  1597. {
  1598. const struct ast_sorcery_object_details *details = object;
  1599. return details->object->id;
  1600. }
  1601. const char *ast_sorcery_object_get_type(const void *object)
  1602. {
  1603. const struct ast_sorcery_object_details *details = object;
  1604. return details->object->type;
  1605. }
  1606. const char *ast_sorcery_object_get_extended(const void *object, const char *name)
  1607. {
  1608. const struct ast_sorcery_object_details *details = object;
  1609. struct ast_variable *field;
  1610. for (field = details->object->extended; field; field = field->next) {
  1611. if (!strcmp(field->name + 1, name)) {
  1612. return field->value;
  1613. }
  1614. }
  1615. return NULL;
  1616. }
  1617. int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value)
  1618. {
  1619. RAII_VAR(struct ast_variable *, field, NULL, ast_variables_destroy);
  1620. struct ast_variable *extended = ast_variable_new(name, value, ""), *previous = NULL;
  1621. const struct ast_sorcery_object_details *details = object;
  1622. if (!extended) {
  1623. return -1;
  1624. }
  1625. for (field = details->object->extended; field; previous = field, field = field->next) {
  1626. if (!strcmp(field->name, name)) {
  1627. if (previous) {
  1628. previous->next = field->next;
  1629. } else {
  1630. details->object->extended = field->next;
  1631. }
  1632. field->next = NULL;
  1633. break;
  1634. }
  1635. }
  1636. extended->next = details->object->extended;
  1637. details->object->extended = extended;
  1638. return 0;
  1639. }
  1640. int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
  1641. {
  1642. RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
  1643. struct ast_sorcery_object_type_observer *observer;
  1644. int res;
  1645. if (!object_type || !callbacks) {
  1646. return -1;
  1647. }
  1648. if (!(observer = ao2_alloc(sizeof(*observer), NULL))) {
  1649. return -1;
  1650. }
  1651. observer->callbacks = callbacks;
  1652. res = 0;
  1653. if (!ao2_link(object_type->observers, observer)) {
  1654. res = -1;
  1655. }
  1656. ao2_ref(observer, -1);
  1657. return res;
  1658. }
  1659. /*! \brief Internal callback function for removing an observer */
  1660. static int sorcery_observer_remove(void *obj, void *arg, int flags)
  1661. {
  1662. const struct ast_sorcery_object_type_observer *observer = obj;
  1663. return (observer->callbacks == arg) ? CMP_MATCH | CMP_STOP : 0;
  1664. }
  1665. void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
  1666. {
  1667. RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
  1668. struct ast_sorcery_observer *cbs = (struct ast_sorcery_observer *) callbacks;/* Remove const for traversal. */
  1669. if (!sorcery) {
  1670. return;
  1671. }
  1672. object_type = ao2_find(sorcery->types, type, OBJ_KEY);
  1673. if (!object_type) {
  1674. return;
  1675. }
  1676. ao2_callback(object_type->observers, OBJ_NODATA | OBJ_UNLINK,
  1677. sorcery_observer_remove, cbs);
  1678. }
  1679. int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
  1680. {
  1681. const char *right_key = arg;
  1682. int cmp;
  1683. switch (flags & OBJ_SEARCH_MASK) {
  1684. case OBJ_SEARCH_OBJECT:
  1685. right_key = ast_sorcery_object_get_id(arg);
  1686. /* Fall through */
  1687. case OBJ_SEARCH_KEY:
  1688. cmp = strcmp(ast_sorcery_object_get_id(obj), right_key);
  1689. break;
  1690. case OBJ_SEARCH_PARTIAL_KEY:
  1691. cmp = strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key));
  1692. break;
  1693. default:
  1694. cmp = 0;
  1695. break;
  1696. }
  1697. return cmp;
  1698. }
  1699. int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
  1700. {
  1701. const char *right_key = arg;
  1702. int cmp = 0;
  1703. switch (flags & OBJ_SEARCH_MASK) {
  1704. case OBJ_SEARCH_OBJECT:
  1705. right_key = ast_sorcery_object_get_id(arg);
  1706. /* Fall through */
  1707. case OBJ_SEARCH_KEY:
  1708. if (strcmp(ast_sorcery_object_get_id(obj), right_key) == 0) {
  1709. cmp = CMP_MATCH | CMP_STOP;
  1710. }
  1711. break;
  1712. case OBJ_SEARCH_PARTIAL_KEY:
  1713. if (strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key)) == 0) {
  1714. cmp = CMP_MATCH;
  1715. }
  1716. break;
  1717. default:
  1718. cmp = 0;
  1719. break;
  1720. }
  1721. return cmp;
  1722. }
  1723. int ast_sorcery_object_id_hash(const void *obj, int flags) {
  1724. if (flags & OBJ_SEARCH_OBJECT) {
  1725. return ast_str_hash(ast_sorcery_object_get_id(obj));
  1726. } else if (flags & OBJ_SEARCH_KEY) {
  1727. return ast_str_hash(obj);
  1728. }
  1729. return -1;
  1730. }
  1731. struct ast_sorcery_object_type *ast_sorcery_get_object_type(const struct ast_sorcery *sorcery,
  1732. const char *type)
  1733. {
  1734. return ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
  1735. }
  1736. static int is_registered_cb(void *obj, void *arg, int flags)
  1737. {
  1738. struct ast_sorcery_object_field *object_field = obj;
  1739. char *name = arg;
  1740. int rc = 0;
  1741. if (object_field->name_regex
  1742. && !regexec(object_field->name_regex, name, 0, NULL, 0)) {
  1743. rc = CMP_MATCH | CMP_STOP;
  1744. }
  1745. return rc;
  1746. }
  1747. int ast_sorcery_is_object_field_registered(const struct ast_sorcery_object_type *object_type,
  1748. const char *field_name)
  1749. {
  1750. struct ast_sorcery_object_field *object_field;
  1751. int res = 1;
  1752. ast_assert(object_type != NULL);
  1753. object_field = ao2_find(object_type->fields, field_name, OBJ_SEARCH_KEY);
  1754. if (!object_field) {
  1755. object_field = ao2_callback(object_type->fields, 0, is_registered_cb, (char *)field_name);
  1756. }
  1757. if (!object_field) {
  1758. res = 0;
  1759. }
  1760. ao2_cleanup(object_field);
  1761. return res;
  1762. }