dnp_sim3.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* dnp_simulation.c - this file varifies the correctness of dnp algorithm
  42. by generating random sequences of operations, applying
  43. the algorithm and outputing the result
  44. usage: dnp_sim [-h] [-n <number of simulations> ] [-v] [-f <output file>]
  45. -h - print usage information.
  46. -n <number of simulations> - how many simulations to perform; default - 1.
  47. -v - verbose mode (prints full entry state after each operation execution)
  48. -f <output file> - file where results are stored; by default results are
  49. printed to the screen.
  50. -o <op file> - file that contains operation sequence to execute; by default,
  51. random sequence is generated.
  52. */
  53. #include <stdlib.h>
  54. #include <stdio.h>
  55. #include <errno.h>
  56. #include <memory.h>
  57. #include <string.h>
  58. #include <time.h>
  59. #include <windows.h>
  60. #define MAX_OPS 18 /* maximum number of operations in a simulation */
  61. #define MAX_VALS 10 /* maximum number of values is entry or dn */
  62. #define MAX_ATTR_NAME 16 /* max length of the attribute name */
  63. #define NOT_PRESENT -1
  64. #define SV_ATTR_NAME "sv_attr" /* name of the singlevalued attribute */
  65. #define MV_ATTR_NAME "mv_attr" /* name of the multivalued attribute */
  66. /* data types */
  67. /* value */
  68. typedef struct value_state
  69. {
  70. int value_index; /* value */
  71. int presence_csn; /* last time at which we know the value was present */
  72. int delete_csn; /* last attempt to delete this value */
  73. int present; /* flag that tells whether the value is present */
  74. } Value_State;
  75. /* shared attribute state */
  76. typedef struct attr_state
  77. {
  78. int delete_csn; /* last deletion csn */
  79. int present; /* flag that tells whether the attribute is present */
  80. }Attr_State;
  81. /* singlevalued attribute */
  82. typedef struct sv_attr_state
  83. {
  84. Attr_State attr_state; /* shared attribute state */
  85. Value_State current_value; /* current attribute value */
  86. Value_State *pending_value; /* latest pending value */
  87. } SV_Attr_State;
  88. /* maltivalued attribute */
  89. typedef struct mv_attr_state
  90. {
  91. Attr_State attr_state; /* shared attribute state */
  92. Value_State values [MAX_VALS]; /* latest pending value */
  93. int value_count; /* number of values in the array */
  94. } MV_Attr_State;
  95. /* node of dn_csn_list */
  96. typedef struct dn_csn
  97. {
  98. int csn; /* dn csn */
  99. int sv_attr; /* is this single valued or multivalued attr */
  100. int value_index; /* dn value */
  101. } Dn_Csn;
  102. typedef struct entry_state
  103. {
  104. Dn_Csn dn_csns [MAX_VALS + 1]; /* list of dn csns for this entry */
  105. int dn_csn_count; /* csn of the current dn */
  106. SV_Attr_State sv_attr; /* singlevalued attribute */
  107. MV_Attr_State mv_attr; /* singlevalued attribute */
  108. } Entry_State;
  109. typedef enum
  110. {
  111. OP_ADD_VALUE,
  112. OP_DELETE_VALUE,
  113. OP_RENAME_ENTRY,
  114. OP_DELETE_ATTR,
  115. OP_END
  116. } Operation_Type;
  117. typedef struct operation
  118. {
  119. Operation_Type type; /* operation type */
  120. int csn; /* operation csn */
  121. int sv_attr; /* is this applied to singlevalued attribute */
  122. int value_index; /* value to add, remove or rename from */
  123. int delete_old_rdn; /* rename only */
  124. int old_rdn_sv_attr; /* is oldrdn a singlevalued attribute */
  125. int old_rdn_value_index; /* index of old_rdn */
  126. }Operation;
  127. typedef struct simulator_params
  128. {
  129. int runs; /* number of runs */
  130. FILE *fout; /* output file */
  131. int value_count; /* number of values */
  132. int verbose; /* verbose mode */
  133. Operation *ops; /* operation sequence to apply */
  134. int op_count;
  135. }Simulator_Params;
  136. /* gloabl data */
  137. Simulator_Params sim;
  138. char *g_values[] =
  139. {
  140. "v",
  141. "u",
  142. "w",
  143. NULL
  144. };
  145. /* forward declarations */
  146. /* initialization */
  147. void process_cmd (int argc, char **argv);
  148. void set_default_sim_params ();
  149. int count_values ();
  150. void parse_operations_file (char *name);
  151. void parse_operation (char *line, int pos);
  152. int value2index (char *value);
  153. void print_usage ();
  154. /* simulation run */
  155. void run_simulation ();
  156. void generate_operations (Operation **ops, int *op_count);
  157. void generate_operation (Operation *op, int csn);
  158. int* generate_operation_order (int op_count, int seq_num);
  159. void apply_operation_sequence (Operation *ops, int op_count, int *order, Entry_State *entry);
  160. void init_entry_state (Entry_State *entry);
  161. void init_sv_attr_state (SV_Attr_State *sv_attr);
  162. void init_mv_attr_state (MV_Attr_State *mv_attr);
  163. void init_value_state (Value_State *val, int seq_num);
  164. void free_operations (Operation **ops);
  165. int ** new_perm_table (int op_count);
  166. void free_perm_table (int ***perm_table, int op_count);
  167. int get_perm_count (int op_count);
  168. void generate_perm_table (int *elements, int element_count, int static_part,
  169. int **perm_table);
  170. void apply_operation (Entry_State *entry, Operation *op);
  171. void apply_add_operation (Entry_State *entry, Operation *op);
  172. void apply_value_delete_operation (Entry_State *entry, Operation *op);
  173. void apply_attr_delete_operation (Entry_State *entry, Operation *op);
  174. void apply_rename_operation (Entry_State *entry, Operation *op);
  175. void resolve_mv_attr_state (Entry_State *entry, Value_State *value);
  176. void resolve_sv_attr_state (Entry_State *entry, Value_State *value);
  177. void purge_sv_attr_state (Entry_State *entry);
  178. void purge_mv_attr_state (Entry_State *entry, Value_State *value);
  179. int value_distinguished_at_csn (Entry_State *entry, int sv_attr, Value_State *value, int csn);
  180. /* state comparison */
  181. int compare_entry_state (Entry_State *entry1, Entry_State *entry2, int run);
  182. int compare_entry_state_quick (Entry_State *entry1, Entry_State *entry2, int run);
  183. int compare_sv_attr_state_quick (SV_Attr_State *sv_attr1, SV_Attr_State *sv_attr2, int run);
  184. int compare_mv_attr_state_quick (MV_Attr_State *mv_attr1, MV_Attr_State *mv_attr2, int run);
  185. int compare_sv_attr_state (SV_Attr_State *sv_attr1, SV_Attr_State *sv_attr2, int run);
  186. int compare_mv_attr_state (MV_Attr_State *mv_attr1, MV_Attr_State *mv_attr2, int run);
  187. int compare_value_state (Value_State *value1, Value_State *value2, int run);
  188. /* dnc_csn handling */
  189. int dn_csn_add (Entry_State *entry, int sv_attr, int value_index, int csn);
  190. /* data tracing */
  191. void dump_operations (Operation *ops, int op_count, int *order);
  192. void dump_operation (Operation *op);
  193. void dump_perm_table (int **perm_table, int op_count);
  194. void dump_entry_state (Entry_State *entry);
  195. void dump_sv_attr_state (SV_Attr_State *sv_attr);
  196. void dump_mv_attr_state (MV_Attr_State *mv_attr);
  197. void dump_value_state (Value_State *value, int sv_attr);
  198. void dump_dn_csn_list (Entry_State *entry);
  199. /* misc functions */
  200. int max_val (int a, int b);
  201. int main (int argc, char **argv)
  202. {
  203. int i;
  204. process_cmd (argc, argv);
  205. for (i = 0; i < sim.runs; i++)
  206. {
  207. fprintf (sim.fout, "*******running simulation #%d ...\n\n", i+1);
  208. run_simulation ();
  209. fprintf (sim.fout, "\n*******done with simulation #%d ...\n\n", i+1);
  210. }
  211. if (sim.fout != stdout)
  212. fclose (sim.fout);
  213. return 0;
  214. }
  215. void process_cmd (int argc, char **argv)
  216. {
  217. int i;
  218. set_default_sim_params ();
  219. if (argc == 1)
  220. {
  221. return;
  222. }
  223. if (strcmp (argv[1], "-h") == 0) /* print help */
  224. {
  225. print_usage ();
  226. exit (0);
  227. }
  228. i = 1;
  229. while (i < argc)
  230. {
  231. if (strcmp (argv[i], "-v") == 0) /* verbose mode */
  232. {
  233. sim.verbose = 1;
  234. i ++;
  235. }
  236. else if (strcmp (argv[i], "-n") == 0)
  237. {
  238. if (i < argc - 1)
  239. {
  240. int runs = atoi (argv[i + 1]);
  241. if (runs > 0)
  242. sim.runs = runs;
  243. i+=2;
  244. }
  245. else
  246. {
  247. /* ONREPL print warning */
  248. i++;
  249. }
  250. }
  251. else if (strcmp (argv[i], "-f") == 0) /* output file */
  252. {
  253. if (i < argc - 1)
  254. {
  255. FILE *f = fopen (argv[i + 1], "w");
  256. if (f == 0)
  257. {
  258. printf ("failed to open output file; error - %s, using stdout\n",
  259. strerror(errno));
  260. }
  261. else
  262. {
  263. /* ONREPL print warning */
  264. sim.fout = f;
  265. }
  266. i += 2;
  267. }
  268. else
  269. i++;
  270. }
  271. else if (strcmp (argv[i], "-o") == 0) /* file with operation sequence */
  272. {
  273. if (i < argc - 1)
  274. {
  275. parse_operations_file (argv[i+1]);
  276. i += 2;
  277. }
  278. else
  279. {
  280. /* ONREPL print warning */
  281. i ++;
  282. }
  283. }
  284. else /* unknown option */
  285. {
  286. printf ("unknown option - %s; ignored\n", argv[i]);
  287. i ++;
  288. }
  289. }
  290. }
  291. void set_default_sim_params ()
  292. {
  293. memset (&sim, 0, sizeof (sim));
  294. sim.runs = 1;
  295. sim.fout = stdout;
  296. sim.value_count = count_values ();
  297. }
  298. /* file format: <operation count>
  299. add <attribute> <value>
  300. delete <attribute>[ <value>]
  301. rename to <attribute> <value>[ delete <attribute> <value>]
  302. all spaces are significant
  303. */
  304. void parse_operations_file (char *name)
  305. {
  306. FILE *file = fopen (name, "r");
  307. char line [256];
  308. int i;
  309. if (file == NULL)
  310. {
  311. printf ("failed to open operations file %s: error = %d\n", name, errno);
  312. print_usage ();
  313. exit (1);
  314. }
  315. i = 0;
  316. while (fgets (line, sizeof (line), file))
  317. {
  318. if (i == 0)
  319. {
  320. /* read operation count */
  321. sim.op_count = atoi (line);
  322. if (sim.op_count < 1 || sim.op_count > MAX_OPS/2)
  323. {
  324. printf ("invalid operation count - %d; value must be between 1 and %d\n",
  325. sim.op_count, MAX_OPS/2);
  326. print_usage ();
  327. exit (1);
  328. }
  329. else
  330. {
  331. sim.ops = (Operation*)malloc (sim.op_count * sizeof (Operation));
  332. }
  333. }
  334. else
  335. {
  336. if (strlen (line) == 0) /* skip empty lines */
  337. continue;
  338. parse_operation (line, i);
  339. }
  340. i ++;
  341. }
  342. }
  343. #define ADD_KEYWORD "add "
  344. #define DELETE_KEYWORD "delete "
  345. #define RENAME_KEYWORD "rename to "
  346. #define DELET_OLD_RDN_KEYWORD " delete "
  347. void parse_operation (char *line, int i)
  348. {
  349. int rc = 0;
  350. char *pos;
  351. char buff [64];
  352. sim.ops [i - 1].csn = i;
  353. if (line[strlen(line) - 1] == '\n')
  354. line[strlen(line) - 1] = '\0';
  355. /* add <attribute> <value> */
  356. if (strncmp (line, ADD_KEYWORD, strlen (ADD_KEYWORD)) == 0)
  357. {
  358. sim.ops [i - 1].type = OP_ADD_VALUE;
  359. pos = strchr (&line[strlen (ADD_KEYWORD)], ' ');
  360. if (pos == NULL)
  361. {
  362. rc = -1;
  363. goto done;
  364. }
  365. memset (buff, 0, sizeof (buff));
  366. strncpy (buff, &line[strlen (ADD_KEYWORD)], pos - &line[strlen (ADD_KEYWORD)]);
  367. sim.ops [i - 1].sv_attr = strcmp (buff, MV_ATTR_NAME);
  368. sim.ops [i - 1].value_index = value2index (pos + 1);
  369. }
  370. /* delete <attribute>[ <value>] */
  371. else if (strncmp (line, DELETE_KEYWORD, strlen (DELETE_KEYWORD)) == 0)
  372. {
  373. pos = strchr (&line[strlen (DELETE_KEYWORD)], ' ');
  374. if (pos == NULL) /* delete attribute version */
  375. {
  376. sim.ops [i - 1].type = OP_DELETE_ATTR;
  377. sim.ops [i - 1].sv_attr = strcmp (&line[strlen (DELETE_KEYWORD)],
  378. MV_ATTR_NAME);
  379. }
  380. else /* delete value version */
  381. {
  382. memset (buff, 0, sizeof (buff));
  383. sim.ops [i - 1].type = OP_DELETE_VALUE;
  384. strncpy (buff, &line[strlen (DELETE_KEYWORD)],
  385. pos - &line[strlen (DELETE_KEYWORD)]);
  386. sim.ops [i - 1].sv_attr = strcmp (buff, MV_ATTR_NAME);
  387. sim.ops [i - 1].value_index = value2index (pos + 1);
  388. }
  389. }
  390. /* rename to <attribute> <valued>[ delete <attribute> <value>] */
  391. else if (strncmp (line, RENAME_KEYWORD, 10) == 0)
  392. {
  393. char *pos2;
  394. sim.ops [i - 1].type = OP_RENAME_ENTRY;
  395. pos = strchr (&line[strlen (RENAME_KEYWORD)], ' ');
  396. if (pos == NULL)
  397. {
  398. rc = -1;
  399. goto done;
  400. }
  401. memset (buff, 0, sizeof (buff));
  402. strncpy (buff, &line[strlen (RENAME_KEYWORD)], pos - &line[strlen (RENAME_KEYWORD)]);
  403. sim.ops [i - 1].sv_attr = strcmp (buff, MV_ATTR_NAME);
  404. pos2 = strstr (pos + 1, DELET_OLD_RDN_KEYWORD);
  405. if (pos2 == NULL) /* no delete old rdn part */
  406. {
  407. sim.ops [i - 1].value_index = value2index (pos + 1);
  408. sim.ops [i - 1].delete_old_rdn = 0;
  409. }
  410. else
  411. {
  412. memset (buff, 0, sizeof (buff));
  413. strncpy (buff, pos + 1, pos2 - pos - 1);
  414. sim.ops [i - 1].value_index = value2index (buff);
  415. pos2 += strlen (DELET_OLD_RDN_KEYWORD);
  416. pos = strchr (pos2, ' ');
  417. if (pos == NULL)
  418. {
  419. rc = -1;
  420. goto done;
  421. }
  422. memset (buff, 0, sizeof (buff));
  423. strncpy (buff, pos2, pos - pos2);
  424. sim.ops [i - 1].delete_old_rdn = 1;
  425. sim.ops [i - 1].old_rdn_sv_attr = strcmp (buff, MV_ATTR_NAME);
  426. sim.ops [i - 1].old_rdn_value_index = value2index (pos + 1);
  427. }
  428. }
  429. else
  430. {
  431. /* error */
  432. rc = -1;
  433. }
  434. done:
  435. if (rc)
  436. {
  437. /* invalid line */
  438. printf ("invalid operation: %s\n", line);
  439. exit (1);
  440. }
  441. }
  442. int value2index (char *value)
  443. {
  444. int i;
  445. for (i = 0; i < sim.value_count; i++)
  446. {
  447. if (strcmp (g_values[i], value) == 0)
  448. return i;
  449. }
  450. return -1;
  451. }
  452. void print_usage ()
  453. {
  454. printf ("usage: dnp_sim [-h] [-n <number of simulations> ] [-v] [-f <output file>]\n"
  455. "\t-h - print usage information\n"
  456. "\t-n <number of simulations>; default - 1\n"
  457. "\t-v - verbose mode\n"
  458. "\t-f <output file> - by default, results are printed to the screen\n"
  459. "\t-o <op file> - file that contains operation sequence to execute;\n"
  460. "\tby default, random sequence is generated.\n");
  461. }
  462. int count_values ()
  463. {
  464. int i;
  465. for (i = 0; g_values[i]; i++);
  466. return i;
  467. }
  468. void run_simulation ()
  469. {
  470. int *order;
  471. int i;
  472. int perm_count;
  473. Entry_State entry_first, entry_current;
  474. int error = 0;
  475. init_entry_state (&entry_first);
  476. fprintf (sim.fout, "initial entry state :\n");
  477. dump_entry_state (&entry_first);
  478. if (sim.ops == NULL)
  479. {
  480. generate_operations (&sim.ops, &sim.op_count);
  481. }
  482. fprintf (sim.fout, "initial operation set:\n");
  483. dump_operations (sim.ops, sim.op_count, NULL/* order */);
  484. perm_count = get_perm_count (sim.op_count);
  485. for (i = 0; i < perm_count; i++)
  486. {
  487. fprintf (sim.fout, "--------------------------------\n");
  488. fprintf (sim.fout, "simulation run %d\n", i + 1);
  489. fprintf (sim.fout, "--------------------------------\n");
  490. order = generate_operation_order (sim.op_count, i);
  491. if (i == 0)
  492. apply_operation_sequence (sim.ops, sim.op_count, order, &entry_first);
  493. else
  494. {
  495. apply_operation_sequence (sim.ops, sim.op_count, order, &entry_current);
  496. error |= compare_entry_state (&entry_first, &entry_current, i + 1);
  497. }
  498. }
  499. switch (error)
  500. {
  501. case 0: fprintf (sim.fout, "all runs left the entry in the same state\n");
  502. break;
  503. case 1: fprintf (sim.fout, "while value presence is consistent across all runs, "
  504. "the exact state does not match\n");
  505. break;
  506. case 3: fprintf (sim.fout, "the runs left entries in an inconsistent state\n");
  507. break;
  508. }
  509. free_operations (&sim.ops);
  510. }
  511. void generate_operations (Operation **ops, int *op_count)
  512. {
  513. int i;
  514. /* generate number operations in the sequence */
  515. *op_count = slapi_rand () % (MAX_OPS / 2) + 1;
  516. *ops = (Operation *)malloc (*op_count * sizeof (Operation));
  517. for (i = 0; i < *op_count; i ++)
  518. {
  519. generate_operation (&((*ops)[i]), i + 1);
  520. }
  521. }
  522. void generate_operation (Operation *op, int csn)
  523. {
  524. /* generate operation type */
  525. op->type = slapi_rand () % OP_END;
  526. op->csn = csn;
  527. /* choose if the operation applies to the single value or
  528. the multivalued attribute */
  529. op->sv_attr = slapi_rand () % 2;
  530. /* generate value to which operation applies */
  531. op->value_index = slapi_rand () % sim.value_count;
  532. if (op->type == OP_RENAME_ENTRY)
  533. {
  534. op->delete_old_rdn = slapi_rand () % 2;
  535. if (op->delete_old_rdn)
  536. {
  537. op->old_rdn_sv_attr = slapi_rand () % 2;
  538. op->old_rdn_value_index = slapi_rand () % sim.value_count;
  539. while (op->old_rdn_sv_attr == op->sv_attr &&
  540. op->old_rdn_value_index == op->value_index)
  541. {
  542. op->old_rdn_sv_attr = slapi_rand () % 2;
  543. op->old_rdn_value_index = slapi_rand () % sim.value_count;
  544. }
  545. }
  546. }
  547. }
  548. int* generate_operation_order (int op_count, int seq_num)
  549. {
  550. static int **perm_table = NULL;
  551. /* first request - generate pemutation table */
  552. if (seq_num == 0)
  553. {
  554. int elements [MAX_OPS];
  555. int i;
  556. if (perm_table)
  557. free_perm_table (&perm_table, op_count);
  558. perm_table = new_perm_table (op_count);
  559. for (i = 0; i < op_count; i++)
  560. elements [i] = i;
  561. generate_perm_table (elements, op_count, 0 /* static part */,
  562. perm_table);
  563. }
  564. return perm_table [seq_num];
  565. }
  566. void apply_operation_sequence (Operation *ops, int op_count, int *order, Entry_State *entry)
  567. {
  568. int i;
  569. init_entry_state (entry);
  570. if (!sim.verbose)
  571. {
  572. if (!sim.verbose)
  573. {
  574. fprintf (sim.fout, "operation_sequence for this run:\n");
  575. dump_operations (ops, op_count, order);
  576. }
  577. }
  578. for (i = 0; i < op_count; i++)
  579. {
  580. apply_operation (entry, &(ops [order[i]]));
  581. }
  582. if (!sim.verbose)
  583. {
  584. fprintf (sim.fout, "final entry state :\n");
  585. dump_entry_state (entry);
  586. }
  587. }
  588. void init_entry_state (Entry_State *entry)
  589. {
  590. memset (entry, 0, sizeof (*entry));
  591. entry->dn_csn_count = 1;
  592. init_sv_attr_state (&entry->sv_attr);
  593. init_mv_attr_state (&entry->mv_attr);
  594. }
  595. void init_sv_attr_state (SV_Attr_State *sv_attr)
  596. {
  597. memset (sv_attr, 0, sizeof (*sv_attr));
  598. sv_attr->attr_state.delete_csn = NOT_PRESENT;
  599. sv_attr->attr_state.present = 1;
  600. init_value_state (&sv_attr->current_value, 1);
  601. }
  602. void init_mv_attr_state (MV_Attr_State *mv_attr)
  603. {
  604. int i;
  605. memset (mv_attr, 0, sizeof (*mv_attr));
  606. mv_attr->attr_state.delete_csn = NOT_PRESENT;
  607. mv_attr->attr_state.present = 1;
  608. mv_attr->value_count = sim.value_count;
  609. for (i = 0; i < mv_attr->value_count; i++)
  610. {
  611. init_value_state (&(mv_attr->values[i]), i);
  612. }
  613. }
  614. void init_value_state (Value_State *val, int seq_num)
  615. {
  616. memset (val, 0, sizeof (*val));
  617. val->value_index = seq_num;
  618. val->present = 1;
  619. val->delete_csn = NOT_PRESENT;
  620. }
  621. void apply_operation (Entry_State *entry, Operation *op)
  622. {
  623. switch (op->type)
  624. {
  625. case OP_ADD_VALUE: apply_add_operation (entry, op);
  626. break;
  627. case OP_DELETE_VALUE: apply_value_delete_operation (entry, op);
  628. break;
  629. case OP_DELETE_ATTR: apply_attr_delete_operation (entry, op);
  630. break;
  631. case OP_RENAME_ENTRY: apply_rename_operation (entry, op);
  632. break;
  633. }
  634. if (sim.verbose)
  635. {
  636. fprintf (sim.fout, "operation: ");
  637. dump_operation (op);
  638. fprintf (sim.fout, "\n");
  639. dump_entry_state (entry);
  640. }
  641. }
  642. void free_operations (Operation **ops)
  643. {
  644. free (*ops);
  645. *ops = NULL;
  646. }
  647. int **new_perm_table (int op_count)
  648. {
  649. int i;
  650. int **perm_table;
  651. int perm_count = get_perm_count (op_count);
  652. perm_table = (int**)malloc (perm_count * sizeof (int*));
  653. for (i = 0; i < perm_count; i ++)
  654. perm_table [i] = (int*) malloc (op_count * sizeof (int));
  655. return perm_table;
  656. }
  657. void free_perm_table (int ***perm_table, int op_count)
  658. {
  659. int i;
  660. int perm_count = get_perm_count (op_count);
  661. for (i = 0; i < perm_count; i ++)
  662. free ((*perm_table)[i]);
  663. free (*perm_table);
  664. *perm_table = NULL;
  665. }
  666. void generate_perm_table (int *elements, int element_count, int static_part,
  667. int **perm_table)
  668. {
  669. int i;
  670. int elements_copy [MAX_OPS];
  671. int start_pos;
  672. if (element_count - 1 == static_part)
  673. {
  674. memcpy (*perm_table, elements, element_count * sizeof (int));
  675. return;
  676. }
  677. start_pos = 0;
  678. for (i = 0; i < element_count - static_part; i ++)
  679. {
  680. memcpy (elements_copy, elements, element_count * sizeof (int));
  681. elements_copy [static_part] = elements [static_part + i];
  682. elements_copy [static_part + i] = elements [static_part];
  683. generate_perm_table (elements_copy, element_count, static_part + 1,
  684. &perm_table [start_pos]);
  685. start_pos += get_perm_count (element_count - static_part - 1);
  686. }
  687. }
  688. int get_perm_count (int op_count)
  689. {
  690. int i;
  691. int perm_count = 1;
  692. for (i = 2; i <= op_count; i ++)
  693. perm_count *= i;
  694. return perm_count;
  695. }
  696. void apply_add_operation (Entry_State *entry, Operation *op)
  697. {
  698. if (op->sv_attr)
  699. {
  700. Value_State *val;
  701. Value_State temp_val;
  702. if (op->value_index == entry->sv_attr.current_value.value_index)
  703. {
  704. val = &entry->sv_attr.current_value;
  705. }
  706. else if (entry->sv_attr.pending_value &&
  707. op->value_index == entry->sv_attr.pending_value->value_index)
  708. {
  709. val = entry->sv_attr.pending_value;
  710. }
  711. else /* new value */
  712. {
  713. init_value_state (&temp_val, op->value_index);
  714. val = &temp_val;
  715. }
  716. if (val->presence_csn < op->csn)
  717. val->presence_csn = op->csn;
  718. resolve_sv_attr_state (entry, val);
  719. }
  720. else
  721. {
  722. if (entry->mv_attr.values[op->value_index].presence_csn < op->csn)
  723. {
  724. entry->mv_attr.values[op->value_index].presence_csn = op->csn;
  725. resolve_mv_attr_state (entry, &(entry->mv_attr.values[op->value_index]));
  726. }
  727. }
  728. }
  729. void apply_value_delete_operation (Entry_State *entry, Operation *op)
  730. {
  731. if (op->sv_attr)
  732. {
  733. if (entry->sv_attr.attr_state.delete_csn < op->csn)
  734. {
  735. entry->sv_attr.attr_state.delete_csn = op->csn;
  736. resolve_sv_attr_state (entry, NULL);
  737. }
  738. }
  739. else /* mv attr */
  740. {
  741. if (entry->mv_attr.values[op->value_index].delete_csn < op->csn)
  742. {
  743. entry->mv_attr.values[op->value_index].delete_csn = op->csn;
  744. resolve_mv_attr_state (entry, &(entry->mv_attr.values[op->value_index]));
  745. }
  746. }
  747. }
  748. void apply_attr_delete_operation (Entry_State *entry, Operation *op)
  749. {
  750. int i;
  751. if (op->sv_attr)
  752. {
  753. if (entry->sv_attr.attr_state.delete_csn < op->csn)
  754. {
  755. entry->sv_attr.attr_state.delete_csn = op->csn;
  756. resolve_sv_attr_state (entry, NULL);
  757. }
  758. }
  759. else /* mv attr */
  760. {
  761. if (entry->mv_attr.attr_state.delete_csn < op->csn)
  762. {
  763. entry->mv_attr.attr_state.delete_csn = op->csn;
  764. for (i = 0; i < sim.value_count; i++)
  765. {
  766. resolve_mv_attr_state (entry, &(entry->mv_attr.values[i]));
  767. }
  768. }
  769. }
  770. }
  771. void apply_rename_operation (Entry_State *entry, Operation *op)
  772. {
  773. int index;
  774. Operation del_op;
  775. /* insert new dn into dn_csn_list */
  776. index = dn_csn_add (entry, op->sv_attr, op->value_index, op->csn);
  777. /* issue delete value operation for the old rdn */
  778. if (op->delete_old_rdn)
  779. {
  780. del_op.type = OP_DELETE_VALUE;
  781. del_op.csn = op->csn;
  782. del_op.sv_attr = op->old_rdn_sv_attr;
  783. del_op.value_index = op->old_rdn_value_index;
  784. apply_value_delete_operation (entry, &del_op);
  785. }
  786. /* resolve state of the previous node in dn_csn_list */
  787. if (index > 0)
  788. {
  789. if (entry->dn_csns[index-1].sv_attr)
  790. {
  791. if (entry->dn_csns[index-1].value_index ==
  792. entry->sv_attr.current_value.value_index)
  793. {
  794. resolve_sv_attr_state (entry, &(entry->sv_attr.current_value));
  795. }
  796. else if (entry->sv_attr.pending_value &&
  797. entry->dn_csns[index-1].value_index ==
  798. entry->sv_attr.pending_value->value_index)
  799. {
  800. resolve_sv_attr_state (entry, entry->sv_attr.pending_value);
  801. }
  802. }
  803. else
  804. {
  805. int i = entry->dn_csns[index-1].value_index;
  806. resolve_mv_attr_state (entry, &(entry->mv_attr.values[i]));
  807. }
  808. }
  809. /* resolve state of the new dn */
  810. if (op->sv_attr)
  811. {
  812. Value_State *value;
  813. Value_State temp_val;
  814. if (op->value_index == entry->sv_attr.current_value.value_index)
  815. {
  816. value = &entry->sv_attr.current_value;
  817. }
  818. else if (entry->sv_attr.pending_value &&
  819. op->value_index == entry->sv_attr.pending_value->value_index)
  820. {
  821. value = entry->sv_attr.pending_value;
  822. }
  823. else /* new value */
  824. {
  825. init_value_state (&temp_val, op->value_index);
  826. value = &temp_val;
  827. }
  828. if (value->presence_csn == NOT_PRESENT || value->presence_csn < op->csn)
  829. value->presence_csn = op->csn;
  830. resolve_sv_attr_state (entry, value);
  831. }
  832. else
  833. {
  834. if (entry->mv_attr.values[op->value_index].presence_csn == NOT_PRESENT ||
  835. entry->mv_attr.values[op->value_index].presence_csn < op->csn)
  836. entry->mv_attr.values[op->value_index].presence_csn = op->csn;
  837. resolve_mv_attr_state (entry, &(entry->mv_attr.values[op->value_index]));
  838. }
  839. }
  840. void purge_mv_attr_state (Entry_State *entry, Value_State *value)
  841. {
  842. if (value->presence_csn > value->delete_csn)
  843. value->delete_csn = NOT_PRESENT;
  844. }
  845. void purge_sv_attr_state (Entry_State *entry)
  846. {
  847. if (entry->sv_attr.attr_state.delete_csn != NOT_PRESENT)
  848. {
  849. if (entry->sv_attr.pending_value)
  850. {
  851. if (entry->sv_attr.attr_state.delete_csn <
  852. entry->sv_attr.pending_value->presence_csn)
  853. {
  854. entry->sv_attr.attr_state.delete_csn = NOT_PRESENT;
  855. }
  856. }
  857. else
  858. {
  859. if (entry->sv_attr.attr_state.delete_csn <
  860. entry->sv_attr.current_value.presence_csn)
  861. entry->sv_attr.attr_state.delete_csn = NOT_PRESENT;
  862. }
  863. }
  864. }
  865. void resolve_mv_attr_state (Entry_State *entry, Value_State *value)
  866. {
  867. purge_mv_attr_state (entry, value);
  868. /* no deletes that effect the state */
  869. if (max_val (value->delete_csn, entry->mv_attr.attr_state.delete_csn) <
  870. value->presence_csn)
  871. {
  872. value->present = 1;
  873. return;
  874. }
  875. if (value->present) /* check if it should be removed based on the current state */
  876. {
  877. if (!value_distinguished_at_csn (entry, 0, value,
  878. max (value->delete_csn, entry->mv_attr.attr_state.delete_csn)))
  879. {
  880. value->present = 0;
  881. }
  882. }
  883. else /* not present - check if it should be restored */
  884. {
  885. if (value_distinguished_at_csn (entry, 0, value,
  886. max (value->delete_csn, entry->mv_attr.attr_state.delete_csn)))
  887. {
  888. value->present = 1;
  889. }
  890. }
  891. if (entry->mv_attr.attr_state.delete_csn == NOT_PRESENT)
  892. {
  893. entry->mv_attr.attr_state.present = 1;
  894. }
  895. else
  896. {
  897. int i;
  898. int distinguished = 0;
  899. for (i = 0; i < entry->mv_attr.value_count; i ++)
  900. {
  901. distinguished |= value_distinguished_at_csn (entry, 0,
  902. &(entry->mv_attr.values[i]),
  903. entry->mv_attr.attr_state.delete_csn);
  904. }
  905. entry->mv_attr.attr_state.present = distinguished;
  906. }
  907. }
  908. void resolve_sv_attr_state (Entry_State *entry, Value_State *value)
  909. {
  910. purge_sv_attr_state (entry);
  911. if (value)
  912. {
  913. /* existing value is modified */
  914. if (value == &(entry->sv_attr.current_value) ||
  915. value == entry->sv_attr.pending_value)
  916. {
  917. /* check if current value should be replaced with the pending value */
  918. if (entry->sv_attr.pending_value)
  919. {
  920. if (!value_distinguished_at_csn (entry, 1, &entry->sv_attr.current_value,
  921. entry->sv_attr.current_value.presence_csn))
  922. {
  923. /* replace current value with the pending value */
  924. memcpy (&entry->sv_attr.current_value, entry->sv_attr.pending_value,
  925. sizeof (Value_State));
  926. free (entry->sv_attr.pending_value);
  927. entry->sv_attr.pending_value = NULL;
  928. }
  929. }
  930. }
  931. else /* addition of a new value */
  932. {
  933. /* new value is before the current value; note that, for new value,
  934. presence_csn is the same as distinguished_csn */
  935. if (value->presence_csn < entry->sv_attr.current_value.presence_csn)
  936. {
  937. /* if new value is distinguished, it should become current and the
  938. current can become pending */
  939. if (value_distinguished_at_csn (entry, 1, value,
  940. entry->sv_attr.current_value.presence_csn))
  941. {
  942. if (entry->sv_attr.pending_value == NULL)
  943. {
  944. entry->sv_attr.pending_value = (Value_State*)
  945. malloc (sizeof (Value_State));
  946. memcpy (entry->sv_attr.pending_value, &entry->sv_attr.current_value,
  947. sizeof (Value_State));
  948. }
  949. memcpy (&entry->sv_attr.current_value, value, sizeof (Value_State));
  950. }
  951. }
  952. else /* new value is after the current value */
  953. {
  954. /* if current value is not distinguished, new value should
  955. become distinguished */
  956. if (!value_distinguished_at_csn (entry, 1, &entry->sv_attr.current_value,
  957. value->presence_csn))
  958. {
  959. memcpy (&entry->sv_attr.current_value, value, sizeof (Value_State));
  960. }
  961. else /* current value is distinguished - check if new value should replace
  962. the pending value */
  963. { if (entry->sv_attr.pending_value)
  964. {
  965. if (value->presence_csn > entry->sv_attr.pending_value->presence_csn)
  966. {
  967. memcpy (entry->sv_attr.pending_value, value, sizeof (Value_State));
  968. }
  969. }
  970. else
  971. {
  972. entry->sv_attr.pending_value = (Value_State*)malloc (sizeof (Value_State));
  973. memcpy (entry->sv_attr.pending_value, value, sizeof (Value_State));
  974. }
  975. }
  976. }
  977. }
  978. }
  979. /* update the attribute state */
  980. purge_sv_attr_state (entry);
  981. /* set attribute state */
  982. if (entry->sv_attr.attr_state.delete_csn != NOT_PRESENT &&
  983. !value_distinguished_at_csn (entry, 1, &entry->sv_attr.current_value,
  984. entry->sv_attr.attr_state.delete_csn))
  985. {
  986. entry->sv_attr.attr_state.present = 0;
  987. }
  988. else
  989. {
  990. entry->sv_attr.attr_state.present = 1;
  991. }
  992. }
  993. int value_distinguished_at_csn (Entry_State *entry, int sv_attr, Value_State *value, int csn)
  994. {
  995. int i;
  996. for (i = 0; i < entry->dn_csn_count; i++)
  997. {
  998. if (entry->dn_csns[i].csn > csn)
  999. break;
  1000. }
  1001. /* i is never equal to 0 because the csn of the first element is always
  1002. smaller than csn of any operation we can receive */
  1003. return (entry->dn_csns[i-1].value_index == value->value_index &&
  1004. entry->dn_csns[i-1].sv_attr == sv_attr);
  1005. }
  1006. int compare_entry_state (Entry_State *entry1, Entry_State *entry2, int run)
  1007. {
  1008. int i;
  1009. int error = 0;
  1010. error = compare_entry_state_quick (entry1, entry2, run);
  1011. if (error)
  1012. return 3;
  1013. /* compare dnc_csn list */
  1014. if (entry1->dn_csn_count != entry2->dn_csn_count)
  1015. {
  1016. fprintf (sim.fout, "dn_csn count is %d for run 1 and %d for run %d\n",
  1017. entry1->dn_csn_count, entry2->dn_csn_count, run);
  1018. error = 1;
  1019. }
  1020. for (i = 0; i < entry1->dn_csn_count; i++)
  1021. {
  1022. if (entry1->dn_csns [i].csn != entry2->dn_csns [i].csn ||
  1023. entry1->dn_csns [i].sv_attr != entry2->dn_csns [i].sv_attr ||
  1024. entry1->dn_csns [i].value_index != entry2->dn_csns [i].value_index)
  1025. {
  1026. fprintf (sim.fout,"elements %d of dn csn list are different:\n"
  1027. "\tfirst run: csn - %d, attr - %s, value - %s\n"
  1028. "\t%d run: csn - %d, attr - %s value - %s\n", i,
  1029. entry1->dn_csns [i].csn,
  1030. entry1->dn_csns [i].sv_attr ? SV_ATTR_NAME : MV_ATTR_NAME,
  1031. g_values[entry1->dn_csns [i].value_index],
  1032. run, entry2->dn_csns [i].csn,
  1033. entry2->dn_csns [i].sv_attr ? SV_ATTR_NAME : MV_ATTR_NAME,
  1034. g_values[entry2->dn_csns [i].value_index]);
  1035. error = 1;
  1036. }
  1037. }
  1038. error |= compare_sv_attr_state (&entry1->sv_attr, &entry2->sv_attr, run);
  1039. error |= compare_mv_attr_state (&entry1->mv_attr, &entry2->mv_attr, run);
  1040. if (error != 0)
  1041. {
  1042. return 1;
  1043. }
  1044. else
  1045. return 0;
  1046. }
  1047. /* just compare if the same attributes and values are present */
  1048. int compare_entry_state_quick (Entry_State *entry1, Entry_State *entry2, int run)
  1049. {
  1050. int error;
  1051. error = compare_sv_attr_state_quick (&entry1->sv_attr, &entry2->sv_attr, run);
  1052. error |= compare_mv_attr_state_quick (&entry1->mv_attr, &entry2->mv_attr, run);
  1053. return error;
  1054. }
  1055. int compare_sv_attr_state_quick (SV_Attr_State *sv_attr1, SV_Attr_State *sv_attr2, int run)
  1056. {
  1057. int error = 0;
  1058. if (sv_attr1->attr_state.present != sv_attr2->attr_state.present)
  1059. {
  1060. fprintf (sim.fout, "singlevalued attribute is %s present in the first run "
  1061. "but is %s present in the %d run\n",
  1062. sv_attr1->attr_state.present ? "" : "not",
  1063. sv_attr2->attr_state.present ? "" : "not", run);
  1064. return 1;
  1065. }
  1066. if (sv_attr1->attr_state.present &&
  1067. sv_attr1->current_value.value_index != sv_attr2->current_value.value_index)
  1068. {
  1069. fprintf (sim.fout, "different values for singlevalued attribute: %s for the \n"
  1070. "first run and %s for the %d run\n",
  1071. g_values [sv_attr1->current_value.value_index],
  1072. g_values [sv_attr2->current_value.value_index], run);
  1073. return 1;
  1074. }
  1075. return 0;
  1076. }
  1077. int compare_mv_attr_state_quick (MV_Attr_State *mv_attr1, MV_Attr_State *mv_attr2, int run)
  1078. {
  1079. int i;
  1080. int error = 0;
  1081. if (mv_attr1->attr_state.present != mv_attr2->attr_state.present)
  1082. {
  1083. fprintf (sim.fout, "multivalued attribute is %s present in the first run "
  1084. "but is %s present in the %d run\n",
  1085. mv_attr1->attr_state.present ? "" : "not",
  1086. mv_attr2->attr_state.present ? "" : "not", run);
  1087. return 1;
  1088. }
  1089. /* value count does not change during the iteration, so we don't have
  1090. to check if the count is the same for both attributes */
  1091. for (i = 0; i < mv_attr1->value_count; i++)
  1092. {
  1093. if (mv_attr1->values[i].present != mv_attr2->values[i].present)
  1094. {
  1095. fprintf (sim.fout, "value %s is %s present in the multivalued attribute\n"
  1096. "in the first run but %s present in the %d run\n",
  1097. g_values[i], mv_attr1->values[i].present ? "" : "not",
  1098. mv_attr2->values[i].present ? "" : "not", run);
  1099. error = 1;
  1100. }
  1101. }
  1102. return error;
  1103. }
  1104. int compare_sv_attr_state (SV_Attr_State *sv_attr1, SV_Attr_State *sv_attr2, int run)
  1105. {
  1106. int error = 0;
  1107. if (sv_attr1->attr_state.delete_csn != sv_attr2->attr_state.delete_csn)
  1108. {
  1109. fprintf (sim.fout, "singlevalued attribute deletion csn is %d for run 1 "
  1110. "but is %d for run %d\n", sv_attr1->attr_state.delete_csn,
  1111. sv_attr2->attr_state.delete_csn, run);
  1112. error = 1;
  1113. }
  1114. error |= compare_value_state (&sv_attr1->current_value, &sv_attr2->current_value, run);
  1115. if ((sv_attr1->pending_value && !sv_attr1->pending_value) ||
  1116. (!sv_attr1->pending_value && sv_attr1->pending_value))
  1117. {
  1118. fprintf (sim.fout, "pending value is %s present in the singlevalued attribute\n"
  1119. " in the first run but is %s in the %d run\n",
  1120. sv_attr1->pending_value ? "" : "not",
  1121. sv_attr2->pending_value ? "" : "not", run);
  1122. return 1;
  1123. }
  1124. if (sv_attr1->pending_value)
  1125. error |= compare_value_state (sv_attr1->pending_value, sv_attr2->pending_value, run);
  1126. return 0;
  1127. }
  1128. int compare_mv_attr_state (MV_Attr_State *mv_attr1, MV_Attr_State *mv_attr2, int run)
  1129. {
  1130. int error = 0;
  1131. int i;
  1132. if (mv_attr1->attr_state.delete_csn != mv_attr2->attr_state.delete_csn)
  1133. {
  1134. fprintf (sim.fout, "multivalued attribute deletion csn is %d for run 1 "
  1135. "but is %d for run %d\n", mv_attr1->attr_state.delete_csn,
  1136. mv_attr2->attr_state.delete_csn, run);
  1137. error = 1;
  1138. }
  1139. for (i = 0; i < mv_attr1->value_count; i++)
  1140. {
  1141. error |= compare_value_state (&mv_attr1->values[i], &mv_attr2->values[i], run);
  1142. }
  1143. return error;
  1144. }
  1145. int compare_value_state (Value_State *value1, Value_State *value2, int run)
  1146. {
  1147. int error = 0;
  1148. if (value1->presence_csn != value2->presence_csn)
  1149. {
  1150. fprintf (sim.fout, "multivalued attribute: presence csn for value %s is %d "
  1151. "in run 1 but is %d in run %d\n", g_values[value1->value_index],
  1152. value1->presence_csn, value2->presence_csn, run);
  1153. error = 1;
  1154. }
  1155. if (value1->delete_csn != value2->delete_csn)
  1156. {
  1157. fprintf (sim.fout, "multivalued attribute: delete csn for value %s is %d in run 1 "
  1158. "but is %d in run %d\n", g_values[value1->value_index],
  1159. value1->delete_csn, value2->delete_csn, run);
  1160. error = 1;
  1161. }
  1162. return error;
  1163. }
  1164. int dn_csn_add (Entry_State *entry, int sv_attr, int value_index, int csn)
  1165. {
  1166. int i;
  1167. for (i = 0; i < entry->dn_csn_count; i++)
  1168. {
  1169. if (entry->dn_csns[i].csn > csn)
  1170. break;
  1171. }
  1172. if (i < entry->dn_csn_count)
  1173. {
  1174. memcpy (&(entry->dn_csns[i+1]), &(entry->dn_csns[i]),
  1175. (entry->dn_csn_count - i) * sizeof (Dn_Csn));
  1176. }
  1177. entry->dn_csns[i].csn = csn;
  1178. entry->dn_csns[i].sv_attr = sv_attr;
  1179. entry->dn_csns[i].value_index = value_index;
  1180. entry->dn_csn_count ++;
  1181. return i;
  1182. }
  1183. void dump_operations (Operation *ops, int op_count, int *order)
  1184. {
  1185. int index;
  1186. int i;
  1187. for (i = 0; i < op_count; i ++)
  1188. {
  1189. if (order == NULL) /* current order */
  1190. index = i;
  1191. else
  1192. index = order [i];
  1193. dump_operation (&ops[index]);
  1194. }
  1195. fprintf (sim.fout, "\n");
  1196. }
  1197. void dump_operation (Operation *op)
  1198. {
  1199. switch (op->type)
  1200. {
  1201. case OP_ADD_VALUE:
  1202. fprintf (sim.fout, "\t%d add value %s to %s\n", op->csn,
  1203. g_values [op->value_index],
  1204. op->sv_attr ? SV_ATTR_NAME : MV_ATTR_NAME);
  1205. break;
  1206. case OP_DELETE_VALUE:
  1207. fprintf (sim.fout, "\t%d delete value %s from %s\n", op->csn,
  1208. g_values [op->value_index],
  1209. op->sv_attr ? SV_ATTR_NAME : MV_ATTR_NAME);
  1210. break;
  1211. case OP_DELETE_ATTR:
  1212. fprintf (sim.fout, "\t%d delete %s attribute\n", op->csn,
  1213. op->sv_attr ? SV_ATTR_NAME : MV_ATTR_NAME);
  1214. break;
  1215. case OP_RENAME_ENTRY:
  1216. fprintf (sim.fout, "\t%d rename entry to %s=%s", op->csn,
  1217. op->sv_attr ? SV_ATTR_NAME : MV_ATTR_NAME,
  1218. g_values [op->value_index]);
  1219. if (op->delete_old_rdn)
  1220. fprintf (sim.fout, " delete old rdn %s=%s\n",
  1221. op->old_rdn_sv_attr ? SV_ATTR_NAME : MV_ATTR_NAME,
  1222. g_values [op->old_rdn_value_index]);
  1223. else
  1224. fprintf (sim.fout, "\n");
  1225. break;
  1226. }
  1227. }
  1228. void dump_perm_table (int **perm_table, int op_count)
  1229. {
  1230. int i, j;
  1231. int perm_count = get_perm_count (op_count);
  1232. for (i = 0; i < op_count; i++)
  1233. {
  1234. for (j = 0; j < perm_count; j++)
  1235. {
  1236. fprintf (sim.fout, "%d ", perm_table [j][i]);
  1237. }
  1238. fprintf (sim.fout, "\n");
  1239. }
  1240. }
  1241. void dump_entry_state (Entry_State *entry)
  1242. {
  1243. dump_dn_csn_list (entry);
  1244. dump_sv_attr_state (&entry->sv_attr);
  1245. dump_mv_attr_state (&entry->mv_attr);
  1246. fprintf (sim.fout, "\n");
  1247. }
  1248. void dump_sv_attr_state (SV_Attr_State *sv_attr)
  1249. {
  1250. fprintf (sim.fout, "\tattribute %s is %s present", SV_ATTR_NAME,
  1251. sv_attr->attr_state.present ? "" : "not");
  1252. if (sv_attr->attr_state.present)
  1253. {
  1254. fprintf (sim.fout, " and has the value of %s\n",
  1255. g_values[sv_attr->current_value.value_index]);
  1256. }
  1257. else
  1258. {
  1259. fprintf (sim.fout, "\n");
  1260. }
  1261. if (sim.verbose)
  1262. {
  1263. fprintf (sim.fout, "\t\tdeletion csn: %d\n", sv_attr->attr_state.delete_csn);
  1264. fprintf (sim.fout, "\t\tcurrent value: ");
  1265. dump_value_state (&sv_attr->current_value, 1/* for single valued attr */);
  1266. if (sv_attr->pending_value)
  1267. {
  1268. fprintf (sim.fout, "\t\tpending value: ");
  1269. dump_value_state (sv_attr->pending_value, 1/* for single valued attr */);
  1270. }
  1271. }
  1272. }
  1273. void dump_mv_attr_state (MV_Attr_State *mv_attr)
  1274. {
  1275. int i;
  1276. fprintf (sim.fout, "\tattribute %s is %s present\n", MV_ATTR_NAME,
  1277. mv_attr->attr_state.present ? "" : "not");
  1278. if (sim.verbose)
  1279. {
  1280. fprintf (sim.fout, "\t\tdeletion csn: %d\n", mv_attr->attr_state.delete_csn);
  1281. }
  1282. for (i = 0; i < mv_attr->value_count; i++)
  1283. {
  1284. dump_value_state (&(mv_attr->values[i]), 0);
  1285. }
  1286. }
  1287. void dump_value_state (Value_State *value, int sv_attr)
  1288. {
  1289. if (!sv_attr)
  1290. {
  1291. fprintf (sim.fout, "\tvalue %s is %s present\n", g_values[value->value_index],
  1292. value->present ? "" : "not");
  1293. }
  1294. else
  1295. {
  1296. fprintf (sim.fout, "%s\n", g_values[value->value_index]);
  1297. }
  1298. if (sim.verbose)
  1299. {
  1300. fprintf (sim.fout, "\t\t\tpresence csn: %d\n", value->presence_csn);
  1301. fprintf (sim.fout, "\t\t\tdeletion value csn: %d\n", value->delete_csn);
  1302. }
  1303. }
  1304. void dump_dn_csn_list (Entry_State *entry)
  1305. {
  1306. int i;
  1307. fprintf (sim.fout, "\tdn csn list: \n");
  1308. for (i = 0; i < entry->dn_csn_count; i++)
  1309. {
  1310. fprintf (sim.fout, "\t\t %s=%s, csn: %d\n",
  1311. entry->dn_csns[i].sv_attr ? SV_ATTR_NAME : MV_ATTR_NAME,
  1312. g_values[entry->dn_csns[i].value_index], entry->dn_csns[i].csn);
  1313. }
  1314. }
  1315. /* misc functions */
  1316. int max_val (int a, int b)
  1317. {
  1318. if (a >= b)
  1319. return a;
  1320. else
  1321. return b;
  1322. }