-
Notifications
You must be signed in to change notification settings - Fork 196
/
generator.py
163 lines (141 loc) · 4.04 KB
/
generator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/env python
# -*- coding: utf-8 -*
# Copyright: [CUP] - See LICENSE for details.
# Authors: Guannan Ma (@mythmgn),
"""
class CGeneratorMan(object)
===========================
Generate unique integers, strings and auto incremental uint.
Notice CGeneratorMan is a singleton class, which means cup will keep
only 1 instance per process.
:init:
__init__(self, str_prefix=get_local_hostname())
local hostname will be used by default.
:methods:
**get_uniqname()**
get unique name.
Host-Level unique name (build upon str_prefix, pid, threadid)
**get_next_uniq_num()**
Process-level auto incremental uint. Thread-safe
**reset_uniqid_start(num=0)**
Reset next uniqid to which genman starts from
**get_random_str()**
Get random string by length
**get_uuid()**
Get uuid
"""
import os
import time
import random
import string
import socket
import struct
import threading
import cup
from cup import decorators
__all__ = [
'CGeneratorMan',
'CycleIDGenerator'
]
@decorators.Singleton
class CGeneratorMan(object):
"""
refer to the docstring
"""
def __init__(self, str_prefix='localhost'):
"""
Generate unique integers, strings and auto incremental uint.
"""
if str_prefix == 'localhost':
prefix = cup.net.get_local_hostname()
else:
prefix = str(str_prefix)
self._prefix = prefix + str(os.getpid())
self._lock = threading.Lock()
self._ind = 0
self._nlock = threading.Lock()
self._nind = 0
def reset_uniqid_start(self, num=0):
"""
reset next uniqid to which genman starts from.
"""
self._lock.acquire()
self._nind = num
self._lock.release()
def get_uniqname(self):
"""
get a unique name
"""
self._lock.acquire()
strrev = self._prefix + str(self._ind) + '_thd_' + \
str(threading.current_thread().ident)
self._ind = self._ind + 1
self._lock.release()
return strrev
def get_next_uniq_num(self):
"""
get next uniq num. Thread-safe
"""
self._nlock.acquire()
temp = self._nind
self._nind += 1
self._nlock.release()
return temp
def get_next_uniqhex(self):
"""
return next uniqhex
"""
temp = self.get_next_uniq_num()
return str(hex(temp))
@classmethod
def get_random_str(cls, length):
"""get random str by length"""
return ''.join(random.choice(string.lowercase) for i in range(length))
@classmethod
def get_uuid(cls):
"""get random uuid"""
import uuid
uuid.uuid4()
class CycleIDGenerator(object):
"""
cycle id generator. 128bit ID will be produced.
128 bit contains:
a. 64bit [ip, port, etc] b. 64bit[auto increment id]
"""
def __init__(self, ip, port):
"""
ip, port will be encoded into the ID
"""
self._ip = ip
self._port = port
self._lock = threading.Lock()
packed = socket.inet_aton(self._ip)
tmp = struct.unpack("!L", packed)[0] << 96
self._pre_num = tmp | (int(self._port) << 64)
self._max_id = 0X1 << 63
self._next_id = int(time.time())
def reset_nextid(self, nextid):
"""reset nextid that will return to you"""
self._lock.acquire()
if nextid > self._max_id:
self._lock.release()
return False
self._next_id = nextid
self._lock.release()
return True
def next_id(self):
"""get next id"""
self._lock.acquire()
num = self._pre_num | self._next_id
if self._next_id == self._max_id:
self._next_id = 0
else:
self._next_id += 1
self._lock.release()
return num
@classmethod
def id2_hexstring(cls, num):
"""return hex of the id"""
str_num = str(hex(num))
return str_num
# vi:set tw=0 ts=4 sw=4 nowrap fdm=indent