id generator support extra bits

pull/10/head
yuqing 2016-05-14 19:37:55 +08:00
parent f829bd5e88
commit 064c4730e4
8 changed files with 160 additions and 42 deletions

View File

@ -1,4 +1,7 @@
Version 1.28 2016-05-14
* id generator support extra bits
Version 1.27 2016-04-15 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

View File

@ -2,7 +2,7 @@
%define LibFastcommonDevel libfastcommon-devel %define LibFastcommonDevel libfastcommon-devel
Name: libfastcommon Name: libfastcommon
Version: 1.0.27 Version: 1.0.28
Release: 1%{?dist} Release: 1%{?dist}
Summary: c common functions library extracted from my open source projects FastDFS Summary: c common functions library extracted from my open source projects FastDFS
License: GPL License: GPL

View File

@ -44,6 +44,7 @@ const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, N
ZEND_FE(fastcommon_is_private_ip, NULL) ZEND_FE(fastcommon_is_private_ip, NULL)
ZEND_FE(fastcommon_id_generator_init, NULL) ZEND_FE(fastcommon_id_generator_init, NULL)
ZEND_FE(fastcommon_id_generator_next, NULL) ZEND_FE(fastcommon_id_generator_next, NULL)
ZEND_FE(fastcommon_id_generator_get_extra, NULL)
ZEND_FE(fastcommon_id_generator_destroy, NULL) ZEND_FE(fastcommon_id_generator_destroy, NULL)
{NULL, NULL, NULL} /* Must be the last line */ {NULL, NULL, NULL} /* Must be the last line */
}; };
@ -368,7 +369,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 sn_bits = 16]) int machine_id = 0, int mid_bits = 16, int extra_bits = 0, 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,11 +378,12 @@ 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 extra_bits;
long sn_bits; long sn_bits;
char *filename; char *filename;
argc = ZEND_NUM_ARGS(); argc = ZEND_NUM_ARGS();
if (argc > 4) { if (argc > 5) {
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);
@ -392,9 +394,11 @@ ZEND_FUNCTION(fastcommon_id_generator_init)
filename_len = 0; filename_len = 0;
machine_id = 0; machine_id = 0;
mid_bits = 16; mid_bits = 16;
extra_bits = 0;
sn_bits = 16; sn_bits = 16;
if (zend_parse_parameters(argc TSRMLS_CC, "|slll", &filename, if (zend_parse_parameters(argc TSRMLS_CC, "|sllll", &filename,
&filename_len, &machine_id, &mid_bits, &sn_bits) == FAILURE) &filename_len, &machine_id, &mid_bits, &extra_bits,
&sn_bits) == FAILURE)
{ {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"zend_parse_parameters fail!", __LINE__); "zend_parse_parameters fail!", __LINE__);
@ -407,8 +411,8 @@ ZEND_FUNCTION(fastcommon_id_generator_init)
RETURN_BOOL(false); RETURN_BOOL(false);
} }
if (id_generator_init_ex(&idg_context, filename, if (id_generator_init_extra(&idg_context, filename,
machine_id, mid_bits, sn_bits) != 0) machine_id, mid_bits, extra_bits, sn_bits) != 0)
{ {
RETURN_BOOL(false); RETURN_BOOL(false);
} }
@ -417,22 +421,30 @@ ZEND_FUNCTION(fastcommon_id_generator_init)
} }
/* /*
long/string fastcommon_id_generator_next() long/string fastcommon_id_generator_next([int extra])
return id for success, false for fail return id for success, false for fail
return long in 64 bits OS, return string in 32 bits Os return long in 64 bits OS, return string in 32 bits Os
*/ */
ZEND_FUNCTION(fastcommon_id_generator_next) ZEND_FUNCTION(fastcommon_id_generator_next)
{ {
int argc; int argc;
long extra;
int64_t id; int64_t id;
argc = ZEND_NUM_ARGS(); argc = ZEND_NUM_ARGS();
if (argc != 0) { if (argc > 1) {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"fastcommon_id_generator_next parameters count: %d is invalid", "fastcommon_id_generator_next parameters count: %d is invalid",
__LINE__, argc); __LINE__, argc);
RETURN_BOOL(false); RETURN_BOOL(false);
} }
extra = 0;
if (zend_parse_parameters(argc TSRMLS_CC, "|l", &extra) == FAILURE)
{
logError("file: "__FILE__", line: %d, "
"zend_parse_parameters fail!", __LINE__);
RETURN_BOOL(false);
}
if (idg_context.fd < 0) { if (idg_context.fd < 0) {
if (id_generator_init(&idg_context, DEFAULT_SN_FILENAME) != 0) { if (id_generator_init(&idg_context, DEFAULT_SN_FILENAME) != 0) {
@ -440,7 +452,7 @@ ZEND_FUNCTION(fastcommon_id_generator_next)
} }
} }
if (id_generator_next(&idg_context, &id) != 0) { if (id_generator_next_extra(&idg_context, extra, &id) != 0) {
RETURN_BOOL(false); RETURN_BOOL(false);
} }
@ -456,6 +468,38 @@ ZEND_FUNCTION(fastcommon_id_generator_next)
#endif #endif
} }
/*
int fastcommon_id_generator_get_extra(long id)
return the extra data
*/
ZEND_FUNCTION(fastcommon_id_generator_get_extra)
{
int argc;
long id;
argc = ZEND_NUM_ARGS();
if (argc != 1) {
logError("file: "__FILE__", line: %d, "
"fastcommon_id_generator_get_extra parameters count: %d is invalid",
__LINE__, argc);
RETURN_BOOL(false);
}
if (zend_parse_parameters(argc TSRMLS_CC, "l", &id) == FAILURE)
{
logError("file: "__FILE__", line: %d, "
"zend_parse_parameters fail!", __LINE__);
RETURN_BOOL(false);
}
if (idg_context.fd < 0) {
logError("file: "__FILE__", line: %d, "
"must call fastcommon_id_generator_init first", __LINE__);
RETURN_BOOL(false);
}
RETURN_LONG(id_generator_get_extra(&idg_context, id));
}
/* /*
bool fastcommon_id_generator_destroy() bool fastcommon_id_generator_destroy()
return true for success, false for fail return true for success, false for fail

View File

@ -28,6 +28,7 @@ ZEND_FUNCTION(fastcommon_is_private_ip);
ZEND_FUNCTION(fastcommon_id_generator_init); ZEND_FUNCTION(fastcommon_id_generator_init);
ZEND_FUNCTION(fastcommon_id_generator_next); ZEND_FUNCTION(fastcommon_id_generator_next);
ZEND_FUNCTION(fastcommon_id_generator_get_extra);
ZEND_FUNCTION(fastcommon_id_generator_destroy); ZEND_FUNCTION(fastcommon_id_generator_destroy);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -16,13 +16,15 @@ 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(); //fastcommon_id_generator_init();
//fastcommon_id_generator_init("/tmp/sn.txt", 0, 8, 16); fastcommon_id_generator_init("/tmp/sn.txt", 0, 8, 10, 14);
var_dump(fastcommon_id_generator_next()); $id = fastcommon_id_generator_next(1024);
for ($i=0; $i<10; $i++) { printf("%d %X, extra: %d\n", $id, $id, fastcommon_id_generator_get_extra($id));
$id = fastcommon_id_generator_next();
printf("%d %X\n", $id, $id); for ($i=0; $i<1024; $i++) {
$id = fastcommon_id_generator_next($i);
printf("%d %X, extra: %d\n", $id, $id, fastcommon_id_generator_get_extra($id));
} }
fastcommon_id_generator_destroy(); fastcommon_id_generator_destroy();

View File

@ -21,8 +21,9 @@
#include "local_ip_func.h" #include "local_ip_func.h"
#include "id_generator.h" #include "id_generator.h"
int id_generator_init_ex(struct idg_context *context, const char *filename, int id_generator_init_extra(struct idg_context *context, const char *filename,
const int machine_id, const int mid_bits, const int sn_bits) const int machine_id, const int mid_bits, const int extra_bits,
const int sn_bits)
{ {
int result; int result;
int mid; int mid;
@ -34,6 +35,14 @@ int id_generator_init_ex(struct idg_context *context, const char *filename,
context->fd = -1; context->fd = -1;
return EINVAL; return EINVAL;
} }
if (extra_bits < 0 || extra_bits > 16)
{
logError("file: "__FILE__", line: %d, "
"invalid bits of extra data: %d",
__LINE__, extra_bits);
context->fd = -1;
return EINVAL;
}
if (sn_bits < 8) if (sn_bits < 8)
{ {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
@ -42,11 +51,11 @@ int id_generator_init_ex(struct idg_context *context, const char *filename,
context->fd = -1; context->fd = -1;
return EINVAL; return EINVAL;
} }
if (mid_bits + sn_bits > 32) if (mid_bits + extra_bits + sn_bits > 32)
{ {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"invalid mid_bits + sn_bits: %d > 32", "invalid mid_bits + extra_bits + sn_bits: %d > 32",
__LINE__, mid_bits + sn_bits); __LINE__, mid_bits + extra_bits + sn_bits);
context->fd = -1; context->fd = -1;
return EINVAL; return EINVAL;
} }
@ -119,13 +128,17 @@ 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->extra_bits = extra_bits;
context->sn_bits = sn_bits; context->sn_bits = sn_bits;
context->mid_sn_bits = mid_bits + sn_bits; context->mes_bits_sum = mid_bits + extra_bits + sn_bits;
context->masked_mid = ((int64_t)mid) << context->sn_bits; context->masked_mid = ((int64_t)mid) << (extra_bits + sn_bits);
context->sn_mask = ((int64_t)1 << context->sn_bits) - 1; context->extra_mask = ((int64_t)1 << (extra_bits + sn_bits)) -
((int64_t)1 << sn_bits);
context->sn_mask = ((int64_t)1 << sn_bits) - 1;
logDebug("mid: 0x%08X, masked_mid: 0x%08llX, sn_mask: 0x%08llX\n", logDebug("mid: 0x%08X, masked_mid: 0x%08llX, extra_mask: 0x%08llX, "
mid, context->masked_mid, context->sn_mask); "sn_mask: 0x%08llX\n", mid, context->masked_mid,
context->extra_mask, context->sn_mask);
return 0; return 0;
} }
@ -139,7 +152,8 @@ void id_generator_destroy(struct idg_context *context)
} }
} }
int id_generator_next(struct idg_context *context, int64_t *id) int id_generator_next_extra(struct idg_context *context, const int extra,
int64_t *id)
{ {
int result; int result;
int len; int len;
@ -206,8 +220,9 @@ int id_generator_next(struct idg_context *context, int64_t *id)
file_unlock(context->fd); file_unlock(context->fd);
*id = (((int64_t)time(NULL)) << context->mid_sn_bits) | *id = (((int64_t)time(NULL)) << context->mes_bits_sum) |
context->masked_mid | (sn & context->sn_mask); context->masked_mid | ((extra << context->sn_bits) & context->extra_mask) |
(sn & context->sn_mask);
return result; return result;
} }

View File

@ -8,8 +8,8 @@
/** /**
64 bits id generator for multi processes, the generated id format: 64 bits id generator for multi processes, the generated id format:
32 bits timestamp + X bits machine id + Y bits serial number 32 bits timestamp + X bits machine id + Y bits of extra data + Z bits serial number
such as 12 bits machine id and 20 bits serial number such as 12 bits machine id, 0 bits extra data and 20 bits serial number
*/ */
#ifndef ID_GENERATOR_H #ifndef ID_GENERATOR_H
@ -31,12 +31,29 @@ struct idg_context {
int fd; int fd;
int machine_id; int machine_id;
int mid_bits; //bits of machine id int mid_bits; //bits of machine id
int extra_bits; //extra bits
int sn_bits; //bits of serial number int sn_bits; //bits of serial number
int mid_sn_bits; //mid_bits + sn_bits int mes_bits_sum; //mid_bits + extra_bits + sn_bits
int64_t masked_mid; int64_t masked_mid;
int64_t extra_mask;
int64_t sn_mask; int64_t sn_mask;
}; };
/**
* init function
* parameter:
* context: the id generator context
* filename: the filename to store id
* machine_id: the machine id, 0 for auto generate by local ip address
* mid_bits: the bits of machine id, such as 16
* extra_bits: the extra bits, such as 0
* 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
*/
int id_generator_init_extra(struct idg_context *context, const char *filename,
const int machine_id, const int mid_bits, const int extra_bits,
const int sn_bits);
/** /**
* init function * init function
* parameter: * parameter:
@ -47,13 +64,20 @@ struct idg_context {
* sn_bits: the bits of serial no, such as 16, mid_bits + sn_bits must <= 32 * 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, static inline int id_generator_init_ex(struct idg_context *context,
const int machine_id, const int mid_bits, const int sn_bits); const char *filename, const int machine_id, const int mid_bits,
const int sn_bits)
{
const int extra_bits = 0;
return id_generator_init_extra(context, filename, machine_id, mid_bits,
extra_bits, sn_bits);
}
/** /**
* init function * init function
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 mid_bits to 16
set extra_bits to 0
set sn_bits to 16 set sn_bits to 16
* parameter: * parameter:
* context: the id generator context * context: the id generator context
@ -64,8 +88,10 @@ 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;
const int extra_bits = 0;
const int sn_bits = 16; const int sn_bits = 16;
return id_generator_init_ex(context, filename, machine_id, mid_bits, sn_bits); return id_generator_init_extra(context, filename, machine_id, mid_bits,
extra_bits, sn_bits);
} }
/** /**
@ -76,6 +102,17 @@ static inline int id_generator_init(struct idg_context *context, const char *fil
*/ */
void id_generator_destroy(struct idg_context *context); void id_generator_destroy(struct idg_context *context);
/**
* generate next id ex
* parameter:
* context: the id generator context
* extra: the extra data
* id: store the id
* return error no, 0 for success, none zero for fail
*/
int id_generator_next_extra(struct idg_context *context, const int extra,
int64_t *id);
/** /**
* generate next id * generate next id
* parameter: * parameter:
@ -83,7 +120,22 @@ void id_generator_destroy(struct idg_context *context);
* id: store the id * id: store the id
* return error no, 0 for success, none zero for fail * return error no, 0 for success, none zero for fail
*/ */
int id_generator_next(struct idg_context *context, int64_t *id); static inline int id_generator_next(struct idg_context *context, int64_t *id)
{
return id_generator_next_extra(context, 0, id);
}
/**
* get extra data from id
* parameter:
* context: the id generator context
* id: the id
* return the extra data
*/
static inline int id_generator_get_extra(struct idg_context *context, const int64_t id)
{
return (int)((id & context->extra_mask) >> context->sn_bits);
}
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -21,15 +21,16 @@ int main(int argc, char *argv[])
int i; int i;
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 = 8;
const int sn_bits = 16; const int extra_bits = 10;
const int sn_bits = 14;
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_extra(&context, "/tmp/sn.txt",
machine_id, mid_bits, sn_bits); machine_id, mid_bits, extra_bits, sn_bits);
if (result != 0) if (result != 0)
{ {
return result; return result;
@ -37,12 +38,12 @@ int main(int argc, char *argv[])
for (i=0; i<100; i++) for (i=0; i<100; i++)
{ {
result = id_generator_next(&context, &id); result = id_generator_next_extra(&context, i, &id);
if (result != 0) if (result != 0)
{ {
break; break;
} }
printf("%"PRId64"\n", id); printf("id: %"PRId64", extra: %d\n", id, id_generator_get_extra(&context, id));
} }
id_generator_destroy(&context); id_generator_destroy(&context);