Skip to content

Commit

Permalink
Use system time in microseconds as the timestamp format
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob Vaterlaus committed Sep 13, 2012
1 parent fc1ea10 commit 4f6df25
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 16 deletions.
9 changes: 8 additions & 1 deletion README.txt
Expand Up @@ -18,7 +18,7 @@ support) that are useful for the Django database backend, so I targeted that
instead of 0.6. Unfortunately, the Cassandra Thrift API changed between 0.6 and 0.7,
so the two version are incompatible.

I currently use the 1.0.3 release. That's the only version I test against, so no
I currently use the 1.0.10 release. That's the only version I test against, so no
promises if you try it with a different version. I have tested earlier versions
against the 0.7.x and 0.8.x versions of Cassandra with no problem, so I would expect
that it would still work.
Expand Down Expand Up @@ -199,6 +199,13 @@ Known Issues
daemon, etc. Currently you just get a somewhat uninformative exception in
these cases.

Changes for 0.2.4
=================
- switch the timestamp format to use the system time in microseconds to be
consistent with the standard Cassandra timestamps used by other Cassandra
components (e.g. the Cassandra CLI) and to hopefully eliminate issues with
timestamp collisions across multiple Django processes.

Changes for 0.2.3
=================
- fixed a bug with the retry/reconnect logic where it would use a stale Cassandra
Expand Down
37 changes: 22 additions & 15 deletions django_cassandra/db/utils.py
Expand Up @@ -142,26 +142,33 @@ def combine_rows(rows1, rows2, op, primary_key_column):

return combined_rows

_last_time = None
_last_counter = None
_last_timestamp = None

def get_next_timestamp():
# The timestamp is a 64-bit integer
# We use the top 44 bits for the current time in milliseconds since the
# epoch. The low 20 bits are a counter that is incremented if the current
# time value from the top 44 bits is the same as the last
# time value. This guarantees that a new timestamp is always
# greater than the previous timestamp
global _last_time, _last_counter
current_time = int(time.time() * 1000)
# We now use the standard Cassandra timestamp format of the
# current system time in microseconds. We also keep track of the
# last timestamp we returned and if the current time is less than
# that, then we just advance the timestamp by 1 to make sure we
# return monotonically increasing timestamps. Note that this isn't
# guaranteed to handle the fairly common Django deployment model of
# having multiple Django processes that are dispatched to from a
# web server like Apache. In practice I don't think that case will be
# a problem though (at least with current hardware) because I don't
# think you could have two consecutive calls to Django from another
# process that would be dispatched to two different Django processes
# that would happen in the same microsecond.

global _last_timestamp

timestamp = int(time.time() * 1000000)

if (_last_time == None) or (current_time > _last_time):
_last_time = current_time
_last_counter = 0
else:
_last_counter += 1
if (_last_timestamp != None) and (timestamp <= _last_timestamp):
timestamp = _last_timestamp + 1

_last_timestamp = timestamp

return _last_time * 0x100000 + _last_counter
return timestamp

def convert_string_to_list(s):
# FIXME: Shouldn't use eval here, because of security considerations
Expand Down

0 comments on commit 4f6df25

Please sign in to comment.