diff options
Diffstat (limited to 'ldap/servers/slapd/csngen.c')
-rw-r--r-- | ldap/servers/slapd/csngen.c | 73 |
1 files changed, 54 insertions, 19 deletions
diff --git a/ldap/servers/slapd/csngen.c b/ldap/servers/slapd/csngen.c index 7fcd379d..137b995c 100644 --- a/ldap/servers/slapd/csngen.c +++ b/ldap/servers/slapd/csngen.c @@ -60,6 +60,9 @@ #define STATE_FORMAT "%8x%8x%8x%4hx%4hx" #define STATE_LENGTH 32 #define MAX_VAL(x,y) ((x)>(y)?(x):(y)) +#define CSN_CALC_TSTAMP(gen) ((gen)->state.sampled_time + \ + (gen)->state.local_offset + \ + (gen)->state.remote_offset) /* * ************************************************************************** @@ -273,8 +276,7 @@ csngen_new_csn (CSNGen *gen, CSN **csn, PRBool notify) gen->state.seq_num = 0; } - (*csn)->tstamp = gen->state.sampled_time + gen->state.local_offset + - gen->state.remote_offset; + (*csn)->tstamp = CSN_CALC_TSTAMP(gen); (*csn)->seqnum = gen->state.seq_num ++; (*csn)->rid = gen->state.rid; (*csn)->subseqnum = 0; @@ -308,8 +310,9 @@ void csngen_abort_csn (CSNGen *gen, const CSN *csn) of time so that it does not generate smaller csns */ int csngen_adjust_time (CSNGen *gen, const CSN* csn) { - time_t remote_time, remote_offset; + time_t remote_time, remote_offset, cur_time; PRUint16 remote_seqnum; + int rc; if (gen == NULL || csn == NULL) return CSN_INVALID_PARAMETER; @@ -319,21 +322,38 @@ int csngen_adjust_time (CSNGen *gen, const CSN* csn) PR_RWLock_Wlock (gen->lock); - if (remote_seqnum > gen->state.seq_num ) - { - if (remote_seqnum < CSN_MAX_SEQNUM) - { - gen->state.seq_num = remote_seqnum + 1; - } - else - { - remote_time++; - } - } + /* make sure we have the current time */ + csngen_update_time(); + cur_time = g_sampled_time; + + /* make sure sampled_time is current */ + /* must only call adjust_local_time if the current time is greater than + the generator state time */ + if ((cur_time > gen->state.sampled_time) && + (CSN_SUCCESS != (rc = _csngen_adjust_local_time(gen, cur_time)))) + { + /* _csngen_adjust_local_time will log error */ + PR_RWLock_Unlock (gen->lock); + csngen_dump_state(gen); + return rc; + } - if (remote_time >= gen->state.sampled_time) + cur_time = CSN_CALC_TSTAMP(gen); + if (remote_time >= cur_time) { - remote_offset = remote_time - gen->state.sampled_time; + if (remote_seqnum > gen->state.seq_num ) + { + if (remote_seqnum < CSN_MAX_SEQNUM) + { + gen->state.seq_num = remote_seqnum + 1; + } + else + { + remote_time++; + } + } + + remote_offset = remote_time - cur_time; if (remote_offset > gen->state.remote_offset) { if (remote_offset <= CSN_MAX_TIME_ADJUST) @@ -346,10 +366,18 @@ int csngen_adjust_time (CSNGen *gen, const CSN* csn) "adjustment limit exceeded; value - %ld, limit - %ld\n", remote_offset, (long)CSN_MAX_TIME_ADJUST); PR_RWLock_Unlock (gen->lock); + csngen_dump_state(gen); return CSN_LIMIT_EXCEEDED; } } - } + } + else if (gen->state.remote_offset > 0) + { + /* decrease remote offset? */ + /* how to decrease remote offset but ensure that we don't + generate a duplicate CSN, or a CSN smaller than one we've already + generated? */ + } PR_RWLock_Unlock (gen->lock); @@ -576,7 +604,14 @@ _csngen_adjust_local_time (CSNGen *gen, time_t cur_time) { time_t time_diff = cur_time - gen->state.sampled_time; - if (time_diff > 0) + if (time_diff == 0) { + /* This is a no op - _csngen_adjust_local_time should never be called + in this case, because there is nothing to adjust - but just return + here to protect ourselves + */ + return CSN_SUCCESS; + } + else if (time_diff > 0) { gen->state.sampled_time = cur_time; if (time_diff > gen->state.local_offset) @@ -588,7 +623,7 @@ _csngen_adjust_local_time (CSNGen *gen, time_t cur_time) return CSN_SUCCESS; } - else /* time was turend back */ + else /* time was turned back */ { if (abs (time_diff) > CSN_MAX_TIME_ADJUST) { |