sp_var.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. #include "precompile.h"
  2. #include "sp_var.h"
  3. #include "sp_def.h"
  4. #include "sp_svc.h"
  5. #include "sp_dbg_export.h"
  6. #include "sp_iom.h"
  7. #include "sp_cfg.h"
  8. #include "sp_env.h"
  9. #include "sp_rsn.h"
  10. #include "memutil.h"
  11. #include "strutil.h"
  12. #include "list.h"
  13. #include "array.h"
  14. #include "refcnt.h"
  15. #include "iniutil.h"
  16. #define VAR_CMD_CHANGE 0x01
  17. #define VAR_CMD_SUBSCRIBE 0x02
  18. #define VAR_CMD_UNSUBSCRIBE 0x03
  19. struct sp_var_client_t
  20. {
  21. sp_svc_t *svc;
  22. };
  23. static int sp_var_can_write(sp_var_client_t *client, const char *key, sp_cfg_shell_sysevent_t **p_sysevent)
  24. {
  25. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  26. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  27. sp_cfg_shell_sysevent_t *sysevent;
  28. sysevent = sp_cfg_get_sysevent(cfg, key);
  29. if (sysevent) {
  30. int i;
  31. *p_sysevent = sysevent;
  32. for (i = 0; i < sysevent->arr_owner_entity->nelts; ++i) {
  33. sp_cfg_shell_entity_t *ent = ARRAY_IDX(sysevent->arr_owner_entity, i, sp_cfg_shell_entity_t*);
  34. if (ent->idx == sp_svc_get_id(client->svc))
  35. return TRUE;
  36. }
  37. } else {
  38. *p_sysevent = NULL;
  39. }
  40. return FALSE;
  41. }
  42. int sp_var_client_create(sp_svc_t *svc, sp_var_client_t **p_client)
  43. {
  44. sp_var_client_t *client = MALLOC_T(sp_var_client_t);
  45. client->svc = svc;
  46. *p_client = client;
  47. return 0;
  48. }
  49. void sp_var_client_destroy(sp_var_client_t *client)
  50. {
  51. free(client);
  52. }
  53. // str == NULL for delete
  54. int sp_var_client_set(sp_var_client_t *client, const char *key, const char *str, int persist)
  55. {
  56. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  57. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  58. int svc_id = sp_svc_get_id(client->svc);
  59. int rc;
  60. sp_cfg_shell_sysevent_t *sysevent;
  61. char old_value[SP_CFG_MAX_SYSEVT_BUF];
  62. if (!key ) {
  63. sp_dbg_warn("%s invalid argument", __FUNCTION__);
  64. return Error_Null;
  65. }
  66. if (str && strlen(str) >= SP_CFG_MAX_SYSEVT_BUF) {
  67. sp_dbg_warn("%s has exceed max sysevent length!", key);
  68. return Error_Param;
  69. }
  70. if (!sp_var_can_write(client, key, &sysevent)) {
  71. sp_dbg_warn("%s has no write privilege!", __FUNCTION__);
  72. return Error_NoPrivilege;
  73. }
  74. // same value, not trigger change event
  75. if ((str != NULL && strcmp(str, sysevent->init_value) == 0)
  76. || (str == NULL && sysevent->init_value[0] == 0))
  77. return Error_Succeed;
  78. sp_cfg_lock(cfg);
  79. if (str) {
  80. strcpy(old_value, sysevent->init_value);
  81. strcpy(sysevent->init_value, str);
  82. if (persist)
  83. inifile_format_write(cfg->shellvar_ini_path != NULL ? cfg->shellvar_ini_path : cfg->shell_ini_path,
  84. "SysEvent", key, "%s,\"%s\"", sp_cfg_get_entity_by_idx(cfg, svc_id)->name, str);
  85. } else {
  86. sysevent->init_value[0] = 0;
  87. if (persist)
  88. inifile_format_write(cfg->shellvar_ini_path != NULL ? cfg->shellvar_ini_path : cfg->shell_ini_path,
  89. "SysEvent", key, "%s,\"\"", sp_cfg_get_entity_by_idx(cfg, svc_id)->name);
  90. }
  91. sp_cfg_unlock(cfg);
  92. {
  93. iobuffer_t *pkt = iobuffer_create(-1, -1);
  94. iobuffer_write(pkt, IOBUF_T_I4, &svc_id, 0);
  95. iobuffer_write(pkt, IOBUF_T_STR, key, -1);
  96. iobuffer_write(pkt, IOBUF_T_STR, old_value, -1);
  97. iobuffer_write(pkt, IOBUF_T_STR, str, -1);
  98. rc = sp_svc_post(client->svc, SP_SHELL_MOD_ID, SP_SHELL_SVC_ID, SP_PKT_VAR|VAR_CMD_CHANGE, 0, &pkt);
  99. if (rc != 0) {
  100. sp_dbg_warn("%s post SP_PKT_VAR|VAR_CMD_CHANGE failed!", __FUNCTION__);
  101. }
  102. if (pkt)
  103. iobuffer_dec_ref(pkt);
  104. }
  105. return rc;
  106. }
  107. int sp_var_client_get(sp_var_client_t *client, const char *key, char *str, int *n)
  108. {
  109. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  110. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  111. int rc = 0;
  112. sp_cfg_shell_sysevent_t *sysevent;
  113. sysevent = sp_cfg_get_sysevent(cfg, key);
  114. if (!sysevent) {
  115. sp_dbg_warn("%s cannot find sysevent !", key);
  116. return Error_NotExist;
  117. }
  118. if (str) {
  119. int slen;
  120. sp_cfg_lock(cfg);
  121. slen = (int)strlen(sysevent->init_value);
  122. if (*n > slen) {
  123. strcpy(str, sysevent->init_value);
  124. } else {
  125. rc = Error_Bug;
  126. }
  127. sp_cfg_unlock(cfg);
  128. } else {
  129. if (n) {
  130. *n = SP_CFG_MAX_SYSEVT_BUF;
  131. } else {
  132. rc = Error_Bug;
  133. }
  134. }
  135. return rc;
  136. }
  137. int sp_var_client_lock(sp_var_client_t *client)
  138. {
  139. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  140. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  141. sp_cfg_lock(cfg);
  142. return 0;
  143. }
  144. int sp_var_client_unlock(sp_var_client_t *client)
  145. {
  146. sp_iom_t *iom = sp_svc_get_iom(client->svc);
  147. sp_cfg_t *cfg = sp_get_env(iom)->cfg;
  148. sp_cfg_unlock(cfg);
  149. return 0;
  150. }
  151. struct sp_var_listener_t
  152. {
  153. int client_id;
  154. int subcribed;
  155. int enabled;
  156. char *key;
  157. strand_t *strand;
  158. sp_var_on_change on_change;
  159. void *user_data;
  160. void *tag;
  161. sp_svc_t *svc;
  162. DECLARE_REF_COUNT_MEMBER(ref_cnt);
  163. };
  164. DECLARE_REF_COUNT_STATIC(sp_var_listener, sp_var_listener_t)
  165. static void listener_on_pkt_threadpool(threadpool_t *threadpool, void *arg)
  166. {
  167. iobuffer_t *pkt = (iobuffer_t*)arg;
  168. sp_var_listener_t *listener;
  169. sp_svc_t *svc;
  170. int epid;
  171. int pkt_type;
  172. int svc_id;
  173. int pkt_id;
  174. sp_uid_t rsn;
  175. sp_rsn_context_t rsn_ctx;
  176. iobuffer_read(pkt, IOBUF_T_I4, &listener, NULL);
  177. iobuffer_read(pkt, IOBUF_T_I4, &epid, NULL);
  178. iobuffer_read(pkt, IOBUF_T_I4, &svc_id, NULL);
  179. iobuffer_read(pkt, IOBUF_T_I4, &pkt_type, NULL);
  180. iobuffer_read(pkt, IOBUF_T_I4, &pkt_id, NULL);
  181. svc = listener->svc;
  182. rsn = sp_svc_new_runserial(svc);
  183. sp_rsn_context_init_original(rsn, SP_ORIGINAL_T_CALLBACK, &rsn_ctx);
  184. sp_svc_push_runserial_context(svc, &rsn_ctx);
  185. if (listener->subcribed && listener->enabled) {
  186. int var_client_id = pkt_id;
  187. int var_cmd = SP_GET_TYPE(pkt_type);
  188. if (var_cmd == VAR_CMD_CHANGE && listener->subcribed) {
  189. int from_client_id;
  190. char *key = NULL;
  191. iobuffer_format_read(pkt, "4s", &from_client_id, &key);
  192. if (listener->key[0] == '*' || _stricmp(key, listener->key) == 0) {
  193. char *old_value = NULL;
  194. char *new_value = NULL;
  195. iobuffer_format_read(pkt, "ss", &old_value, &new_value);
  196. listener->on_change(listener, key, old_value, new_value, from_client_id, listener->user_data);
  197. if (old_value)
  198. toolkit_free(old_value);
  199. if (new_value)
  200. toolkit_free(new_value);
  201. }
  202. if (key)
  203. toolkit_free(key);
  204. }
  205. }
  206. if (pkt)
  207. iobuffer_dec_ref(pkt);
  208. sp_var_listener_dec_ref(listener); //@
  209. sp_svc_pop_runserial_context(svc);
  210. }
  211. static int listener_on_pkt(sp_svc_t *svc,int epid, int svc_id, int pkt_type, int pkt_id, iobuffer_t **p_pkt, void *user_data)
  212. {
  213. sp_var_listener_t *listener = (sp_var_listener_t *)user_data;
  214. int var_cmd = SP_GET_TYPE(pkt_type);
  215. if (var_cmd == VAR_CMD_CHANGE && listener->subcribed && listener->enabled) {
  216. iobuffer_t *pkt = iobuffer_clone(*p_pkt);
  217. iobuffer_write_head(pkt, IOBUF_T_I4, &pkt_id, 0);
  218. iobuffer_write_head(pkt, IOBUF_T_I4, &pkt_type, 0);
  219. iobuffer_write_head(pkt, IOBUF_T_I4, &svc_id, 0);
  220. iobuffer_write_head(pkt, IOBUF_T_I4, &epid, 0);
  221. iobuffer_write_head(pkt, IOBUF_T_I4, &listener, 0);
  222. sp_var_listener_inc_ref(listener);//@
  223. if (threadpool_queue_workitem(sp_svc_get_threadpool(svc), listener->strand, &listener_on_pkt_threadpool, pkt) < 0) {
  224. sp_var_listener_dec_ref(listener);//@
  225. iobuffer_dec_ref(pkt);
  226. }
  227. }
  228. return TRUE; // continue
  229. }
  230. int sp_var_listener_create(sp_svc_t *svc, const char *key, sp_var_on_change on_change, void *user_data, sp_var_listener_t **p_listener)
  231. {
  232. sp_var_listener_t *listener = MALLOC_T(sp_var_listener_t);
  233. listener->on_change = on_change;
  234. listener->user_data = user_data;
  235. listener->subcribed = 0;
  236. listener->enabled = 1;
  237. listener->strand = strand_create();
  238. listener->key = _strdup(key);
  239. listener->svc = svc;
  240. *p_listener = listener;
  241. return 0;
  242. }
  243. static void __sp_var_listener_destroy(sp_var_listener_t *listener)
  244. {
  245. strand_destroy(listener->strand);
  246. free(listener->key);
  247. free(listener);
  248. }
  249. IMPLEMENT_REF_COUNT_MT_STATIC(sp_var_listener, sp_var_listener_t, ref_cnt, __sp_var_listener_destroy)
  250. void sp_var_listener_destroy(sp_var_listener_t *listener)
  251. {
  252. sp_var_listener_dec_ref(listener);
  253. }
  254. int sp_var_listener_subscribe(sp_var_listener_t *listener)
  255. {
  256. iobuffer_t *pkt;
  257. int rc;
  258. if (listener->subcribed)
  259. return Error_Duplication;
  260. pkt = iobuffer_create(-1, -1);
  261. sp_svc_add_pkt_handler(listener->svc, (int)listener, SP_PKT_VAR, &listener_on_pkt, listener);
  262. iobuffer_write(pkt, IOBUF_T_STR, listener->key, -1);
  263. rc = sp_svc_post(listener->svc, SP_SHELL_MOD_ID, SP_SHELL_SVC_ID,
  264. SP_PKT_VAR|VAR_CMD_SUBSCRIBE, 0, &pkt);
  265. if (rc == 0) {
  266. listener->subcribed = 1;
  267. }
  268. if (pkt)
  269. iobuffer_dec_ref(pkt);
  270. return rc;
  271. }
  272. int sp_var_listener_unsubscribe(sp_var_listener_t *listener)
  273. {
  274. int rc;
  275. if (listener->subcribed) {
  276. iobuffer_t *pkt = iobuffer_create(-1, -1);
  277. iobuffer_write(pkt, IOBUF_T_STR, listener->key, -1);
  278. rc = sp_svc_post(listener->svc, SP_SHELL_MOD_ID, SP_SHELL_SVC_ID,
  279. SP_PKT_VAR|VAR_CMD_UNSUBSCRIBE, 0, &pkt);
  280. if (rc == 0) {
  281. listener->subcribed = 0;
  282. sp_svc_remove_pkt_handler(listener->svc, (int)listener, SP_PKT_VAR);
  283. }
  284. if (pkt)
  285. iobuffer_dec_ref(pkt);
  286. } else {
  287. rc = Error_NotInit;
  288. }
  289. return rc;
  290. }
  291. void sp_var_listener_set_tag(sp_var_listener_t *listener, void *tag)
  292. {
  293. listener->tag = tag;
  294. }
  295. void* sp_var_listener_get_tag(sp_var_listener_t *listener)
  296. {
  297. return listener->tag;
  298. }
  299. int sp_var_listener_enable(sp_var_listener_t *listener, int enabled)
  300. {
  301. int old = listener->enabled;
  302. listener->enabled = enabled;
  303. return old;
  304. }
  305. typedef struct var_listener_entry {
  306. int epid;
  307. int svc_id;
  308. char *key;
  309. int instance;
  310. }var_listener_entry;
  311. struct sp_var_daemon_t
  312. {
  313. CRITICAL_SECTION lock;
  314. array_header_t *arr_listener;
  315. sp_svc_t *svc;
  316. };
  317. static void daemon_lock(sp_var_daemon_t *daemon)
  318. {
  319. EnterCriticalSection(&daemon->lock);
  320. }
  321. static void daemon_unlock(sp_var_daemon_t *daemon)
  322. {
  323. LeaveCriticalSection(&daemon->lock);
  324. }
  325. static int daemon_on_pkt(sp_svc_t *svc,int epid, int svc_id, int pkt_type, int pkt_id, iobuffer_t **p_pkt, void *user_data)
  326. {
  327. sp_var_daemon_t *daemon = (sp_var_daemon_t *)user_data;
  328. int var_cmd = SP_GET_TYPE(pkt_type);
  329. if (var_cmd == VAR_CMD_CHANGE) {
  330. iobuffer_t *pkt = *p_pkt;
  331. int i;
  332. int client_id;
  333. int read_state = iobuffer_get_read_state(pkt);
  334. int write_state = iobuffer_get_write_state(pkt);
  335. char *key = NULL;
  336. iobuffer_format_read(pkt, "4s", &client_id, &key);
  337. iobuffer_restore_read_state(pkt, read_state);
  338. iobuffer_restore_write_state(pkt, write_state);
  339. daemon_lock(daemon);
  340. for (i = 0; i < daemon->arr_listener->nelts; ++i) {
  341. var_listener_entry* tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  342. if (_stricmp(tmp->key, "*")==0 || _stricmp(key, tmp->key) == 0) {
  343. iobuffer_t *copy_pkt;
  344. if (i == daemon->arr_listener->nelts-1) {
  345. copy_pkt = pkt;
  346. pkt =NULL;
  347. } else {
  348. copy_pkt = iobuffer_clone(pkt);
  349. }
  350. sp_svc_post(daemon->svc, tmp->epid, tmp->svc_id, SP_PKT_VAR|VAR_CMD_CHANGE, 0, &copy_pkt);
  351. if (copy_pkt)
  352. iobuffer_dec_ref(copy_pkt);
  353. }
  354. }
  355. daemon_unlock(daemon);
  356. toolkit_free(key);
  357. if (pkt)
  358. iobuffer_dec_ref(pkt);
  359. *p_pkt = NULL;
  360. } else if (var_cmd == VAR_CMD_SUBSCRIBE) {
  361. char *key = NULL;
  362. int i;
  363. int slen;
  364. iobuffer_read(*p_pkt, IOBUF_T_STR, NULL, &slen);
  365. key = malloc(slen+1);
  366. iobuffer_read(*p_pkt, IOBUF_T_STR, key, NULL);
  367. daemon_lock(daemon);
  368. for (i = 0; i < daemon->arr_listener->nelts; ++i) {
  369. var_listener_entry* tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  370. if (tmp->epid == epid && tmp->svc_id == svc_id && _stricmp(key, tmp->key) == 0) {
  371. tmp->instance++;
  372. break;
  373. }
  374. }
  375. if (i == daemon->arr_listener->nelts) {
  376. var_listener_entry* tmp = MALLOC_T(var_listener_entry);
  377. tmp->epid = epid;
  378. tmp->svc_id = svc_id;
  379. tmp->key = key;
  380. key = NULL;
  381. tmp->instance = 1;
  382. ARRAY_PUSH(daemon->arr_listener, var_listener_entry*) = tmp;
  383. }
  384. daemon_unlock(daemon);
  385. if (key)
  386. free(key);
  387. } else if (var_cmd == VAR_CMD_UNSUBSCRIBE) {
  388. char *key = NULL;
  389. int i;
  390. int slen;
  391. iobuffer_read(*p_pkt, IOBUF_T_STR, NULL, &slen);
  392. key = malloc(slen+1);
  393. iobuffer_read(*p_pkt, IOBUF_T_STR, key, NULL);
  394. daemon_lock(daemon);
  395. for (i = 0; i < daemon->arr_listener->nelts; ++i) {
  396. var_listener_entry* tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  397. if (tmp->epid == epid && tmp->svc_id == svc_id && _stricmp(key, tmp->key) == 0) {
  398. tmp->instance--;
  399. if (tmp->instance == 0) {
  400. if (i < daemon->arr_listener->nelts-1)
  401. ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*) = ARRAY_IDX(daemon->arr_listener, daemon->arr_listener->nelts-1, var_listener_entry*);
  402. array_pop(daemon->arr_listener);
  403. free(tmp->key);
  404. free(tmp);
  405. }
  406. break;
  407. }
  408. }
  409. daemon_unlock(daemon);
  410. if (key)
  411. free(key);
  412. } else {
  413. assert(0);
  414. }
  415. return TRUE;
  416. }
  417. static void daemon_on_sys(sp_svc_t *svc,int epid, int state, void *user_data)
  418. {
  419. sp_var_daemon_t *daemon = (sp_var_daemon_t *)user_data;
  420. if (state == BUS_STATE_OFF) {
  421. int i = 0;
  422. daemon_lock(daemon);
  423. while (i < daemon->arr_listener->nelts) {
  424. var_listener_entry* tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  425. if (tmp->epid == epid) {
  426. if (i < daemon->arr_listener->nelts-1)
  427. ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*) = ARRAY_IDX(daemon->arr_listener, daemon->arr_listener->nelts-1, var_listener_entry*);
  428. array_pop(daemon->arr_listener);
  429. free(tmp->key);
  430. free(tmp);
  431. } else {
  432. ++i;
  433. }
  434. }
  435. daemon_unlock(daemon);
  436. }
  437. }
  438. int sp_var_daemon_create(sp_svc_t *svc, sp_var_daemon_t **p_daemon)
  439. {
  440. sp_var_daemon_t *daemon = ZALLOC_T(sp_var_daemon_t);
  441. daemon->svc = svc;
  442. daemon->arr_listener = array_make(3, sizeof(var_listener_entry*));
  443. InitializeCriticalSection(&daemon->lock);
  444. sp_svc_add_pkt_handler(svc, (int)daemon, SP_PKT_VAR, &daemon_on_pkt, daemon);
  445. sp_svc_add_sys_handler(svc, (int)daemon, &daemon_on_sys, daemon);
  446. *p_daemon = daemon;
  447. return 0;
  448. }
  449. void sp_var_daemon_destroy(sp_var_daemon_t *daemon)
  450. {
  451. int i;
  452. for (i = 0; i < daemon->arr_listener->nelts; ++i) {
  453. var_listener_entry *tmp = ARRAY_IDX(daemon->arr_listener, i, var_listener_entry*);
  454. free(tmp->key);
  455. free(tmp);
  456. }
  457. array_free(daemon->arr_listener);
  458. DeleteCriticalSection(&daemon->lock);
  459. sp_svc_remove_pkt_handler(daemon->svc, (int)daemon, SP_PKT_VAR);
  460. sp_svc_remove_sys_handler(daemon->svc, (int)daemon);
  461. free(daemon);
  462. }