summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/csn.c
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/slapd/csn.c
downloadds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.gz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.xz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/servers/slapd/csn.c')
-rw-r--r--ldap/servers/slapd/csn.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/ldap/servers/slapd/csn.c b/ldap/servers/slapd/csn.c
new file mode 100644
index 00000000..30243d88
--- /dev/null
+++ b/ldap/servers/slapd/csn.c
@@ -0,0 +1,383 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+/*
+ * csn.c - CSN
+ */
+
+#include <string.h>
+#include "slap.h"
+#include <prcountr.h>
+
+#define _CSN_TSTAMP_STRSIZE_STR "8"
+#define _CSN_SEQNUM_STRSIZE_STR "4"
+#define _CSN_REPLID_STRSIZE_STR "4"
+#define _CSN_SUBSEQNUM_STRSIZE_STR "4"
+
+#define _CSN_TSTAMP_SCANSTR "%"_CSN_TSTAMP_STRSIZE_STR"lx"
+#define _CSN_SEQNUM_SCANSTR "%"_CSN_SEQNUM_STRSIZE_STR"hx"
+#define _CSN_REPLID_SCANSTR "%"_CSN_REPLID_STRSIZE_STR"hx"
+#define _CSN_SUBSEQNUM_SCANSTR "%"_CSN_SUBSEQNUM_STRSIZE_STR"hx"
+
+#define _CSN_TSORDER_SPRINTSTR "%08x%04x%04x%04x"
+
+#define _CSN_TSORDER_TSTAMP_OFFSET 0
+#define _CSN_TSORDER_SEQNUM_OFFSET 8
+#define _CSN_TSORDER_REPLID_OFFSET 12
+#define _CSN_TSORDER_SUBSEQNUM_OFFSET 16
+
+static PRBool _csnIsValidString(const char *csnStr);
+
+/*
+ * Debugging counters.
+ */
+static int counters_created= 0;
+PR_DEFINE_COUNTER(slapi_csn_counter_created);
+PR_DEFINE_COUNTER(slapi_csn_counter_deleted);
+PR_DEFINE_COUNTER(slapi_csn_counter_exist);
+
+/*
+ * **************************************************************************
+ * CSN Functions
+ * **************************************************************************
+ */
+
+static void
+csn_create_counters()
+{
+ PR_CREATE_COUNTER(slapi_csn_counter_created,"Slapi_CSN","created","");
+ PR_CREATE_COUNTER(slapi_csn_counter_deleted,"Slapi_CSN","deleted","");
+ PR_CREATE_COUNTER(slapi_csn_counter_exist,"Slapi_CSN","exist","");
+ counters_created= 1;
+}
+
+CSN *csn_new()
+{
+ if(!counters_created)
+ {
+ csn_create_counters();
+ }
+ PR_INCREMENT_COUNTER(slapi_csn_counter_created);
+ PR_INCREMENT_COUNTER(slapi_csn_counter_exist);
+ return (CSN*)slapi_ch_calloc(sizeof(CSN),1);
+}
+
+CSN *csn_new_by_string(const char *s)
+{
+ CSN *newcsn= NULL;
+ if(s!=NULL)
+ {
+ if(_csnIsValidString(s))
+ {
+ newcsn= csn_new();
+ csn_init_by_string(newcsn,s);
+ }
+ }
+ return newcsn;
+}
+
+void csn_init(CSN *csn)
+{
+ if(csn!=NULL)
+ {
+ memset(csn,0,sizeof(CSN));
+ }
+}
+
+void csn_init_by_csn(CSN *csn1,const CSN *csn2)
+{
+ if(csn2!=NULL)
+ {
+ memcpy(csn1,csn2,sizeof(CSN));
+ }
+ else
+ {
+ csn_init(csn1);
+ }
+}
+
+void csn_init_by_string(CSN *csn, const char *s)
+{
+ time_t csnTime= 0;
+ PRUint16 csnSeqNum= 0;
+ ReplicaId rid= 0;
+ PRUint16 csnSubSeqNum= 0;
+
+ if(_csnIsValidString(s))
+ {
+ /* JCM - char2hex faster */
+ sscanf((s+_CSN_TSORDER_TSTAMP_OFFSET), _CSN_TSTAMP_SCANSTR, &csnTime); /* JCM - scanf is very slow */
+ sscanf((s+_CSN_TSORDER_SEQNUM_OFFSET), _CSN_SEQNUM_SCANSTR, &csnSeqNum);/* JCM - scanf is very slow */
+ sscanf((s+_CSN_TSORDER_REPLID_OFFSET), _CSN_REPLID_SCANSTR, &rid);/* JCM - scanf is very slow */
+ sscanf((s+_CSN_TSORDER_SUBSEQNUM_OFFSET), _CSN_SUBSEQNUM_SCANSTR, &csnSubSeqNum);/* JCM - scanf is very slow */
+ csn->tstamp= csnTime;
+ csn->seqnum= csnSeqNum;
+ csn->rid= rid;
+ csn->subseqnum= csnSubSeqNum;
+ }
+}
+
+CSN *csn_dup(const CSN *csn)
+{
+ CSN *newcsn= NULL;
+ if(csn!=NULL)
+ {
+ newcsn= csn_new();
+ csn_init_by_csn(newcsn,csn);
+ }
+ return newcsn;
+}
+
+void csn_done(CSN *csn)
+{
+}
+
+void csn_free(CSN **csn)
+{
+ if(csn!=NULL && *csn!=NULL)
+ {
+ if(!counters_created)
+ {
+ csn_create_counters();
+ }
+ PR_INCREMENT_COUNTER(slapi_csn_counter_deleted);
+ PR_DECREMENT_COUNTER(slapi_csn_counter_exist);
+ slapi_ch_free((void **)csn);
+ }
+ return;
+}
+
+void csn_set_replicaid(CSN *csn, ReplicaId rid)
+{
+ csn->rid= rid;
+}
+
+void csn_set_time(CSN *csn, time_t csntime)
+{
+ csn->tstamp= csntime;
+}
+
+void csn_set_seqnum(CSN *csn, PRUint16 seqnum)
+{
+ csn->seqnum= seqnum;
+}
+
+ReplicaId csn_get_replicaid(const CSN *csn)
+{
+ return csn->rid;
+}
+
+PRUint16 csn_get_seqnum(const CSN *csn)
+{
+ return csn->seqnum;
+}
+
+time_t csn_get_time(const CSN *csn)
+{
+ if(csn==NULL)
+ {
+ return 0;
+ }
+ else
+ {
+ return csn->tstamp;
+ }
+}
+
+
+/*
+ * WARNING: ss must point to memory at least CSN_STRSIZE bytes long,
+ * WARNING: or be NULL, which means this function will allocate the
+ * WARNING: memory, which must be free'd by the caller.
+ */
+char *
+csn_as_string(const CSN *csn, PRBool replicaIdOrder, char *ss)
+{
+ char *s= ss;
+ if(s==NULL)
+ {
+ s= slapi_ch_malloc(CSN_STRSIZE);
+ }
+ if(csn==NULL)
+ {
+ s[0]= '\0';
+ }
+ else
+ {
+ /* JCM - hex2char would be quicker */
+ sprintf(s,"%08lx%04x%04x%04x",
+ csn->tstamp,csn->seqnum,csn->rid, csn->subseqnum);
+ }
+ return s;
+}
+
+
+/*
+ * WARNING: ss must point to memory at least (7+CSN_STRSIZE) bytes long,
+ * WARNING: or be NULL, which means this function will allocate the
+ * WARNING: memory, which must be free'd by the caller.
+ */
+char *
+csn_as_attr_option_string(CSNType t,const CSN *csn,char *ss)
+{
+ char *s= ss;
+ if(csn!=NULL)
+ {
+ if(s==NULL)
+ {
+ s= slapi_ch_malloc(8+CSN_STRSIZE);
+ }
+ s[0]= ';';
+ switch(t)
+ {
+ case CSN_TYPE_UNKNOWN:
+ s[1]= 'x';
+ s[2]= '1';
+ break;
+ case CSN_TYPE_NONE:
+ s[1]= 'x';
+ s[2]= '2';
+ break;
+ case CSN_TYPE_ATTRIBUTE_DELETED:
+ s[1]= 'a';
+ s[2]= 'd';
+ break;
+ case CSN_TYPE_VALUE_UPDATED:
+ s[1]= 'v';
+ s[2]= 'u';
+ break;
+ case CSN_TYPE_VALUE_DELETED:
+ s[1]= 'v';
+ s[2]= 'd';
+ break;
+ case CSN_TYPE_VALUE_DISTINGUISHED:
+ s[1]= 'm';
+ s[2]= 'd';
+ break;
+ }
+ s[3]= 'c';
+ s[4]= 's';
+ s[5]= 'n';
+ s[6]= '-';
+ csn_as_string(csn,PR_FALSE,s+7);
+ }
+ return s;
+}
+
+int
+csn_compare(const CSN *csn1, const CSN *csn2)
+{
+ PRInt32 retVal;
+ if(csn1!=NULL && csn2!=NULL)
+ {
+ /* csns can't be compared via memcmp (previuos version of the code)
+ because, on NT, bytes are reversed */
+ if (csn1->tstamp < csn2->tstamp)
+ retVal = -1;
+ else if (csn1->tstamp > csn2->tstamp)
+ retVal = 1;
+ else
+ {
+ if (csn1->seqnum < csn2->seqnum)
+ retVal = -1;
+ else if (csn1->seqnum > csn2->seqnum)
+ retVal = 1;
+ else
+ {
+ if (csn1->rid < csn2->rid)
+ retVal = -1;
+ else if (csn1->rid > csn2->rid)
+ retVal = 1;
+ else
+ {
+ if (csn1->subseqnum < csn2->subseqnum)
+ retVal = -1;
+ else if (csn1->subseqnum > csn2->subseqnum)
+ retVal = 1;
+ else
+ retVal = 0;
+ }
+ }
+ }
+
+ }
+ else if(csn1!=NULL && csn2==NULL)
+ {
+ retVal= 1; /* csn1>csn2 */
+ }
+ else if (csn1==NULL && csn2!=NULL)
+ {
+ retVal= -1; /* csn1<csn2 */
+ }
+ else /* (csn1==NULL && csn2==NULL) */
+ {
+ retVal= 0; /* The same */
+ }
+
+ return(retVal);
+}
+
+time_t csn_time_difference(const CSN *csn1, const CSN *csn2)
+{
+ return csn_get_time(csn1) - csn_get_time(csn2);
+}
+
+const CSN *
+csn_max(const CSN *csn1,const CSN *csn2)
+{
+ if(csn_compare(csn1, csn2)>0)
+ {
+ return csn1;
+ }
+ else
+ {
+ return csn2;
+ }
+}
+
+int csn_increment_subsequence (CSN *csn)
+{
+ if (csn == NULL)
+ {
+ return -1;
+ }
+ else if (csn->subseqnum == 0xFFFFFFFF)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, NULL,
+ "csn_increment_subsequence: subsequence overflow\n");
+
+ return -1;
+ }
+ else
+ {
+ csn->subseqnum ++;
+ return 0;
+ }
+}
+
+/*
+ * sizeof(vucsn-011111111222233334444)
+ * Does not include the trailing '\0'
+ */
+size_t
+csn_string_size()
+{
+ return LDIF_CSNPREFIX_MAXLENGTH + _CSN_VALIDCSN_STRLEN;
+}
+
+static PRBool
+_csnIsValidString(const char *s)
+{
+ if(NULL == s) {
+ return(PR_FALSE);
+ }
+ if(strlen(s) < _CSN_VALIDCSN_STRLEN) {
+ return(PR_FALSE);
+ }
+
+ /* some more checks on validity of tstamp portion? */
+ return(PR_TRUE);
+}