ruleparam_db.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  1. /*
  2. * Copyright (c) 2019 Clementine Computing LLC.
  3. *
  4. * This file is part of PopuFare.
  5. *
  6. * PopuFare is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * PopuFare is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with PopuFare. If not, see <https://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include "ruleparam_db.h"
  21. extern int commhub_fd;
  22. struct message_record log_msg;
  23. int ruleparam_db_init( ruleparam_db_ctx *ctx )
  24. {
  25. ctx->n = 0;
  26. ctx->head = NULL;
  27. ctx->sync_counter = 0;
  28. ctx->sync_every_n = 100;
  29. ctx->n_filename_history = 4;
  30. ctx->pos_filename_history = 0;
  31. ctx->seq = 0;
  32. return 0;
  33. }
  34. static int _chomp(char *s)
  35. {
  36. int n;
  37. if (!s)
  38. {
  39. return -1;
  40. }
  41. n = strlen(s);
  42. if (n==0)
  43. return 0;
  44. if (s[n-1] == '\n')
  45. {
  46. s[n-1] = '\0';
  47. return n-1;
  48. }
  49. return n;
  50. }
  51. // In the consistency check, we allocate our own ruleparam_db, so we needed to expose
  52. // this function.
  53. //
  54. passdb_slim_ruleparam *_alloc_ruleparam_db_nod(int id, char *name, char *param)
  55. {
  56. passdb_slim_ruleparam *nod;
  57. nod = (passdb_slim_ruleparam *)malloc(sizeof(passdb_slim_ruleparam));
  58. if (!nod)
  59. {
  60. fprintf(stderr, "_alloc_ruelparam_db_nod malloc failed: %s line %i\n", __FILE__, __LINE__ );
  61. return NULL;
  62. }
  63. nod->id = id;
  64. strncpy( nod->name, name, RULENAME_LEN);
  65. strncpy( nod->param, param, PARAM_LEN);
  66. nod->name[RULENAME_LEN-1] = '\0';
  67. nod->param[PARAM_LEN-1] = '\0';
  68. nod->reference_count = 0;
  69. nod->next = NULL;
  70. return nod;
  71. }
  72. ruleparam_db_ctx * ruleparam_db_alloc(void)
  73. {
  74. ruleparam_db_ctx *ctx;
  75. ctx = (ruleparam_db_ctx *)malloc(sizeof(ruleparam_db_ctx));
  76. if (!ctx)
  77. {
  78. fprintf(stderr, "ruleparam_db_alloc: malloc failed: %s line %i\n", __FILE__, __LINE__ );
  79. return NULL;
  80. }
  81. ctx->n_filename_history = 4;
  82. ctx->pos_filename_history = 0;
  83. ruleparam_db_init(ctx);
  84. return ctx;
  85. }
  86. int ruleparam_db_load( ruleparam_db_ctx **ctx, char *db_fn )
  87. {
  88. FILE *fp;
  89. passdb_slim_ruleparam *nod, *prev=NULL;
  90. ruleparam_db_ctx *tctx = NULL;
  91. FILE *seq_fp;
  92. char db_seq_fn[1024];
  93. char buf[1024];
  94. char name[RULENAME_LEN];
  95. char param[PARAM_LEN];
  96. char *chp, *chp_next;
  97. char *token;
  98. int r = -1;
  99. int id;
  100. int line_no = 0;
  101. int k;
  102. unsigned long long seq=0;
  103. long long int tseq;
  104. int rulecount=-1;
  105. tctx = (ruleparam_db_ctx *)malloc(sizeof(ruleparam_db_ctx));
  106. CHECK_ALLOC_FAIL( (tctx) );
  107. ruleparam_db_init( tctx );
  108. // Read in sequence number from file.
  109. // Keep going if file does not exist.
  110. //
  111. snprintf(db_seq_fn, 128, "%s.seq", db_fn );
  112. seq_fp = fopen( db_seq_fn, "r");
  113. if (!seq_fp)
  114. {
  115. perror( db_seq_fn );
  116. }
  117. else
  118. {
  119. fgets( buf, 1024, seq_fp );
  120. tseq = atoll( buf );
  121. if (tseq > 0)
  122. {
  123. seq = (unsigned long long)tseq;
  124. }
  125. fclose(seq_fp);
  126. }
  127. fp = fopen(db_fn, "r");
  128. if (!fp)
  129. {
  130. perror(db_fn);
  131. if (tctx)
  132. free(tctx);
  133. return -1;
  134. }
  135. while (fgets(buf, 1024, fp ))
  136. {
  137. line_no++;
  138. chp = buf;
  139. if (!chp)
  140. break;
  141. if (!(*chp))
  142. continue;
  143. token = chp;
  144. // skip initial whitespace
  145. //
  146. while ( (*token) && (*token == ' ') )
  147. token++;
  148. // skip comment
  149. //
  150. if (token[0] == '#')
  151. {
  152. /*
  153. if (strncmp( token, "#seq: ", strlen("#seq: ")) == 0)
  154. {
  155. tseq = atoll( token + strlen("#seq: ") );
  156. if (tseq > 0)
  157. {
  158. seq = (unsigned long long)tseq;
  159. }
  160. }
  161. else
  162. */
  163. if (strncmp( token, "#rulecount: ", strlen("#rulecount: ")) == 0)
  164. {
  165. rulecount = atoi( token + strlen("#rulecount: ") );
  166. }
  167. continue;
  168. }
  169. // skip if empty line
  170. //
  171. if (*token == '\n') continue;
  172. // FIRST TOKEN (id)
  173. //find next token (tab)
  174. chp_next = strchr( chp, '\t' );
  175. if (!chp_next) { goto _cleanup; }
  176. *chp_next = '\0';
  177. // and process
  178. k = _chomp(token);
  179. if (k<0) { goto _cleanup; }
  180. if (k==0) continue;
  181. id = atoi(token);
  182. // SECOND TOKEN (rule)
  183. // find next token (tab)
  184. token = chp_next+1;
  185. chp_next = strchr( token, '\t' );
  186. if ( !chp_next ) { goto _cleanup; }
  187. *chp_next = '\0';
  188. _chomp(token);
  189. // and process
  190. strncpy(name, token, RULENAME_LEN);
  191. name[RULENAME_LEN-1] = '\0';
  192. // THIRD TOKEN (param)
  193. // NOTE: fourth token assummed to exist, even though we don't read it
  194. // in. By convention, the fourth token is the reference count.
  195. //
  196. // find next token (tab)
  197. token = chp_next+1;
  198. chp_next = strchr( token, '\t' );
  199. if ( !chp_next ) { goto _cleanup; }
  200. *chp_next = '\0';
  201. _chomp(token);
  202. // and process
  203. strncpy(param, token, PARAM_LEN);
  204. param[PARAM_LEN-1] = '\0';
  205. nod = _alloc_ruleparam_db_nod( id, name, param );
  206. if (tctx->head) prev->next = nod;
  207. else tctx->head = nod;
  208. prev = nod;
  209. tctx->n++;
  210. }
  211. if (tctx->n != rulecount)
  212. {
  213. fprintf(stderr, "WARNING: ruleparam_db_load: read rule count (%i) != reported rule count (%i)\n", tctx->n, rulecount);
  214. }
  215. r = 0;
  216. tctx->db_filename = strdup( db_fn );
  217. tctx->seq = seq;
  218. *ctx = tctx;
  219. return 0;
  220. _cleanup:
  221. fprintf(stderr, "ERROR: ruleparam_db_load: FAIL on line %i\n", line_no);
  222. if (tctx)
  223. {
  224. nod = tctx->head;
  225. while (nod)
  226. {
  227. prev = nod;
  228. nod = nod->next;
  229. free(prev);
  230. }
  231. free(tctx);
  232. }
  233. fclose(fp);
  234. return -1;
  235. }
  236. int _copy_file( char *src_fn, char *dst_fn )
  237. {
  238. FILE *src_fp, *dst_fp;
  239. char buf[1024];
  240. int read_len=0, write_len=0;
  241. int ret=0;
  242. if ( !(src_fp = fopen(src_fn, "r")) )
  243. {
  244. perror(src_fn);
  245. return errno;
  246. }
  247. if ( !(dst_fp = fopen(dst_fn, "w")) )
  248. {
  249. fclose(src_fp);
  250. perror(dst_fn);
  251. return errno;
  252. }
  253. while (!feof(src_fp))
  254. {
  255. read_len = fread(buf, 1, sizeof(buf), src_fp);
  256. if (read_len <= 0)
  257. {
  258. if (ferror(src_fp) != 0)
  259. {
  260. perror(src_fn);
  261. ret = errno;
  262. goto _copy_file_cleanup;
  263. }
  264. continue;
  265. }
  266. while ( (write_len = fwrite(buf, 1, read_len, dst_fp)) != read_len )
  267. {
  268. perror(dst_fn);
  269. ret = errno;
  270. goto _copy_file_cleanup;
  271. }
  272. }
  273. _copy_file_cleanup:
  274. fclose(src_fp);
  275. fclose(dst_fp);
  276. return ret;
  277. }
  278. int ruleparam_db_seq_save( ruleparam_db_ctx *ctx )
  279. {
  280. FILE *seq_fp;
  281. char tmp_fn[512];
  282. char seq_fn[512];
  283. // After ruleparam.db has been synchronized, finally
  284. // write out sequence number in 'ruleparam.db.seq' file.
  285. //
  286. snprintf(tmp_fn, 512, "%s.seq.tmp", ctx->db_filename );
  287. snprintf(seq_fn, 512, "%s.seq", ctx->db_filename );
  288. seq_fp = fopen( tmp_fn, "w" );
  289. if (seq_fp)
  290. {
  291. fprintf(seq_fp, "%llu", ctx->seq);
  292. fclose(seq_fp);
  293. sync();
  294. rename( tmp_fn, seq_fn );
  295. sync();
  296. }
  297. else
  298. {
  299. perror( tmp_fn );
  300. return -1;
  301. }
  302. return 0;
  303. }
  304. int ruleparam_db_save( ruleparam_db_ctx *ctx )
  305. {
  306. FILE *fp;
  307. passdb_slim_ruleparam *nod;
  308. struct tm tm_tim;
  309. struct timeval timval;
  310. char str_tim[64];
  311. char tmp_fn[1024];
  312. char log_fn[1024];
  313. int fn_num = 0;
  314. int rule_count=0;
  315. if ( ctx->n_filename_history > 1 )
  316. {
  317. if (ctx->pos_filename_history < 0)
  318. {
  319. ctx->pos_filename_history = 0;
  320. }
  321. else
  322. {
  323. ctx->pos_filename_history++;
  324. ctx->pos_filename_history %= ctx->n_filename_history;
  325. }
  326. fn_num = ctx->pos_filename_history;
  327. }
  328. sprintf(tmp_fn, "%s.%i.tmp", ctx->db_filename, fn_num);
  329. sprintf(log_fn, "%s.%i", ctx->db_filename, fn_num);
  330. gettimeofday(&timval, NULL);
  331. localtime_r(&(timval.tv_sec), &tm_tim);
  332. asctime_r(&tm_tim, str_tim);
  333. fp = fopen(tmp_fn, "w");
  334. if (!fp)
  335. {
  336. perror(tmp_fn);
  337. format_log_message(&log_msg, LOGLEVEL_ERROR, "Ruleparam dabase open error (%s)", tmp_fn);
  338. if (commhub_fd >= 0)
  339. {
  340. send_message(commhub_fd, &log_msg);
  341. }
  342. return -1;
  343. }
  344. fprintf(fp, "# %s", str_tim);
  345. fprintf(fp, "# Tabs are a necessary field delimiter.\n");
  346. fprintf(fp, "#\n# InternalID,RuleName,RuleParam,ReferenceCount\n");
  347. fprintf(fp, "# Note: The reference count in this file is only used for debugging purposes.\n");
  348. fprintf(fp, "#seq: %llu\n", ctx->seq);
  349. fprintf(fp, "#\n#\n");
  350. nod = ctx->head;
  351. while (nod)
  352. {
  353. fprintf(fp, "%i\t%s\t%s\t%i\n", nod->id, nod->name, nod->param, nod->reference_count);
  354. nod = nod->next;
  355. rule_count++;
  356. }
  357. fprintf(fp, "#rulecount: %i\n", rule_count);
  358. fclose(fp);
  359. sync();
  360. if (_copy_file( tmp_fn, log_fn ) < 0)
  361. {
  362. format_log_message(&log_msg, LOGLEVEL_ERROR, "Ruleparam dabase copy error (%s -> %s)", tmp_fn, log_fn);
  363. if (commhub_fd >= 0)
  364. {
  365. send_message(commhub_fd, &log_msg);
  366. }
  367. return errno;
  368. }
  369. sync();
  370. rename( tmp_fn, ctx->db_filename );
  371. sync();
  372. ruleparam_db_seq_save( ctx );
  373. return 0;
  374. }
  375. int format_new_ruleparamdb( char *fn )
  376. {
  377. ruleparam_db_ctx ctx;
  378. ruleparam_db_init(&ctx);
  379. //return ruleparam_db_save( &ctx, fn );
  380. return ruleparam_db_save( &ctx );
  381. }
  382. int ruleparam_db_add( ruleparam_db_ctx *ctx, char *name, char *param)
  383. {
  384. int id;
  385. passdb_slim_ruleparam *prev = NULL, *nod ;
  386. if (ctx->n == RULEPARAM_DB_MAX)
  387. return RULEPARAM_DB_FULL;
  388. id = ruleparam_db_find( ctx, name, param );
  389. if (id >= 0)
  390. return RULEPARAM_DB_DUP;
  391. id = ruleparam_db_find_free_id( ctx );
  392. if (id < 0)
  393. return id;
  394. nod = _alloc_ruleparam_db_nod( id, name, param);
  395. ctx->n++;
  396. if (!(ctx->head))
  397. {
  398. ctx->head = nod;
  399. return 0;
  400. }
  401. prev = ctx->head;
  402. while(prev->next) prev = prev->next;
  403. prev->next = nod;
  404. return id;
  405. }
  406. int ruleparam_db_remove( ruleparam_db_ctx *ctx, int id)
  407. {
  408. passdb_slim_ruleparam *prev = NULL, *nod ;
  409. nod = ctx->head;
  410. while (nod)
  411. {
  412. if (nod->id == id)
  413. {
  414. if (prev) prev->next = nod->next;
  415. else ctx->head = nod->next;
  416. free(nod);
  417. ctx->n--;
  418. return 0;
  419. }
  420. prev = nod;
  421. nod = nod->next;
  422. }
  423. return RULEPARAM_DB_NOT_FOUND;
  424. }
  425. // Return id of found rule record.
  426. // RULEPARAM_DB_NOT_FOUND if none found.
  427. //
  428. int ruleparam_db_find( ruleparam_db_ctx *ctx, char *name, char *param )
  429. {
  430. passdb_slim_ruleparam *nod;
  431. nod = ctx->head;
  432. while (nod)
  433. {
  434. if ( (strncmp( nod->name, name, RULENAME_LEN ) == 0) &&
  435. (strncmp( nod->param, param, PARAM_LEN ) == 0) )
  436. return nod->id;
  437. nod = nod->next;
  438. }
  439. return RULEPARAM_DB_NOT_FOUND;
  440. }
  441. // Return reference count of rule give as (name,param) string pair
  442. //
  443. int ruleparam_db_reference_count( ruleparam_db_ctx *ctx, char *name, char *param )
  444. {
  445. passdb_slim_ruleparam *nod;
  446. nod = ctx->head;
  447. while (nod)
  448. {
  449. if ( (strncmp( nod->name, name, RULENAME_LEN ) == 0) &&
  450. (strncmp( nod->param, param, PARAM_LEN ) == 0) )
  451. return nod->reference_count;
  452. nod = nod->next;
  453. }
  454. return RULEPARAM_DB_NOT_FOUND;
  455. }
  456. // Populate name and param from rule id, if found
  457. //
  458. int ruleparam_db_get( char *name, char *param, ruleparam_db_ctx *ctx, int id )
  459. {
  460. passdb_slim_ruleparam *nod;
  461. nod = ctx->head;
  462. while (nod)
  463. {
  464. if (nod->id == id)
  465. {
  466. memcpy( name, nod->name, RULENAME_LEN );
  467. memcpy( param, nod->param, PARAM_LEN );
  468. name[RULENAME_LEN-1] = '\0';
  469. name[PARAM_LEN-1] = '\0';
  470. return 0;
  471. }
  472. nod = nod->next;
  473. }
  474. return RULEPARAM_DB_NOT_FOUND;
  475. }
  476. static int _icmp( const void *a, const void *b)
  477. {
  478. return (*((int *)a)) - (*((int *)b)) ;
  479. }
  480. // Take all id's, put them into an array.
  481. // Sort it.
  482. // Find the first non colliding entry starting
  483. // at 0.
  484. //
  485. int ruleparam_db_find_free_id( ruleparam_db_ctx *ctx )
  486. {
  487. int i, n, pos=0;
  488. int *p;
  489. passdb_slim_ruleparam *nod;
  490. n = ctx->n;
  491. if (n == RULEPARAM_DB_MAX)
  492. return RULEPARAM_DB_FULL;
  493. if (n == 0)
  494. return 0;
  495. p = (int *)malloc(sizeof(int)*n);
  496. CHECK_ALLOC_FAIL( (p) );
  497. nod = ctx->head;
  498. while (nod)
  499. {
  500. p[pos++] = nod->id;
  501. nod = nod->next;
  502. }
  503. qsort(p, n, sizeof(int), _icmp);
  504. i=0;
  505. pos=0;
  506. while ( (i<n) && (pos < RULEPARAM_DB_MAX) )
  507. {
  508. if (p[i] == pos)
  509. {
  510. i++;
  511. pos++;
  512. }
  513. else break;
  514. }
  515. free(p);
  516. return pos;
  517. }
  518. void ruleparam_db_dump(ruleparam_db_ctx *ctx)
  519. {
  520. passdb_slim_ruleparam *nod;
  521. printf("n %i\n", ctx->n);
  522. nod = ctx->head;
  523. while (nod)
  524. {
  525. printf(" (%i) '%s' '%s'\n", nod->id, nod->name, nod->param );
  526. nod = nod->next;
  527. }
  528. printf("\n");
  529. }
  530. passdb_slim_ruleparam *ruleparam_db_get_node( ruleparam_db_ctx *ctx, int id )
  531. {
  532. passdb_slim_ruleparam *nod;
  533. nod = ctx->head;
  534. while (nod)
  535. {
  536. if (nod->id == id )
  537. return nod;
  538. nod = nod->next;
  539. }
  540. return NULL;
  541. }
  542. int ruleparam_db_update( ruleparam_db_ctx *ctx, char *name, char *param, int delta_ref_count )
  543. {
  544. int id;
  545. int r;
  546. passdb_slim_ruleparam *nod = NULL;
  547. id = ruleparam_db_find( ctx, name, param );
  548. // If it's not found, create it and update reference count
  549. //
  550. if ( id == RULEPARAM_DB_NOT_FOUND )
  551. {
  552. if (delta_ref_count < 0)
  553. {
  554. goto _ruleparam_db_update_sanity_error;
  555. }
  556. id = ruleparam_db_add( ctx, name, param );
  557. if (id < 0)
  558. return id;
  559. nod = ruleparam_db_get_node( ctx, id );
  560. nod->reference_count += delta_ref_count;
  561. //ruleparam_db_save( ctx, ctx->db_filename );
  562. ruleparam_db_save( ctx );
  563. return id;
  564. }
  565. // Rule record was found, update reference count
  566. //
  567. nod = ruleparam_db_get_node( ctx, id );
  568. nod->reference_count += delta_ref_count;
  569. // check for sanity
  570. //
  571. if (nod->reference_count < 0)
  572. {
  573. goto _ruleparam_db_update_sanity_error;
  574. }
  575. // simply return if there are more references to this record
  576. //
  577. if (nod->reference_count > 0)
  578. {
  579. return id;
  580. }
  581. // otherwise we need to remove this rule record
  582. //
  583. r = ruleparam_db_remove( ctx, id );
  584. if (r < 0)
  585. goto _ruleparam_db_update_sanity_error;
  586. //ruleparam_db_save( ctx, ctx->db_filename );
  587. ruleparam_db_save( ctx );
  588. return r;
  589. _ruleparam_db_update_sanity_error:
  590. fprintf(stderr, "ERROR: sanity! ruleparam_db_update: id %i (%s,%s), delta_ref_count: %i, [ nod(%p).reference_count:%i ] \n",
  591. id, name, param, delta_ref_count,
  592. nod, nod ? nod->reference_count : 0 );
  593. fprintf(stdout, "ERROR: sanity! ruleparam_db_update: id %i (%s,%s), delta_ref_count: %i, [ nod(%p).reference_count:%i ] \n",
  594. id, name, param, delta_ref_count,
  595. nod, nod ? nod->reference_count : 0 );
  596. return RULEPARAM_DB_SANITY;
  597. }
  598. // Remove entries that have zero references
  599. //
  600. int ruleparam_db_clean (ruleparam_db_ctx *ctx)
  601. {
  602. passdb_slim_ruleparam *nod;
  603. passdb_slim_ruleparam *prv = NULL;
  604. passdb_slim_ruleparam *nex ;
  605. nod = ctx->head;
  606. while (nod)
  607. {
  608. nex = nod->next;
  609. if (nod->reference_count == 0)
  610. {
  611. if (prv) prv->next = nex;
  612. else ctx->head = nex;
  613. free(nod);
  614. ctx->n--;
  615. }
  616. else
  617. {
  618. prv = nod;
  619. }
  620. nod = nex;
  621. }
  622. if (ctx->n == 0)
  623. ctx->head = NULL;
  624. return 0;
  625. }
  626. int ruleparam_db_consistency_check( ruleparam_db_ctx *ctx )
  627. {
  628. int n=0;
  629. passdb_slim_ruleparam *nod;
  630. if (!ctx)
  631. {
  632. printf("ruleparam_db_consistenc_check: error, ctx is null\n");
  633. return 0;
  634. }
  635. if ((ctx->n > 0) && (!(ctx->head)))
  636. {
  637. printf("ruleparam_db_consistenc_check: error, ctx->n > 0 (%i) but ctx->head is null \n", ctx->n);
  638. }
  639. nod = ctx->head;
  640. while(nod)
  641. {
  642. if (nod->name[0] == '\0')
  643. {
  644. printf("ruleparam_db_consistenc_check: error, node id %i (pos %i) name is empty\n", nod->id, n);
  645. return 0;
  646. }
  647. if (nod->reference_count <= 0)
  648. {
  649. printf("ruleparam_db_consistenc_check: error, node id %i (pos %i) (%s,%s) reference count (%i) <= 0 \n", nod->id, n, nod->name, nod->param, nod->reference_count);
  650. return 0;
  651. }
  652. n++;
  653. nod = nod->next;
  654. }
  655. if (n != ctx->n)
  656. {
  657. printf("ruleparam_db_consistenc_check: error, ctx->n (%i) != list length (%i) \n", ctx->n, n);
  658. return 0;
  659. }
  660. return 1;
  661. }
  662. int ruleparam_db_debug_dump( ruleparam_db_ctx *ctx)
  663. {
  664. int count=0;
  665. passdb_slim_ruleparam *nod;
  666. printf("ruleparam_db_ctx:\n");
  667. printf(" n: %i\n", ctx->n);
  668. printf(" db_filename: %s\n", ctx->db_filename);
  669. nod = ctx->head;
  670. while (nod)
  671. {
  672. printf(" {%i} id: %i, reference_count: %i, name: %s, param: %s\n",
  673. count++, nod->id, nod->reference_count, nod->name, nod->param );
  674. nod = nod->next;
  675. }
  676. printf("\n");
  677. return 0;
  678. }
  679. int ruleparam_db_free( ruleparam_db_ctx *ctx )
  680. {
  681. passdb_slim_ruleparam *nod, *prev = NULL;
  682. nod = ctx->head;
  683. while (nod)
  684. {
  685. prev = nod;
  686. nod = nod->next;
  687. free(prev);
  688. }
  689. if (ctx->db_filename)
  690. free(ctx->db_filename);
  691. free(ctx);
  692. return 0;
  693. }
  694. // Periodically refresh ruleparam_db, mostly for debugging purposes
  695. // so we can see a somewhat recent snapshot of reference counts.
  696. //
  697. // ruleparam updates through the 'ruleparam_db_update' function
  698. // will automatically write to the ruleparam_db file if a deletion
  699. // or insertion happened.
  700. //
  701. int ruleparam_db_rate_limited_sync( ruleparam_db_ctx *ctx )
  702. {
  703. int retval = 0;
  704. if (ctx->sync_every_n < 1)
  705. {
  706. ctx->sync_counter++;
  707. return retval;
  708. }
  709. if ((ctx->sync_counter % ctx->sync_every_n) == 0)
  710. {
  711. ruleparam_db_save( ctx );
  712. retval = 1;
  713. }
  714. // Else do a sequence number save regardless
  715. //
  716. else
  717. {
  718. ruleparam_db_seq_save( ctx );
  719. sync();
  720. }
  721. ctx->sync_counter++;
  722. return retval;
  723. }
  724. /*
  725. int main(int argc, char **argv)
  726. {
  727. int id=-1, k;
  728. char name[64], param[64];
  729. name[0] = '\0';
  730. param[0] = '\0';
  731. ruleparam_db_ctx *ctx;
  732. ruleparam_db_load(&ctx, RULEPARAM_DB_FILE);
  733. ruleparam_db_dump(ctx);
  734. ruleparam_db_add( ctx, "myrule", "myparam" );
  735. id = ruleparam_db_add( ctx, "myrule0", "myparam" );
  736. ruleparam_db_add( ctx, "myrule", "myparam0" );
  737. ruleparam_db_add( ctx, "myrule0", "myparam0" );
  738. ruleparam_db_dump(ctx);
  739. printf("removing %i\n", id);
  740. printf("\n\n");
  741. ruleparam_db_remove( ctx, id );
  742. ruleparam_db_dump(ctx);
  743. ruleparam_db_save(ctx, RULEPARAM_DB_FILE);
  744. id = ruleparam_db_find(ctx, "myrule0", "myparam");
  745. printf("got %i\n", id);
  746. k = ruleparam_db_get(name, param, ctx, id);
  747. printf(" (%i) %s %s\n", k, name, param);
  748. }
  749. */