csn.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  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. /*
  13. * csn.c - CSN
  14. */
  15. #include <string.h>
  16. #include "slap.h"
  17. #define _CSN_TSORDER_TSTAMP_OFFSET 0
  18. #define _CSN_TSORDER_SEQNUM_OFFSET 8
  19. #define _CSN_TSORDER_REPLID_OFFSET 12
  20. #define _CSN_TSORDER_SUBSEQNUM_OFFSET 16
  21. static PRBool _csnIsValidString(const char *csnStr);
  22. /*
  23. * Debugging counters.
  24. */
  25. #ifdef DEBUG
  26. static int counters_created= 0;
  27. static Slapi_Counter *slapi_csn_counter_created;
  28. static Slapi_Counter *slapi_csn_counter_deleted;
  29. static Slapi_Counter *slapi_csn_counter_exist;
  30. #endif
  31. /*
  32. * **************************************************************************
  33. * CSN Functions
  34. * **************************************************************************
  35. */
  36. #ifdef DEBUG
  37. static void
  38. csn_create_counters()
  39. {
  40. slapi_csn_counter_created = slapi_counter_new();
  41. slapi_csn_counter_deleted = slapi_counter_new();
  42. slapi_csn_counter_exist = slapi_counter_new();
  43. counters_created= 1;
  44. }
  45. #endif
  46. CSN *csn_new()
  47. {
  48. #ifdef DEBUG
  49. if(!counters_created)
  50. {
  51. csn_create_counters();
  52. }
  53. slapi_counter_increment(slapi_csn_counter_created);
  54. slapi_counter_increment(slapi_csn_counter_exist);
  55. #endif
  56. return (CSN*)slapi_ch_calloc(sizeof(CSN),1);
  57. }
  58. CSN *csn_new_by_string(const char *s)
  59. {
  60. CSN *newcsn= NULL;
  61. if(s!=NULL)
  62. {
  63. if(_csnIsValidString(s))
  64. {
  65. newcsn= csn_new();
  66. csn_init_by_string(newcsn,s);
  67. }
  68. }
  69. return newcsn;
  70. }
  71. void csn_init(CSN *csn)
  72. {
  73. if(csn!=NULL)
  74. {
  75. memset(csn,0,sizeof(CSN));
  76. }
  77. }
  78. void csn_init_by_csn(CSN *csn1,const CSN *csn2)
  79. {
  80. if(csn2!=NULL)
  81. {
  82. memcpy(csn1,csn2,sizeof(CSN));
  83. }
  84. else
  85. {
  86. csn_init(csn1);
  87. }
  88. }
  89. void csn_init_by_string(CSN *csn, const char *s)
  90. {
  91. if(_csnIsValidString(s)) {
  92. /* yes - time_t is long - but the CSN will only ever store the lowest 4 bytes of
  93. the timestamp */
  94. csn->tstamp = slapi_str_to_u32(s+_CSN_TSORDER_TSTAMP_OFFSET);
  95. csn->seqnum = slapi_str_to_u16(s+_CSN_TSORDER_SEQNUM_OFFSET);
  96. csn->rid = slapi_str_to_u16(s+_CSN_TSORDER_REPLID_OFFSET);
  97. csn->subseqnum = slapi_str_to_u16(s+_CSN_TSORDER_SUBSEQNUM_OFFSET);
  98. }
  99. }
  100. CSN *csn_dup(const CSN *csn)
  101. {
  102. CSN *newcsn= NULL;
  103. if(csn!=NULL)
  104. {
  105. newcsn= csn_new();
  106. csn_init_by_csn(newcsn,csn);
  107. }
  108. return newcsn;
  109. }
  110. void csn_done(CSN *csn)
  111. {
  112. }
  113. void csn_free(CSN **csn)
  114. {
  115. if(csn!=NULL && *csn!=NULL)
  116. {
  117. #ifdef DEBUG
  118. if(!counters_created)
  119. {
  120. csn_create_counters();
  121. }
  122. slapi_counter_increment(slapi_csn_counter_deleted);
  123. slapi_counter_increment(slapi_csn_counter_exist);
  124. #endif
  125. slapi_ch_free((void **)csn);
  126. }
  127. return;
  128. }
  129. void csn_set_replicaid(CSN *csn, ReplicaId rid)
  130. {
  131. csn->rid= rid;
  132. }
  133. void csn_set_time(CSN *csn, time_t csntime)
  134. {
  135. csn->tstamp= csntime;
  136. }
  137. void csn_set_seqnum(CSN *csn, PRUint16 seqnum)
  138. {
  139. csn->seqnum= seqnum;
  140. }
  141. ReplicaId csn_get_replicaid(const CSN *csn)
  142. {
  143. return csn->rid;
  144. }
  145. PRUint16 csn_get_seqnum(const CSN *csn)
  146. {
  147. return csn->seqnum;
  148. }
  149. PRUint16 csn_get_subseqnum(const CSN *csn)
  150. {
  151. return csn->subseqnum;
  152. }
  153. time_t csn_get_time(const CSN *csn)
  154. {
  155. if(csn==NULL)
  156. {
  157. return 0;
  158. }
  159. else
  160. {
  161. return csn->tstamp;
  162. }
  163. }
  164. /*
  165. * WARNING: ss must point to memory at least CSN_STRSIZE bytes long,
  166. * WARNING: or be NULL, which means this function will allocate the
  167. * WARNING: memory, which must be free'd by the caller.
  168. */
  169. char *
  170. csn_as_string(const CSN *csn, PRBool replicaIdOrder, char *ss)
  171. {
  172. char *s= ss;
  173. if(s==NULL)
  174. {
  175. s= slapi_ch_malloc(CSN_STRSIZE);
  176. }
  177. if(csn==NULL)
  178. {
  179. s[0]= '\0';
  180. }
  181. else
  182. {
  183. char *ptr = slapi_u32_to_hex(csn->tstamp, s, 0);
  184. ptr = slapi_u16_to_hex(csn->seqnum, ptr, 0);
  185. ptr = slapi_u16_to_hex(csn->rid, ptr, 0);
  186. ptr = slapi_u16_to_hex(csn->subseqnum, ptr, 0);
  187. *ptr = 0;
  188. }
  189. return s;
  190. }
  191. /*
  192. * WARNING: ss must point to memory at least (7+CSN_STRSIZE) bytes long,
  193. * WARNING: or be NULL, which means this function will allocate the
  194. * WARNING: memory, which must be free'd by the caller.
  195. */
  196. char *
  197. csn_as_attr_option_string(CSNType t,const CSN *csn,char *ss)
  198. {
  199. char *s= ss;
  200. if(csn!=NULL)
  201. {
  202. if(s==NULL)
  203. {
  204. s= slapi_ch_malloc(8+CSN_STRSIZE);
  205. }
  206. s[0]= ';';
  207. switch(t)
  208. {
  209. case CSN_TYPE_UNKNOWN:
  210. s[1]= 'x';
  211. s[2]= '1';
  212. break;
  213. case CSN_TYPE_NONE:
  214. s[1]= 'x';
  215. s[2]= '2';
  216. break;
  217. case CSN_TYPE_ATTRIBUTE_DELETED:
  218. s[1]= 'a';
  219. s[2]= 'd';
  220. break;
  221. case CSN_TYPE_VALUE_UPDATED:
  222. s[1]= 'v';
  223. s[2]= 'u';
  224. break;
  225. case CSN_TYPE_VALUE_DELETED:
  226. s[1]= 'v';
  227. s[2]= 'd';
  228. break;
  229. case CSN_TYPE_VALUE_DISTINGUISHED:
  230. s[1]= 'm';
  231. s[2]= 'd';
  232. break;
  233. }
  234. s[3]= 'c';
  235. s[4]= 's';
  236. s[5]= 'n';
  237. s[6]= '-';
  238. csn_as_string(csn,PR_FALSE,s+7);
  239. }
  240. return s;
  241. }
  242. int
  243. csn_compare_ext(const CSN *csn1, const CSN *csn2, unsigned int flags)
  244. {
  245. PRInt32 retVal;
  246. if(csn1!=NULL && csn2!=NULL)
  247. {
  248. /* csns can't be compared via memcmp (previuos version of the code)
  249. because, on NT, bytes are reversed */
  250. if (csn1->tstamp < csn2->tstamp)
  251. retVal = -1;
  252. else if (csn1->tstamp > csn2->tstamp)
  253. retVal = 1;
  254. else
  255. {
  256. if (csn1->seqnum < csn2->seqnum)
  257. retVal = -1;
  258. else if (csn1->seqnum > csn2->seqnum)
  259. retVal = 1;
  260. else
  261. {
  262. if (csn1->rid < csn2->rid)
  263. retVal = -1;
  264. else if (csn1->rid > csn2->rid)
  265. retVal = 1;
  266. else if (!(flags & CSN_COMPARE_SKIP_SUBSEQ))
  267. {
  268. if (csn1->subseqnum < csn2->subseqnum)
  269. retVal = -1;
  270. else if (csn1->subseqnum > csn2->subseqnum)
  271. retVal = 1;
  272. else
  273. retVal = 0;
  274. }
  275. else
  276. retVal = 0;
  277. }
  278. }
  279. }
  280. else if(csn1!=NULL && csn2==NULL)
  281. {
  282. retVal= 1; /* csn1>csn2 */
  283. }
  284. else if (csn1==NULL && csn2!=NULL)
  285. {
  286. retVal= -1; /* csn1<csn2 */
  287. }
  288. else /* (csn1==NULL && csn2==NULL) */
  289. {
  290. retVal= 0; /* The same */
  291. }
  292. return(retVal);
  293. }
  294. int
  295. csn_compare(const CSN *csn1, const CSN *csn2)
  296. {
  297. return csn_compare_ext(csn1, csn2, 0);
  298. }
  299. time_t csn_time_difference(const CSN *csn1, const CSN *csn2)
  300. {
  301. return csn_get_time(csn1) - csn_get_time(csn2);
  302. }
  303. const CSN *
  304. csn_max(const CSN *csn1,const CSN *csn2)
  305. {
  306. if(csn_compare(csn1, csn2)>0)
  307. {
  308. return csn1;
  309. }
  310. else
  311. {
  312. return csn2;
  313. }
  314. }
  315. int csn_increment_subsequence (CSN *csn)
  316. {
  317. PRUint16 maxsubseq = (PRUint16)0xFFFFFFFF;
  318. if (csn == NULL)
  319. {
  320. return -1;
  321. }
  322. else if (csn->subseqnum == maxsubseq)
  323. {
  324. slapi_log_error(SLAPI_LOG_FATAL, NULL,
  325. "csn_increment_subsequence: subsequence overflow\n");
  326. return -1;
  327. }
  328. else
  329. {
  330. csn->subseqnum ++;
  331. return 0;
  332. }
  333. }
  334. /*
  335. * sizeof(vucsn-011111111222233334444)
  336. * Does not include the trailing '\0'
  337. */
  338. size_t
  339. csn_string_size()
  340. {
  341. return LDIF_CSNPREFIX_MAXLENGTH + _CSN_VALIDCSN_STRLEN;
  342. }
  343. static PRBool
  344. _csnIsValidString(const char *s)
  345. {
  346. if(NULL == s) {
  347. return(PR_FALSE);
  348. }
  349. if(strlen(s) < _CSN_VALIDCSN_STRLEN) {
  350. return(PR_FALSE);
  351. }
  352. /* some more checks on validity of tstamp portion? */
  353. return(PR_TRUE);
  354. }