dnp_sim2.c 23 KB

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