Go to the documentation of this file.00001
00002
00003 """
00004 usage: %(progname)s [args]
00005 """
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 import math
00059 import random
00060 import socket
00061 import os, sys
00062 import time
00063 import threading
00064 import string, struct
00065
00066 import getopt
00067
00068
00069
00070 QUEUE_SIZE = 100
00071
00072
00073
00074
00075
00076 MAX_RANDOM = sys.maxint
00077 rand = random.Random()
00078 ip = ''
00079 lock = threading.RLock()
00080 lastguid = ''
00081 try:
00082 ip = socket.gethostbyname(socket.gethostname())
00083 except (socket.gaierror):
00084 ip = '10'
00085 for i in range(3):
00086 ip += '.' + str(rand.randrange(1, 254))
00087 hexip = ''.join(["%04x" % long(i) for i in ip.split('.')])
00088 ipaddrStr = socket.inet_aton(ip)
00089 (ipaddr, ) = struct.unpack(">I", ipaddrStr)
00090
00091 def encode64Char(i):
00092 if i<10: return chr(i+48)
00093 elif i<38: return chr(i-10+64)
00094 elif i<64: return chr(i-38+97)
00095 raise Error
00096
00097 def pack64(i, bytes=6):
00098 parts = []
00099 for j in range(bytes):
00100 a = i & 0x3f
00101 i = (i >> 6)
00102 parts.append(encode64Char(a))
00103 parts.reverse()
00104 p = string.join(parts, "")
00105 return p
00106
00107 def decode64Char(c):
00108 n = ord(c)
00109 if n>=48 and n<=58:
00110 return n-48
00111 elif n >= 64 and n <= 91:
00112 return n - 54
00113 elif n >= 97 and n <= 122:
00114 return n - 59
00115 raise Error
00116
00117 def unpack64(s, bytes=6):
00118 i = 0L
00119
00120 for j in range(bytes):
00121 c = s[j]
00122 a = decode64Char(c)
00123 i = i | a
00124 if j < bytes-1:
00125 i = i << 6
00126 return i
00127
00128 if 0:
00129 for i in range(64):
00130 c = encode64Char(i)
00131 j = decode64Char(c)
00132 if i != j:
00133 print i, c, j
00134
00135 ipaddr64 = pack64(ipaddr)
00136
00137
00138
00139
00140
00141
00142 class CircularSet:
00143 '''A circular set. A set that maxes at a given size, replacing the oldest element after maximum size.
00144 This implementation is NOT thread safe. (generate() below is thread safe, though)
00145 '''
00146 def __init__(self):
00147 self.queue = []
00148 self.queue_map = {}
00149 self.queueindex = 0
00150
00151 def add(self, val):
00152 '''Adds a value to the queue'''
00153
00154 assert not self.queue_map.has_key(val), 'This value is already in the set!'
00155
00156
00157 if len(self.queue) > self.queueindex:
00158
00159 del self.queue_map[self.queue[self.queueindex]]
00160 self.queue[self.queueindex] = val
00161 else:
00162 self.queue.append(val)
00163
00164
00165 self.queue_map[val] = val
00166
00167
00168 self.queueindex += 1
00169 if self.queueindex >= QUEUE_SIZE:
00170 self.queueindex = 0
00171
00172 queue = CircularSet()
00173
00174
00175
00176
00177
00178 def generate(time_t = None):
00179 '''Generates a new guid'''
00180 global lock, queue
00181 if time_t > 1136102400:
00182 raise ValueError, "time_t is too large %s" % time_t
00183
00184 try:
00185 lock.acquire()
00186 while 1:
00187
00188 if time_t == None:
00189 t = long(time.time() * 100)
00190 else:
00191 t = time_t * 100
00192
00193
00194 r = int(rand.random() * MAX_RANDOM) & 0xffff
00195 n = 0L | (long(t)<<48) | (ipaddr<<16) | r
00196 guid = pack64(n, bytes=16)
00197
00198 try:
00199 queue.add(guid)
00200 return guid
00201 except AssertionError:
00202 pass
00203 finally:
00204 lock.release()
00205
00206 InvalidGUID = "Invalid GUID"
00207
00208 def extract_time(guid):
00209 '''Extracts the time portion out of the guid and returns the
00210 number of seconds since the epoch as a float'''
00211 if len(guid) != 16: raise InvalidGUID
00212 n = unpack64(guid, bytes=16)
00213 t = long(n >> 48) / 100
00214 return t
00215
00216
00217 def extract_ip(guid):
00218 '''Extracts the ip portion out of the guid and returns it
00219 as a string like 10.10.10.10'''
00220
00221 if len(guid) != 16: raise InvalidGUID
00222
00223 n = unpack64(guid, bytes=16)
00224 n = n >> 16
00225 n = n & 0xffffffffL
00226
00227 ip = struct.pack(">L", n)
00228 ipaddrStr = socket.inet_ntoa(ip)
00229 return ipaddrStr
00230
00231
00232 def extract_random(guid):
00233 '''Extracts the random bits from the guid (returns the bits in decimal)'''
00234 if len(guid) != 16: raise InvalidGUID
00235
00236 n = unpack64(guid, bytes=16)
00237 r = int(n & 0xffff)
00238 return r
00239
00240
00241
00242 def test():
00243 pass
00244
00245 def usage(progname):
00246 print __doc__ % vars()
00247
00248 def main(argv, stdout, environ):
00249 progname = argv[0]
00250 optlist, args = getopt.getopt(argv[1:], "", ["help", "test", "debug"])
00251
00252 testflag = 0
00253
00254 for (field, val) in optlist:
00255 if field == "--help":
00256 usage(progname)
00257 return
00258 elif field == "--debug":
00259 debugfull()
00260 elif field == "--test":
00261 testflag = 1
00262
00263 if testflag:
00264 test()
00265 return
00266
00267 guids = []
00268 if len(args) == 0:
00269 guids.append(generate())
00270 else:
00271 for arg in args:
00272 guids.append(arg)
00273
00274 for guid in guids:
00275 print "GUID:", guid
00276 print "Time:", time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime(extract_time(guid)))
00277 print "IP: ", extract_ip(guid)
00278 print "Rand:", extract_random(guid)
00279 print
00280
00281
00282 if __name__ == "__main__":
00283 main(sys.argv, sys.stdout, os.environ)
00284
00285