#include #include #include "snowflake.h" #include "log_private.h" #define SNOWFLAKE_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "snowflake", format, ##__VA_ARGS__) struct snowflake { uint8_t worker_base_id; // 5 bit [0, 31] uint8_t worker_offset_id; // 7 bit [0, 127] uint64_t thread_id; // limit 256 uint64_t device_id; // 12 bit [0, 4095] ( base << 7 | offset ) uint64_t sequence; }; struct snowflake *snowflake_new(uint16_t thread_id, uint8_t worker_base_id, uint8_t worker_offset_id) { if (thread_id > 255) { SNOWFLAKE_LOG_ERROR("thread_id %u is invalid, range [0, 255]", thread_id); return NULL; } if (worker_base_id > 31) { SNOWFLAKE_LOG_ERROR("worker_base_id %u is invalid, range [0, 31]", worker_base_id); return NULL; } if (worker_offset_id > 127) { SNOWFLAKE_LOG_ERROR("worker_offset_id %u is invalid, range [0, 127]", worker_offset_id); return NULL; } struct snowflake *sf = (struct snowflake *)calloc(1, sizeof(struct snowflake)); if (sf == NULL) { SNOWFLAKE_LOG_ERROR("calloc snowflake failed"); return NULL; } sf->worker_base_id = worker_base_id; sf->worker_offset_id = worker_offset_id; sf->thread_id = thread_id; sf->device_id = ((worker_base_id << 7) | worker_offset_id) & 0xFFF; sf->sequence = 0; return sf; } void snowflake_free(struct snowflake *sf) { if (sf != NULL) { free(sf); sf = NULL; } } /* * high -> low * * +------+------------------+----------------+------------------------+---------------------------+ * | 1bit | 12bit device_id | 8bit thread_id | 28bit timestamp in sec | 15bit sequence per thread | * +------+------------------+----------------+------------------------+---------------------------+ */ #define MAX_ID_PER_THREAD (32768) #define MAX_ID_BASE_TIME (268435456L) uint64_t snowflake_generate(struct snowflake *sf, uint64_t now_sec) { if (sf == NULL) { SNOWFLAKE_LOG_ERROR("snowflake is NULL"); return 0; } uint64_t id = 0; uint64_t id_per_thread = (sf->sequence++) % MAX_ID_PER_THREAD; uint64_t id_base_time = now_sec % MAX_ID_BASE_TIME; id = (sf->device_id << 51) | (sf->thread_id << 43) | (id_base_time << 15) | (id_per_thread); return id; } void snowflake_deserialize(uint64_t id, struct snowflake_meta *meta) { if (meta == NULL) { return; } meta->sequence = id & 0x7FFF; meta->time_cycle = MAX_ID_BASE_TIME; meta->time_relative = (id >> 15) & 0xFFFFFFF; meta->thread_id = (id >> 43) & 0xFF; meta->device_id = (id >> 51) & 0xFFF; meta->worker_base_id = (meta->device_id >> 7) & 0x1F; meta->worker_offset_id = meta->device_id & 0x7F; }