add id generator for multi processes
parent
6bd718079e
commit
8104af5d27
1
HISTORY
1
HISTORY
|
|
@ -3,6 +3,7 @@ Version 1.27 2016-04-09
|
|||
* add function fd_set_cloexec
|
||||
* php-fastcommon.spec.in support PHP 7
|
||||
* add file lock and unlock functions
|
||||
* add id generator for multi processes
|
||||
|
||||
Version 1.26 2016-03-16
|
||||
* add logger parameter: compress_log_days_before
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.lo \
|
|||
fast_timer.lo process_ctrl.lo fast_mblock.lo \
|
||||
connection_pool.lo fast_mpool.lo fast_allocator.lo \
|
||||
fast_buffer.lo multi_skiplist.lo flat_skiplist.lo \
|
||||
system_info.lo fast_blocked_queue.lo
|
||||
system_info.lo fast_blocked_queue.lo id_generator.lo
|
||||
|
||||
FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
|
||||
logger.o sockopt.o base64.o sched_thread.o \
|
||||
|
|
@ -20,7 +20,7 @@ FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
|
|||
fast_timer.o process_ctrl.o fast_mblock.o \
|
||||
connection_pool.o fast_mpool.o fast_allocator.o \
|
||||
fast_buffer.o multi_skiplist.o flat_skiplist.o \
|
||||
system_info.o fast_blocked_queue.o
|
||||
system_info.o fast_blocked_queue.o id_generator.o
|
||||
|
||||
HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \
|
||||
shared_func.h pthread_func.h ini_file_reader.h _os_define.h \
|
||||
|
|
@ -29,8 +29,8 @@ HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \
|
|||
fast_timer.h process_ctrl.h fast_mblock.h \
|
||||
connection_pool.h fast_mpool.h fast_allocator.h \
|
||||
fast_buffer.h skiplist.h multi_skiplist.h flat_skiplist.h \
|
||||
skiplist_common.h system_info.h fast_blocked_queue.h \
|
||||
php7_ext_wrapper.h
|
||||
skiplist_common.h system_info.h fast_blocked_queue.h \
|
||||
php7_ext_wrapper.h id_generator.h
|
||||
|
||||
ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* Copyright (C) 2008 Happy Fish / YuQing
|
||||
*
|
||||
* FastDFS may be copied only under the terms of the GNU General
|
||||
* Public License V3, which may be found in the FastDFS source kit.
|
||||
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
|
||||
**/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/in.h>
|
||||
#include "logger.h"
|
||||
#include "shared_func.h"
|
||||
#include "local_ip_func.h"
|
||||
#include "id_generator.h"
|
||||
|
||||
int id_generator_init_ex(struct idg_context *context, const char *filename,
|
||||
const int machine_id, const int mid_bits)
|
||||
{
|
||||
int result;
|
||||
int mid;
|
||||
if (mid_bits < 2 || mid_bits > 20)
|
||||
{
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"invalid bits of machine id: %d",
|
||||
__LINE__, mid_bits);
|
||||
context->fd = -1;
|
||||
return EINVAL;
|
||||
}
|
||||
if (machine_id < 0 || machine_id >= (1 << mid_bits))
|
||||
{
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"invalid machine id: %d",
|
||||
__LINE__, machine_id);
|
||||
context->fd = -1;
|
||||
return EINVAL;
|
||||
}
|
||||
if (machine_id != 0)
|
||||
{
|
||||
mid = machine_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *local_ip;
|
||||
struct in_addr ip_addr;
|
||||
|
||||
local_ip = get_first_local_ip();
|
||||
if (local_ip == NULL)
|
||||
{
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"can't get local ip address", __LINE__);
|
||||
context->fd = -1;
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, local_ip, &ip_addr) != 1)
|
||||
{
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"invalid local ip address: %s",
|
||||
__LINE__, local_ip);
|
||||
context->fd = -1;
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
printf("ip_addr: %s, s_addr: %08X\n", local_ip, ip_addr.s_addr);
|
||||
printf("mask number: %08X\n", (1 << mid_bits));
|
||||
|
||||
mid = (ip_addr.s_addr >> (32 - mid_bits)) & ((1 << mid_bits) - 1);
|
||||
}
|
||||
|
||||
if ((context->fd = open(filename, O_RDWR | O_CREAT, 0644)) < 0)
|
||||
{
|
||||
result = errno != 0 ? errno : EACCES;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"open file \"%s\" fail, "
|
||||
"errno: %d, error info: %s", __LINE__,
|
||||
filename, result, STRERROR(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
context->machine_id = mid;
|
||||
context->mid_bits = mid_bits;
|
||||
context->sn_bits = 32 - mid_bits;
|
||||
context->masked_mid = ((int64_t)mid) << context->sn_bits;
|
||||
context->sn_mask = ((int64_t)1 << context->sn_bits) - 1;
|
||||
|
||||
printf("mid: %08X, masked_mid: %016llX, sn_mask: %08llX\n", mid, context->masked_mid, context->sn_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void id_generator_destroy(struct idg_context *context)
|
||||
{
|
||||
if (context->fd >= 0)
|
||||
{
|
||||
close(context->fd);
|
||||
context->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int id_generator_next(struct idg_context *context, int64_t *id)
|
||||
{
|
||||
int result;
|
||||
int len;
|
||||
int bytes;
|
||||
int64_t sn;
|
||||
char buff[32];
|
||||
char *endptr;
|
||||
|
||||
if ((result=file_write_lock(context->fd)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (lseek(context->fd, 0L, SEEK_SET) == -1)
|
||||
{
|
||||
result = errno != 0 ? errno : EACCES;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"file lseek fail, "
|
||||
"errno: %d, error info: %s", __LINE__,
|
||||
result, STRERROR(result));
|
||||
sn = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((bytes=read(context->fd, buff, sizeof(buff) - 1)) < 0)
|
||||
{
|
||||
result = errno != 0 ? errno : EACCES;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"file read fail, "
|
||||
"errno: %d, error info: %s", __LINE__,
|
||||
result, STRERROR(result));
|
||||
sn = 0;
|
||||
break;
|
||||
}
|
||||
*(buff + bytes) = '\0';
|
||||
|
||||
sn = strtoll(buff, &endptr, 10);
|
||||
++sn;
|
||||
|
||||
if (lseek(context->fd, 0L, SEEK_SET) == -1)
|
||||
{
|
||||
result = errno != 0 ? errno : EACCES;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"cal lseek fail, "
|
||||
"errno: %d, error info: %s", __LINE__,
|
||||
result, STRERROR(result));
|
||||
break;
|
||||
}
|
||||
|
||||
len = sprintf(buff, "%019"PRId64, sn);
|
||||
if ((bytes=write(context->fd, buff, len)) != len)
|
||||
{
|
||||
result = errno != 0 ? errno : EACCES;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"file write %d bytes fail, written: %d bytes, "
|
||||
"errno: %d, error info: %s", __LINE__,
|
||||
len, bytes, result, STRERROR(result));
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
file_unlock(context->fd);
|
||||
|
||||
*id = (time(NULL) << 32) | context->masked_mid | (sn & context->sn_mask);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Copyright (C) 2008 Happy Fish / YuQing
|
||||
*
|
||||
* FastDFS may be copied only under the terms of the GNU General
|
||||
* Public License V3, which may be found in the FastDFS source kit.
|
||||
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
|
||||
**/
|
||||
|
||||
/**
|
||||
64 bits id generator for multi processes, the generated id format:
|
||||
32 bits timestamp + X bits machine id + Y bits serial number
|
||||
*/
|
||||
|
||||
#ifndef ID_GENERATOR_H
|
||||
#define ID_GENERATOR_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <inttypes.h>
|
||||
#include "common_define.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct idg_context {
|
||||
int fd;
|
||||
int machine_id;
|
||||
int mid_bits; //bits of machine id
|
||||
int sn_bits; //bits of serial number
|
||||
int64_t masked_mid;
|
||||
int64_t sn_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* init function
|
||||
set mid_bits to 16
|
||||
set machine_id to 2 bytes of local ip address
|
||||
* parameter:
|
||||
* context: the id generator context
|
||||
* filename: the filename to store id
|
||||
* return error no, 0 for success, none zero for fail
|
||||
*/
|
||||
int id_generator_init(struct idg_context *context, const char *filename);
|
||||
|
||||
/**
|
||||
* 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 the machine id, such as 16
|
||||
* return error no, 0 for success, none zero for fail
|
||||
*/
|
||||
int id_generator_init_ex(struct idg_context *context, const char *filename,
|
||||
const int machine_id, const int mid_bits);
|
||||
|
||||
/**
|
||||
* init function
|
||||
* parameter:
|
||||
* context: the id generator context
|
||||
* filename: the filename to store id
|
||||
* return error no, 0 for success, none zero for fail
|
||||
*/
|
||||
void id_generator_destroy(struct idg_context *context);
|
||||
|
||||
/**
|
||||
* generate next id
|
||||
* parameter:
|
||||
* context: the id generator context
|
||||
* id: store the id
|
||||
* return error no, 0 for success, none zero for fail
|
||||
*/
|
||||
int id_generator_next(struct idg_context *context, int64_t *id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -4,7 +4,8 @@ COMPILE = $(CC) -g -O1 -Wall -D_FILE_OFFSET_BITS=64 -g -DDEBUG_FLAG
|
|||
INC_PATH = -I/usr/include/fastcommon
|
||||
LIB_PATH = -lfastcommon -lpthread
|
||||
|
||||
ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blocked_queue
|
||||
ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blocked_queue \
|
||||
test_id_generator
|
||||
|
||||
all: $(ALL_PRGS)
|
||||
.c:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include "logger.h"
|
||||
#include "shared_func.h"
|
||||
#include "sched_thread.h"
|
||||
#include "ini_file_reader.h"
|
||||
#include "sockopt.h"
|
||||
#include "id_generator.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct idg_context context;
|
||||
int result;
|
||||
int i;
|
||||
int64_t id;
|
||||
const int machine_id = 0;
|
||||
const int mid_bits = 8;
|
||||
|
||||
result = id_generator_init_ex(&context, "/tmp/sn.txt",
|
||||
machine_id, mid_bits);
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
id_generator_next(&context, &id);
|
||||
printf("id: %"PRId64", %016llX\n", id, id);
|
||||
for (i=0; i<1000000; i++)
|
||||
{
|
||||
result = id_generator_next(&context, &id);
|
||||
if (result != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("id: %"PRId64", %016llX\n", id, id);
|
||||
|
||||
id_generator_destroy(&context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue