id generator support variable sn bits

pull/10/head
yuqing 2016-04-15 14:46:30 +08:00
parent a6f4fe6a3e
commit f829bd5e88
6 changed files with 47 additions and 17 deletions

View File

@ -1,5 +1,5 @@
Version 1.27 2016-04-10 Version 1.27 2016-04-15
* add function fd_set_cloexec * add function fd_set_cloexec
* php-fastcommon.spec.in support PHP 7 * php-fastcommon.spec.in support PHP 7
* add file lock and unlock functions * add file lock and unlock functions

View File

@ -368,7 +368,7 @@ ZEND_FUNCTION(fastcommon_is_private_ip)
/* /*
bool fastcommon_id_generator_init([string filename = "/tmp/fastcommon_id_generator.sn", bool fastcommon_id_generator_init([string filename = "/tmp/fastcommon_id_generator.sn",
int machine_id = 0, int mid_bits = 16]) int machine_id = 0, int mid_bits = 16, int sn_bits = 16])
return true for success, false for fail return true for success, false for fail
*/ */
ZEND_FUNCTION(fastcommon_id_generator_init) ZEND_FUNCTION(fastcommon_id_generator_init)
@ -377,10 +377,11 @@ ZEND_FUNCTION(fastcommon_id_generator_init)
zend_size_t filename_len; zend_size_t filename_len;
long machine_id; long machine_id;
long mid_bits; long mid_bits;
long sn_bits;
char *filename; char *filename;
argc = ZEND_NUM_ARGS(); argc = ZEND_NUM_ARGS();
if (argc > 3) { if (argc > 4) {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"fastcommon_id_generator_init parameters count: %d is invalid", "fastcommon_id_generator_init parameters count: %d is invalid",
__LINE__, argc); __LINE__, argc);
@ -388,10 +389,12 @@ ZEND_FUNCTION(fastcommon_id_generator_init)
} }
filename = DEFAULT_SN_FILENAME; filename = DEFAULT_SN_FILENAME;
filename_len = 0;
machine_id = 0; machine_id = 0;
mid_bits = 16; mid_bits = 16;
if (zend_parse_parameters(argc TSRMLS_CC, "|sll", &filename, sn_bits = 16;
&filename_len, &machine_id, &mid_bits) == FAILURE) if (zend_parse_parameters(argc TSRMLS_CC, "|slll", &filename,
&filename_len, &machine_id, &mid_bits, &sn_bits) == FAILURE)
{ {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"zend_parse_parameters fail!", __LINE__); "zend_parse_parameters fail!", __LINE__);
@ -399,13 +402,13 @@ ZEND_FUNCTION(fastcommon_id_generator_init)
} }
if (idg_context.fd >= 0) { if (idg_context.fd >= 0) {
logError("file: "__FILE__", line: %d, " logWarning("file: "__FILE__", line: %d, "
"already inited!", __LINE__); "already inited!", __LINE__);
RETURN_BOOL(false); RETURN_BOOL(false);
} }
if (id_generator_init_ex(&idg_context, filename, if (id_generator_init_ex(&idg_context, filename,
machine_id, mid_bits) != 0) machine_id, mid_bits, sn_bits) != 0)
{ {
RETURN_BOOL(false); RETURN_BOOL(false);
} }

View File

@ -16,11 +16,13 @@ while (($next_ip=fastcommon_get_next_local_ip($next_ip)))
echo "local ip: $next_ip, private: $is_private_ip\n"; echo "local ip: $next_ip, private: $is_private_ip\n";
} }
fastcommon_id_generator_init("/tmp/sn.txt"); fastcommon_id_generator_init();
//fastcommon_id_generator_init("/tmp/sn.txt", 0, 8, 16);
var_dump(fastcommon_id_generator_next()); var_dump(fastcommon_id_generator_next());
for ($i=0; $i<10; $i++) { for ($i=0; $i<10; $i++) {
echo fastcommon_id_generator_next() . "\n"; $id = fastcommon_id_generator_next();
printf("%d %X\n", $id, $id);
} }
fastcommon_id_generator_destroy(); fastcommon_id_generator_destroy();

View File

@ -22,7 +22,7 @@
#include "id_generator.h" #include "id_generator.h"
int id_generator_init_ex(struct idg_context *context, const char *filename, int id_generator_init_ex(struct idg_context *context, const char *filename,
const int machine_id, const int mid_bits) const int machine_id, const int mid_bits, const int sn_bits)
{ {
int result; int result;
int mid; int mid;
@ -34,6 +34,23 @@ int id_generator_init_ex(struct idg_context *context, const char *filename,
context->fd = -1; context->fd = -1;
return EINVAL; return EINVAL;
} }
if (sn_bits < 8)
{
logError("file: "__FILE__", line: %d, "
"invalid bits of serial no: %d < 8",
__LINE__, sn_bits);
context->fd = -1;
return EINVAL;
}
if (mid_bits + sn_bits > 32)
{
logError("file: "__FILE__", line: %d, "
"invalid mid_bits + sn_bits: %d > 32",
__LINE__, mid_bits + sn_bits);
context->fd = -1;
return EINVAL;
}
if (machine_id < 0 || machine_id >= (1 << mid_bits)) if (machine_id < 0 || machine_id >= (1 << mid_bits))
{ {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
@ -102,7 +119,8 @@ int id_generator_init_ex(struct idg_context *context, const char *filename,
context->machine_id = mid; context->machine_id = mid;
context->mid_bits = mid_bits; context->mid_bits = mid_bits;
context->sn_bits = 32 - mid_bits; context->sn_bits = sn_bits;
context->mid_sn_bits = mid_bits + sn_bits;
context->masked_mid = ((int64_t)mid) << context->sn_bits; context->masked_mid = ((int64_t)mid) << context->sn_bits;
context->sn_mask = ((int64_t)1 << context->sn_bits) - 1; context->sn_mask = ((int64_t)1 << context->sn_bits) - 1;
@ -132,6 +150,7 @@ int id_generator_next(struct idg_context *context, int64_t *id)
if ((result=file_write_lock(context->fd)) != 0) if ((result=file_write_lock(context->fd)) != 0)
{ {
*id = 0;
return result; return result;
} }
@ -187,7 +206,8 @@ int id_generator_next(struct idg_context *context, int64_t *id)
file_unlock(context->fd); file_unlock(context->fd);
*id = (((int64_t)time(NULL)) << 32) | context->masked_mid | (sn & context->sn_mask); *id = (((int64_t)time(NULL)) << context->mid_sn_bits) |
context->masked_mid | (sn & context->sn_mask);
return result; return result;
} }

View File

@ -32,6 +32,7 @@ struct idg_context {
int machine_id; int machine_id;
int mid_bits; //bits of machine id int mid_bits; //bits of machine id
int sn_bits; //bits of serial number int sn_bits; //bits of serial number
int mid_sn_bits; //mid_bits + sn_bits
int64_t masked_mid; int64_t masked_mid;
int64_t sn_mask; int64_t sn_mask;
}; };
@ -42,16 +43,18 @@ struct idg_context {
* context: the id generator context * context: the id generator context
* filename: the filename to store id * filename: the filename to store id
* machine_id: the machine id, 0 for auto generate by local ip address * machine_id: the machine id, 0 for auto generate by local ip address
* mid_bits: the bits of the machine id, such as 16 * mid_bits: the bits of machine id, such as 16
* sn_bits: the bits of serial no, such as 16, mid_bits + sn_bits must <= 32
* return error no, 0 for success, none zero for fail * return error no, 0 for success, none zero for fail
*/ */
int id_generator_init_ex(struct idg_context *context, const char *filename, int id_generator_init_ex(struct idg_context *context, const char *filename,
const int machine_id, const int mid_bits); const int machine_id, const int mid_bits, const int sn_bits);
/** /**
* init function * init function
set mid_bits to 16
set machine_id to 2 bytes of local ip address set machine_id to 2 bytes of local ip address
set mid_bits to 16
set sn_bits to 16
* parameter: * parameter:
* context: the id generator context * context: the id generator context
* filename: the filename to store id * filename: the filename to store id
@ -61,7 +64,8 @@ static inline int id_generator_init(struct idg_context *context, const char *fil
{ {
const int machine_id = 0; const int machine_id = 0;
const int mid_bits = 16; const int mid_bits = 16;
return id_generator_init_ex(context, filename, machine_id, mid_bits); const int sn_bits = 16;
return id_generator_init_ex(context, filename, machine_id, mid_bits, sn_bits);
} }
/** /**

View File

@ -22,13 +22,14 @@ int main(int argc, char *argv[])
int64_t id; int64_t id;
const int machine_id = 0; const int machine_id = 0;
const int mid_bits = 12; const int mid_bits = 12;
const int sn_bits = 16;
log_init(); log_init();
g_log_context.log_level = LOG_DEBUG; g_log_context.log_level = LOG_DEBUG;
//result = id_generator_init(&context, "/tmp/sn.txt"); //result = id_generator_init(&context, "/tmp/sn.txt");
result = id_generator_init_ex(&context, "/tmp/sn.txt", result = id_generator_init_ex(&context, "/tmp/sn.txt",
machine_id, mid_bits); machine_id, mid_bits, sn_bits);
if (result != 0) if (result != 0)
{ {
return result; return result;