| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * 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);
- }
|