dnp_sim2.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. /* dnp_simulation.c - this file varifies the correctness of dnp algorithm
  13. by generating random sequences of operations, applying
  14. the algorithm and outputing the result
  15. usage: dnp_sim [-h] [-n <number of simulations> ] [-v] [-f <output file>]
  16. -h - print usage information.
  17. -n <number of simulations> - how many simulations to perform; default - 1.
  18. -v - verbose mode (prints full entry state after each operation execution)
  19. -f <output file> - file where results are stored; by default results are
  20. printed to the screen.
  21. -o <op file> - file that contains operation sequence to execute; by default,
  22. random sequence is generated.
  23. */
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <errno.h>
  27. #include <memory.h>
  28. #include <string.h>
  29. #include <time.h>
  30. #include <windows.h>
  31. #define MAX_OPS 18 /* maximum number of operations in a simulation */
  32. #define MAX_VALS 10 /* maximum number of values is entry or dn */
  33. #define NOT_PRESENT -1
  34. /* data types */
  35. typedef struct value_state
  36. {
  37. int value_index; /* value */
  38. int presence_csn; /* last time at which we know the value was present */
  39. int distinguished_index; /* index into dncsn list */
  40. int delete_csn; /* last attempt to delete this value */
  41. int present; /* flag that tells whether the value iscurrently present */
  42. } Value_State;
  43. typedef struct dn_csn
  44. {
  45. int csn; /* dn csn */
  46. int value_index; /* dn value */
  47. } Dn_Csn;
  48. typedef struct entry_state
  49. {
  50. Dn_Csn dn_csns[MAX_VALS + 1]; /* list of dn csns for this entry */
  51. int dn_csn_count; /* csn of the current dn */
  52. Value_State values[MAX_VALS]; /* values of the attribute */
  53. int attr_delete_csn; /* last attempt to delete the entire attribute */
  54. } Entry_State;
  55. typedef enum {
  56. OP_ADD_VALUE,
  57. OP_DELETE_VALUE,
  58. OP_RENAME_ENTRY,
  59. OP_DELETE_ATTR,
  60. OP_END
  61. } Operation_Type;
  62. typedef struct operation
  63. {
  64. Operation_Type type; /* operation type */
  65. int csn; /* operation type */
  66. int value_index; /* value to add, remove or rename from */
  67. } Operation;
  68. typedef struct simulator_params
  69. {
  70. int runs; /* number of runs */
  71. FILE *fout; /* output file */
  72. int value_count; /* number of values */
  73. int verbose; /* verbose mode */
  74. Operation *ops; /* operation sequence to apply */
  75. int op_count;
  76. } Simulator_Params;
  77. /* gloabl data */
  78. Simulator_Params sim;
  79. char *g_values[] =
  80. {
  81. "v",
  82. "u",
  83. "w",
  84. NULL};
  85. /* forward declarations */
  86. /* initialization */
  87. void process_cmd(int argc, char **argv);
  88. void set_default_sim_params();
  89. int count_values();
  90. void parse_operations_file(char *name);
  91. void parse_operation(char *line, int pos);
  92. int value2index(char *value);
  93. void print_usage();
  94. /* simulation run */
  95. void run_simulation();
  96. void generate_operations(Operation **ops, int *op_count);
  97. void generate_operation(Operation *op, int csn);
  98. int *generate_operation_order(int op_count, int seq_num);
  99. void apply_operation_sequence(Operation *ops, int op_count, int *order, Entry_State *entry);
  100. void init_entry_state(Entry_State *entry);
  101. void init_value_state(Value_State *val, int seq_num);
  102. void apply_operation(Entry_State *entry, Operation *op);
  103. void free_operations(Operation **ops);
  104. int **new_perm_table(int op_count);
  105. void free_perm_table(int ***perm_table, int op_count);
  106. int get_perm_count(int op_count);
  107. void generate_perm_table(int *elements, int element_count, int static_part, int **perm_table);
  108. void apply_add_operation(Entry_State *entry, Operation *op);
  109. void apply_value_delete_operation(Entry_State *entry, Operation *op);
  110. void apply_attr_delete_operation(Entry_State *entry, Operation *op);
  111. void apply_rename_operation(Entry_State *entry, Operation *op);
  112. void purge_value_state(Entry_State *entry, int index);
  113. void resolve_value_state(Entry_State *entry, int value_index);
  114. int value_distinguished_at_delete(Entry_State *entry, int value_index);
  115. int compare_entry_state(Entry_State *entry1, Entry_State *entry2, int run);
  116. /* dnc_csn handling */
  117. int dn_csn_add(Entry_State *entry, int value_index, int csn);
  118. int get_value_dn_csn(Entry_State *entry, int value_index);
  119. /* data tracing */
  120. void dump_operations(Operation *ops, int op_count, int *order);
  121. void dump_operation(Operation *op);
  122. void dump_perm_table(int **perm_table, int op_count);
  123. void dump_entry_state(Entry_State *entry);
  124. void dump_value_state(Value_State *value);
  125. void dump_dn_csn_list(Entry_State *entry);
  126. /* misc functions */
  127. int max_val(int a, int b);
  128. int
  129. main(int argc, char **argv)
  130. {
  131. int i;
  132. process_cmd(argc, argv);
  133. for (i = 0; i < sim.runs; i++) {
  134. fprintf(sim.fout, "*******running simulation #%d ...\n\n", i + 1);
  135. run_simulation();
  136. fprintf(sim.fout, "\n*******done with simulation #%d ...\n\n", i + 1);
  137. }
  138. if (sim.fout != stdout)
  139. fclose(sim.fout);
  140. return 0;
  141. }
  142. void
  143. process_cmd(int argc, char **argv)
  144. {
  145. int i;
  146. set_default_sim_params();
  147. if (argc == 1) {
  148. return;
  149. }
  150. if (strcmp(argv[1], "-h") == 0) /* print help */
  151. {
  152. print_usage();
  153. exit(0);
  154. }
  155. i = 1;
  156. while (i < argc) {
  157. if (strcmp(argv[i], "-v") == 0) /* verbose mode */
  158. {
  159. sim.verbose = 1;
  160. i++;
  161. } else if (strcmp(argv[i], "-n") == 0) {
  162. if (i < argc - 1) {
  163. int runs = atoi(argv[i + 1]);
  164. if (runs > 0)
  165. sim.runs = runs;
  166. i += 2;
  167. } else {
  168. /* ONREPL print warning */
  169. i++;
  170. }
  171. } else if (strcmp(argv[i], "-f") == 0) /* output file */
  172. {
  173. if (i < argc - 1) {
  174. FILE *f = fopen(argv[i + 1], "w");
  175. if (f == 0) {
  176. printf("failed to open output file; error - %s, using stdout\n",
  177. strerror(errno));
  178. } else {
  179. /* ONREPL print warning */
  180. sim.fout = f;
  181. }
  182. i += 2;
  183. } else
  184. i++;
  185. } else if (strcmp(argv[i], "-o") == 0) /* file with operation sequence */
  186. {
  187. if (i < argc - 1) {
  188. parse_operations_file(argv[i + 1]);
  189. i += 2;
  190. } else {
  191. /* ONREPL print warning */
  192. i++;
  193. }
  194. } else /* unknown option */
  195. {
  196. printf("unknown option - %s; ignored\n", argv[i]);
  197. i++;
  198. }
  199. }
  200. }
  201. void
  202. set_default_sim_params()
  203. {
  204. memset(&sim, 0, sizeof(sim));
  205. sim.runs = 1;
  206. sim.fout = stdout;
  207. sim.value_count = count_values();
  208. }
  209. /* file format: <op count>
  210. add <value>
  211. delete <value>
  212. delete attribute
  213. rename to <value>
  214. all spaces are significant
  215. */
  216. void
  217. parse_operations_file(char *name)
  218. {
  219. FILE *file = fopen(name, "r");
  220. char line[256];
  221. int i;
  222. if (file == NULL) {
  223. printf("failed to open operations file %s: error = %d\n", name, errno);
  224. print_usage();
  225. exit(1);
  226. }
  227. i = 0;
  228. while (fgets(line, sizeof(line), file)) {
  229. if (i == 0) {
  230. /* read operation count */
  231. sim.op_count = atoi(line);
  232. if (sim.op_count < 1 || sim.op_count > MAX_OPS / 2) {
  233. printf("invalid operation count - %d; value must be between 1 and %d\n",
  234. sim.op_count, MAX_OPS / 2);
  235. print_usage();
  236. exit(1);
  237. } else {
  238. sim.ops = (Operation *)malloc(sim.op_count * sizeof(Operation));
  239. }
  240. } else {
  241. if (strlen(line) == 0) /* skip empty lines */
  242. continue;
  243. parse_operation(line, i);
  244. }
  245. i++;
  246. }
  247. }
  248. void
  249. parse_operation(char *line, int i)
  250. {
  251. sim.ops[i - 1].csn = i;
  252. if (line[strlen(line) - 1] == '\n')
  253. line[strlen(line) - 1] = '\0';
  254. if (strncmp(line, "add", 3) == 0) {
  255. sim.ops[i - 1].type = OP_ADD_VALUE;
  256. sim.ops[i - 1].value_index = value2index(&line[4]);
  257. } else if (strncmp(line, "delete attribute", 16) == 0) {
  258. sim.ops[i - 1].type = OP_DELETE_ATTR;
  259. } else if (strncmp(line, "delete", 6) == 0) {
  260. sim.ops[i - 1].type = OP_DELETE_VALUE;
  261. sim.ops[i - 1].value_index = value2index(&line[7]);
  262. } else if (strncmp(line, "rename to", 6) == 0) {
  263. sim.ops[i - 1].type = OP_RENAME_ENTRY;
  264. sim.ops[i - 1].value_index = value2index(&line[10]);
  265. } else {
  266. /* invalid line */
  267. printf("invalid operation: %s\n", line);
  268. exit(1);
  269. }
  270. }
  271. int
  272. value2index(char *value)
  273. {
  274. int i;
  275. for (i = 0; i < sim.value_count; i++) {
  276. if (strcmp(g_values[i], value) == 0)
  277. return i;
  278. }
  279. return -1;
  280. }
  281. void
  282. print_usage()
  283. {
  284. printf("usage: dnp_sim [-h] [-n <number of simulations> ] [-v] [-f <output file>]\n"
  285. "\t-h - print usage information\n"
  286. "\t-n <number of simulations>; default - 1\n"
  287. "\t-v - verbose mode\n"
  288. "\t-f <output file> - by default, results are printed to the screen\n"
  289. "\t-o <op file> - file that contains operation sequence to execute;\n"
  290. "\tby default, random sequence is generated.\n");
  291. }
  292. int
  293. count_values()
  294. {
  295. int i;
  296. for (i = 0; g_values[i]; i++)
  297. ;
  298. return i;
  299. }
  300. void
  301. run_simulation()
  302. {
  303. int *order;
  304. int i;
  305. int perm_count;
  306. Entry_State entry_first, entry_current;
  307. int error = 0;
  308. init_entry_state(&entry_first);
  309. fprintf(sim.fout, "initial entry state :\n");
  310. dump_entry_state(&entry_first);
  311. if (sim.ops == NULL) {
  312. generate_operations(&sim.ops, &sim.op_count);
  313. }
  314. fprintf(sim.fout, "initial operation set:\n");
  315. dump_operations(sim.ops, sim.op_count, NULL /* order */);
  316. //DebugBreak ();
  317. perm_count = get_perm_count(sim.op_count);
  318. for (i = 0; i < perm_count; i++) {
  319. fprintf(sim.fout, "--------------------------------\n");
  320. fprintf(sim.fout, "simulation run %d\n", i + 1);
  321. fprintf(sim.fout, "--------------------------------\n");
  322. order = generate_operation_order(sim.op_count, i);
  323. if (i == 0)
  324. apply_operation_sequence(sim.ops, sim.op_count, order, &entry_first);
  325. else {
  326. apply_operation_sequence(sim.ops, sim.op_count, order, &entry_current);
  327. error |= compare_entry_state(&entry_first, &entry_current, i + 1);
  328. }
  329. }
  330. switch (error) {
  331. case 0:
  332. fprintf(sim.fout, "all runs left the entry in the same state\n");
  333. break;
  334. case 1:
  335. fprintf(sim.fout, "while value presence is consistent across all runs, "
  336. "the exact state does not match\n");
  337. break;
  338. case 3:
  339. fprintf(sim.fout, "the runs left entries in an inconsistent state\n");
  340. break;
  341. }
  342. free_operations(&sim.ops);
  343. }
  344. void
  345. generate_operations(Operation **ops, int *op_count)
  346. {
  347. int i;
  348. /* generate number operations in the sequence */
  349. *op_count = slapi_rand() % (MAX_OPS / 2) + 1;
  350. *ops = (Operation *)malloc(*op_count * sizeof(Operation));
  351. for (i = 0; i < *op_count; i++) {
  352. generate_operation(&((*ops)[i]), i + 1);
  353. }
  354. }
  355. void
  356. generate_operation(Operation *op, int csn)
  357. {
  358. /* generate operation type */
  359. op->type = slapi_rand() % OP_END;
  360. /* generate value to which operation applies */
  361. op->value_index = slapi_rand() % sim.value_count;
  362. op->csn = csn;
  363. }
  364. int *
  365. generate_operation_order(int op_count, int seq_num)
  366. {
  367. static int **perm_table = NULL;
  368. /* first request - generate pemutation table */
  369. if (seq_num == 0) {
  370. int elements[MAX_OPS];
  371. int i;
  372. if (perm_table)
  373. free_perm_table(&perm_table, op_count);
  374. perm_table = new_perm_table(op_count);
  375. for (i = 0; i < op_count; i++)
  376. elements[i] = i;
  377. generate_perm_table(elements, op_count, 0 /* static part */,
  378. perm_table);
  379. }
  380. return perm_table[seq_num];
  381. }
  382. void
  383. apply_operation_sequence(Operation *ops, int op_count, int *order, Entry_State *entry)
  384. {
  385. int i;
  386. init_entry_state(entry);
  387. if (!sim.verbose) {
  388. if (!sim.verbose) {
  389. fprintf(sim.fout, "operation_sequence for this run:\n");
  390. dump_operations(ops, op_count, order);
  391. }
  392. }
  393. for (i = 0; i < op_count; i++) {
  394. apply_operation(entry, &(ops[order[i]]));
  395. }
  396. if (!sim.verbose) {
  397. fprintf(sim.fout, "final entry state :\n");
  398. dump_entry_state(entry);
  399. }
  400. }
  401. void
  402. init_entry_state(Entry_State *entry)
  403. {
  404. int i;
  405. memset(entry, 0, sizeof(*entry));
  406. entry->attr_delete_csn = NOT_PRESENT;
  407. entry->dn_csn_count = 1;
  408. for (i = 0; i < sim.value_count; i++) {
  409. init_value_state(&(entry->values[i]), i);
  410. }
  411. }
  412. void
  413. init_value_state(Value_State *val, int seq_num)
  414. {
  415. memset(val, 0, sizeof(*val));
  416. val->value_index = seq_num;
  417. val->present = 1;
  418. val->delete_csn = NOT_PRESENT;
  419. if (seq_num > 0) /* only first value is distinguished */
  420. val->distinguished_index = -1;
  421. }
  422. void
  423. apply_operation(Entry_State *entry, Operation *op)
  424. {
  425. switch (op->type) {
  426. case OP_ADD_VALUE:
  427. apply_add_operation(entry, op);
  428. break;
  429. case OP_DELETE_VALUE:
  430. apply_value_delete_operation(entry, op);
  431. break;
  432. case OP_DELETE_ATTR:
  433. apply_attr_delete_operation(entry, op);
  434. break;
  435. case OP_RENAME_ENTRY:
  436. apply_rename_operation(entry, op);
  437. break;
  438. }
  439. if (sim.verbose) {
  440. fprintf(sim.fout, "operation: ");
  441. dump_operation(op);
  442. fprintf(sim.fout, "\n");
  443. dump_entry_state(entry);
  444. }
  445. }
  446. void
  447. free_operations(Operation **ops)
  448. {
  449. free(*ops);
  450. *ops = NULL;
  451. }
  452. int **
  453. new_perm_table(int op_count)
  454. {
  455. int i;
  456. int **perm_table;
  457. int perm_count = get_perm_count(op_count);
  458. perm_table = (int **)malloc(perm_count * sizeof(int *));
  459. for (i = 0; i < perm_count; i++)
  460. perm_table[i] = (int *)malloc(op_count * sizeof(int));
  461. return perm_table;
  462. }
  463. void
  464. free_perm_table(int ***perm_table, int op_count)
  465. {
  466. int i;
  467. int perm_count = get_perm_count(op_count);
  468. for (i = 0; i < perm_count; i++)
  469. free((*perm_table)[i]);
  470. free(*perm_table);
  471. *perm_table = NULL;
  472. }
  473. void
  474. generate_perm_table(int *elements, int element_count, int static_part, int **perm_table)
  475. {
  476. int i;
  477. int elements_copy[MAX_OPS];
  478. int start_pos;
  479. if (element_count - 1 == static_part) {
  480. memcpy(*perm_table, elements, element_count * sizeof(int));
  481. return;
  482. }
  483. start_pos = 0;
  484. for (i = 0; i < element_count - static_part; i++) {
  485. memcpy(elements_copy, elements, element_count * sizeof(int));
  486. elements_copy[static_part] = elements[static_part + i];
  487. elements_copy[static_part + i] = elements[static_part];
  488. generate_perm_table(elements_copy, element_count, static_part + 1,
  489. &perm_table[start_pos]);
  490. start_pos += get_perm_count(element_count - static_part - 1);
  491. }
  492. }
  493. int
  494. get_perm_count(int op_count)
  495. {
  496. int i;
  497. int perm_count = 1;
  498. for (i = 2; i <= op_count; i++)
  499. perm_count *= i;
  500. return perm_count;
  501. }
  502. void
  503. apply_add_operation(Entry_State *entry, Operation *op)
  504. {
  505. if (entry->values[op->value_index].presence_csn < op->csn) {
  506. entry->values[op->value_index].presence_csn = op->csn;
  507. resolve_value_state(entry, op->value_index);
  508. }
  509. }
  510. void
  511. apply_value_delete_operation(Entry_State *entry, Operation *op)
  512. {
  513. if (entry->values[op->value_index].delete_csn < op->csn) {
  514. entry->values[op->value_index].delete_csn = op->csn;
  515. resolve_value_state(entry, op->value_index);
  516. }
  517. }
  518. void
  519. apply_attr_delete_operation(Entry_State *entry, Operation *op)
  520. {
  521. int i;
  522. if (entry->attr_delete_csn < op->csn) {
  523. entry->attr_delete_csn = op->csn;
  524. for (i = 0; i < sim.value_count; i++) {
  525. resolve_value_state(entry, i);
  526. }
  527. }
  528. }
  529. void
  530. apply_rename_operation(Entry_State *entry, Operation *op)
  531. {
  532. int index;
  533. if (entry->values[op->value_index].presence_csn == NOT_PRESENT)
  534. entry->values[op->value_index].presence_csn = op->csn;
  535. index = dn_csn_add(entry, op->value_index, op->csn);
  536. if (index > 0)
  537. resolve_value_state(entry, entry->dn_csns[index - 1].value_index);
  538. resolve_value_state(entry, entry->dn_csns[index].value_index);
  539. }
  540. void
  541. purge_value_state(Entry_State *entry, int value_index)
  542. {
  543. Value_State *value = &(entry->values[value_index]);
  544. int value_distinguished_csn = get_value_dn_csn(entry, value_index);
  545. if (value_distinguished_csn == -1 && value->presence_csn > value->delete_csn)
  546. value->delete_csn = NOT_PRESENT;
  547. else if (value->delete_csn < max_val(value_distinguished_csn, value->presence_csn))
  548. value->delete_csn = NOT_PRESENT;
  549. }
  550. void
  551. resolve_value_state(Entry_State *entry, int value_index)
  552. {
  553. Value_State *value = &(entry->values[value_index]);
  554. int value_distinguished_csn = get_value_dn_csn(entry, value_index);
  555. purge_value_state(entry, value_index);
  556. /* no deletes that effect the state */
  557. if (max_val(value->delete_csn, entry->attr_delete_csn) <
  558. max_val(value_distinguished_csn, value->presence_csn)) {
  559. value->present = 1;
  560. return;
  561. }
  562. if (value->present) /* check if it should be removed based on the current state */
  563. {
  564. if (!value_distinguished_at_delete(entry, value_index)) {
  565. value->present = 0;
  566. }
  567. } else /* not present - check if it should be restored */
  568. {
  569. if (value_distinguished_at_delete(entry, value_index)) {
  570. value->present = 1;
  571. }
  572. }
  573. }
  574. int
  575. value_distinguished_at_delete(Entry_State *entry, int value_index)
  576. {
  577. Value_State *value = &(entry->values[value_index]);
  578. int value_distinguished_csn = get_value_dn_csn(entry, value_index);
  579. int delete_csn;
  580. int i;
  581. /* value has never been distinguished */
  582. if (value_distinguished_csn == -1)
  583. return 0;
  584. delete_csn = max_val(entry->attr_delete_csn, value->delete_csn);
  585. for (i = 0; i < entry->dn_csn_count; i++) {
  586. if (entry->dn_csns[i].csn > delete_csn)
  587. break;
  588. }
  589. /* i is never equal to 0 because the csn of the first element is always
  590. smaller than csn of any operation we can receive */
  591. return (entry->dn_csns[i - 1].value_index == value_index);
  592. }
  593. int
  594. compare_entry_state(Entry_State *entry1, Entry_State *entry2, int run)
  595. {
  596. int i;
  597. int error = 0;
  598. /* first - quick check for present / not present */
  599. for (i = 0; i < sim.value_count; i++) {
  600. if (entry1->values[i].present != entry2->values[i].present) {
  601. fprintf(sim.fout,
  602. "value %s is %s present in the first run but %s present in the %d run\n",
  603. g_values[i], entry1->values[i].present ? "" : "not",
  604. entry2->values[i].present ? "" : "not", run);
  605. error = 1;
  606. }
  607. }
  608. if (error)
  609. return 3;
  610. /* compare dnc_csn list */
  611. if (entry1->dn_csn_count != entry2->dn_csn_count) {
  612. fprintf(sim.fout, "dn_csn count is %d for run 1 and %d for run %d\n",
  613. entry1->dn_csn_count, entry2->dn_csn_count, run);
  614. error = 1;
  615. }
  616. for (i = 0; i < entry1->dn_csn_count; i++) {
  617. if (entry1->dn_csns[i].csn != entry2->dn_csns[i].csn ||
  618. entry1->dn_csns[i].value_index != entry2->dn_csns[i].value_index) {
  619. fprintf(sim.fout, "elements %d of dn csn list are different:\n"
  620. "\tfirst run: csn - %d, value - %s\n"
  621. "\t%d run: csn - %d, value - %s\n",
  622. i,
  623. entry1->dn_csns[i].csn,
  624. g_values[entry1->dn_csns[i].value_index],
  625. run, entry2->dn_csns[i].csn,
  626. g_values[entry2->dn_csns[i].value_index]);
  627. error = 1;
  628. }
  629. }
  630. /* compare value state */
  631. if (entry1->attr_delete_csn != entry2->attr_delete_csn) {
  632. fprintf(sim.fout, "attribute delete csn is %d for run 1 "
  633. "but is %d for run %d\n",
  634. entry1->attr_delete_csn,
  635. entry2->attr_delete_csn, run);
  636. error = 1;
  637. }
  638. for (i = 0; i < sim.value_count; i++) {
  639. if (entry1->values[i].presence_csn != entry2->values[i].presence_csn) {
  640. fprintf(sim.fout, "presence csn for value %s is %d in run 1 "
  641. "but is %d in run %d\n",
  642. g_values[i], entry1->values[i].presence_csn,
  643. entry2->values[i].presence_csn, run);
  644. error = 1;
  645. }
  646. if (entry1->values[i].distinguished_index != entry2->values[i].distinguished_index) {
  647. fprintf(sim.fout, "distinguished index for value %s is %d in run 1 "
  648. "but is %d in run %d\n",
  649. g_values[i],
  650. entry1->values[i].distinguished_index,
  651. entry2->values[i].distinguished_index, run);
  652. error = 1;
  653. }
  654. if (entry1->values[i].delete_csn != entry2->values[i].delete_csn) {
  655. fprintf(sim.fout, "delete csn for value %s is %d in run 1 "
  656. "but is %d in run %d\n",
  657. g_values[i], entry1->values[i].delete_csn,
  658. entry2->values[i].delete_csn, run);
  659. error = 1;
  660. }
  661. }
  662. if (error != 0) {
  663. return 1;
  664. } else
  665. return 0;
  666. }
  667. int
  668. dn_csn_add(Entry_State *entry, int value_index, int csn)
  669. {
  670. int i, j;
  671. int distinguished_index;
  672. for (i = 0; i < entry->dn_csn_count; i++) {
  673. if (entry->dn_csns[i].csn > csn)
  674. break;
  675. }
  676. if (i < entry->dn_csn_count) {
  677. distinguished_index = i;
  678. for (j = i; j < entry->dn_csn_count; j++) {
  679. if (entry->dn_csns[j].value_index == value_index)
  680. distinguished_index = j + 1;
  681. if (entry->values[entry->dn_csns[j].value_index].distinguished_index == j)
  682. entry->values[entry->dn_csns[j].value_index].distinguished_index++;
  683. }
  684. memcpy(&(entry->dn_csns[i + 1]), &(entry->dn_csns[i]),
  685. (entry->dn_csn_count - i) * sizeof(Dn_Csn));
  686. } else {
  687. distinguished_index = entry->dn_csn_count;
  688. }
  689. entry->values[value_index].distinguished_index = distinguished_index;
  690. entry->dn_csns[i].csn = csn;
  691. entry->dn_csns[i].value_index = value_index;
  692. entry->dn_csn_count++;
  693. return i;
  694. }
  695. int
  696. get_value_dn_csn(Entry_State *entry, int value_index)
  697. {
  698. Value_State *value = &(entry->values[value_index]);
  699. if (value->distinguished_index == -1)
  700. return -1;
  701. else
  702. return entry->dn_csns[value->distinguished_index].csn;
  703. }
  704. void
  705. dump_operations(Operation *ops, int op_count, int *order)
  706. {
  707. int index;
  708. int i;
  709. for (i = 0; i < op_count; i++) {
  710. if (order == NULL) /* current order */
  711. index = i;
  712. else
  713. index = order[i];
  714. dump_operation(&ops[index]);
  715. }
  716. fprintf(sim.fout, "\n");
  717. }
  718. void
  719. dump_operation(Operation *op)
  720. {
  721. switch (op->type) {
  722. case OP_ADD_VALUE:
  723. fprintf(sim.fout, "\t%d add value %s\n", op->csn,
  724. g_values[op->value_index]);
  725. break;
  726. case OP_DELETE_VALUE:
  727. fprintf(sim.fout, "\t%d delete value %s\n", op->csn,
  728. g_values[op->value_index]);
  729. break;
  730. case OP_DELETE_ATTR:
  731. fprintf(sim.fout, "\t%d delete attribute\n", op->csn);
  732. break;
  733. case OP_RENAME_ENTRY:
  734. fprintf(sim.fout, "\t%d rename entry to %s\n", op->csn,
  735. g_values[op->value_index]);
  736. break;
  737. }
  738. }
  739. void
  740. dump_perm_table(int **perm_table, int op_count)
  741. {
  742. int i, j;
  743. int perm_count = get_perm_count(op_count);
  744. for (i = 0; i < op_count; i++) {
  745. for (j = 0; j < perm_count; j++) {
  746. fprintf(sim.fout, "%d ", perm_table[j][i]);
  747. }
  748. fprintf(sim.fout, "\n");
  749. }
  750. }
  751. void
  752. dump_entry_state(Entry_State *entry)
  753. {
  754. int i;
  755. dump_dn_csn_list(entry);
  756. for (i = 0; i < sim.value_count; i++) {
  757. dump_value_state(&(entry->values[i]));
  758. }
  759. fprintf(sim.fout, "\n");
  760. }
  761. void
  762. dump_value_state(Value_State *value)
  763. {
  764. fprintf(sim.fout, "\tvalue %s is %s\n", g_values[value->value_index],
  765. value->present ? "present" : "not present");
  766. if (sim.verbose) {
  767. fprintf(sim.fout, "\t\tpresent csn: %d\n", value->presence_csn);
  768. fprintf(sim.fout, "\t\tdistinguished index: %d\n", value->distinguished_index);
  769. fprintf(sim.fout, "\t\tdelete value csn: %d\n", value->delete_csn);
  770. }
  771. }
  772. void
  773. dump_dn_csn_list(Entry_State *entry)
  774. {
  775. int i;
  776. fprintf(sim.fout, "\tdn csn list: \n");
  777. for (i = 0; i < entry->dn_csn_count; i++) {
  778. fprintf(sim.fout, "\t\tvalue: %s, csn: %d\n",
  779. g_values[entry->dn_csns[i].value_index], entry->dn_csns[i].csn);
  780. }
  781. }
  782. /* misc functions */
  783. int
  784. max_val(int a, int b)
  785. {
  786. if (a >= b)
  787. return a;
  788. else
  789. return b;
  790. }