diff --git a/.gitignore b/.gitignore index 379b936..3ce5fb0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.userosscache *.sln.docstates *.editorconfig +__*.bat # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/C#.NET/source/Yitter.IdGen.sln b/C#.NET/source/Yitter.IdGen.sln index 2cbc6ea..b0e6203 100644 --- a/C#.NET/source/Yitter.IdGen.sln +++ b/C#.NET/source/Yitter.IdGen.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31005.135 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32602.215 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yitter.IdGenerator", "Yitter.IdGenerator\Yitter.IdGenerator.csproj", "{FF8DAF11-34E7-4842-ADF2-3722A1A5FBB2}" EndProject diff --git a/C#.NET/source/Yitter.IdGenTest/Program.cs b/C#.NET/source/Yitter.IdGenTest/Program.cs index 6805258..8dfc158 100644 --- a/C#.NET/source/Yitter.IdGenTest/Program.cs +++ b/C#.NET/source/Yitter.IdGenTest/Program.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; @@ -11,7 +12,7 @@ namespace Yitter.OrgSystem.TestA class Program { // 测试参数(默认配置下,最佳性能是10W/s) - static int genIdCount = 2;//50000; // 计算ID数量(如果要验证50W效率,请将TopOverCostCount设置为20000或适当增加SeqBitLength) + static int genIdCount = 50000;//5000; // 计算ID数量(如果要验证50W效率,请将TopOverCostCount设置为2000或适当增加SeqBitLength) static short method = 1; // 1-漂移算法,2-传统算法 @@ -26,23 +27,24 @@ namespace Yitter.OrgSystem.TestA static void Main(string[] args) { + RunSingle(); + return; + Console.WriteLine("Hello World! C#"); var options = new IdGeneratorOptions() { - Method = method, + Method = 1, WorkerId = 1, WorkerIdBitLength = 6, SeqBitLength = 6, - DataCenterIdBitLength = 10, + DataCenterIdBitLength = 0, TopOverCostCount = 2000, //TimestampType = 1, - // MinSeqNumber = 1, // MaxSeqNumber = 200, - // BaseTime = DateTime.Now.AddYears(-10), }; @@ -55,27 +57,118 @@ namespace Yitter.OrgSystem.TestA Console.WriteLine("====================================="); Console.WriteLine("这是用方法 " + method + " 生成的 Id:" + newId); - while (true) + var seed1 = 50; + var seed2 = 1000; + var finish = 0; + var next = IdGen.NewLong(); + + var hashSet = new HashSet(seed1 * seed2); + ConcurrentBag bags = new ConcurrentBag(); + + for (int i = 0; i < seed1; i++) + { + (new Thread(_ => + { + for (int j = 0; j < seed2; j++) + { + var me = IdGen.NewLong(); + hashSet.Add(me); + bags.Add(me); + } + + Interlocked.Increment(ref finish); + }) + { IsBackground = true }).Start(); + } + + while (finish < seed1) { - RunSingle(); - //CallDll(); - //Go(options); - Thread.Sleep(1000); // 每隔1秒执行一次Go + Console.WriteLine("等待执行结束"); + Thread.Sleep(2000); } + + Console.WriteLine($"hashSet 共计:{hashSet.Count} 实际应该:{seed1 * seed2}"); + Console.WriteLine($"bags 共计:{bags.Count} 实际应该:{seed1 * seed2}"); + + var IdArray = bags.ToArray(); + int totalCount = 0; + + for (int i = 0; i < seed1 * seed2; i++) + { + var me = IdArray[i]; + int j = 0; + int count = 0; + + while (j < seed1 * seed2) + { + if (IdArray[j] == me) + { + count++; + } + j++; + } + + if (count > 1) + { + totalCount++; + Console.WriteLine($"{IdArray[i]},重复:{count}"); + } + } + + if (totalCount == 0) + { + Console.WriteLine($"重复数为 0 "); + } + + Console.Read(); + + //while (true) + //{ + // //RunSingle(); + // //CallDll(); + // //Go(options); + // Thread.Sleep(1000); // 每隔1秒执行一次Go + //} } private static void RunSingle() { - DateTime start = DateTime.Now; - for (int i = 0; i < genIdCount; i++) + var options = new IdGeneratorOptions() { - var id = IdGen.NewLong(); - } + Method = 1, + WorkerId = 1, + + //WorkerIdBitLength = 6, + SeqBitLength = 6, + + //TopOverCostCount = 2000, + //DataCenterIdBitLength = 0, + + //TimestampType = 1, + // MinSeqNumber = 1, + // MaxSeqNumber = 200, + // BaseTime = DateTime.Now.AddYears(-10), + }; - DateTime end = DateTime.Now; - Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++, total: {(end - start).TotalMilliseconds} ms"); - Interlocked.Increment(ref Program.Count); + //IdGen = new DefaultIdGenerator(options); + YitIdHelper.SetIdGenerator(options); + + while (true) + { + DateTime start = DateTime.Now; + + for (int i = 0; i < genIdCount; i++) + { + //var id = IdGen.NewLong(); + var id = YitIdHelper.NextId(); + } + + DateTime end = DateTime.Now; + Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++, total: {(end - start).TotalMilliseconds} ms"); + Thread.Sleep(1000); + } + //Interlocked.Increment(ref Program.Count); } private static void Go(IdGeneratorOptions options) diff --git a/C#.NET/source/Yitter.IdGenTest/Yitter.IdGenTest.csproj b/C#.NET/source/Yitter.IdGenTest/Yitter.IdGenTest.csproj index 409f0d3..03d97b9 100644 --- a/C#.NET/source/Yitter.IdGenTest/Yitter.IdGenTest.csproj +++ b/C#.NET/source/Yitter.IdGenTest/Yitter.IdGenTest.csproj @@ -2,7 +2,7 @@ Exe - net5.0 + net6.0 diff --git a/C#.NET/source/Yitter.IdGenerator/Contract/IdGeneratorOptions.cs b/C#.NET/source/Yitter.IdGenerator/Contract/IdGeneratorOptions.cs index 1ff5c42..613e9af 100644 --- a/C#.NET/source/Yitter.IdGenerator/Contract/IdGeneratorOptions.cs +++ b/C#.NET/source/Yitter.IdGenerator/Contract/IdGeneratorOptions.cs @@ -63,7 +63,6 @@ namespace Yitter.IdGenerator /// public virtual int TopOverCostCount { get; set; } = 2000; - /// /// 数据中心ID(默认0) /// diff --git a/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM1.cs b/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM1.cs index 4344b5f..709a489 100644 --- a/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM1.cs +++ b/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM1.cs @@ -118,10 +118,10 @@ namespace Yitter.IdGenerator // 7.Others TopOverCostCount = options.TopOverCostCount; - if (TopOverCostCount == 0) - { - TopOverCostCount = 2000; - } + //if (TopOverCostCount == 0) + //{ + // TopOverCostCount = 2000; + //} _TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength); _CurrentSeqNumber = options.MinSeqNumber; @@ -351,6 +351,7 @@ namespace Yitter.IdGenerator while (tempTimeTicker <= _LastTimeTick) { + Thread.Sleep(1); tempTimeTicker = GetCurrentTimeTick(); } diff --git a/C#.NET/source/Yitter.IdGenerator/DefaultIdGenerator.cs b/C#.NET/source/Yitter.IdGenerator/DefaultIdGenerator.cs index 4bb4d13..f21ad03 100644 --- a/C#.NET/source/Yitter.IdGenerator/DefaultIdGenerator.cs +++ b/C#.NET/source/Yitter.IdGenerator/DefaultIdGenerator.cs @@ -92,6 +92,12 @@ namespace Yitter.IdGenerator throw new ApplicationException("MinSeqNumber error. (range:[5, " + maxSeqNumber + "]"); } + // 7.TopOverCostCount + if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) + { + throw new ApplicationException("TopOverCostCount error. (range:[0, 10000]"); + } + switch (options.Method) { case 2: diff --git a/C#.NET/source/Yitter.IdGenerator/YitIdHelper.cs b/C#.NET/source/Yitter.IdGenerator/YitIdHelper.cs index 1127609..cb48892 100644 --- a/C#.NET/source/Yitter.IdGenerator/YitIdHelper.cs +++ b/C#.NET/source/Yitter.IdGenerator/YitIdHelper.cs @@ -34,17 +34,24 @@ namespace Yitter.IdGenerator /// /// 生成新的Id /// 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。 - /// 否则将会初始化一个WorkerId为1的对象。 /// /// public static long NextId() { - if (_IdGenInstance == null) - { - _IdGenInstance = new DefaultIdGenerator( - new IdGeneratorOptions() { WorkerId = 0 } - ); - } + //if (_IdGenInstance == null) + //{ + // lock (_IdGenInstance) + // { + // if (_IdGenInstance == null) + // { + // _IdGenInstance = new DefaultIdGenerator( + // new IdGeneratorOptions() { WorkerId = 0 } + // ); + // } + // } + //} + + if (_IdGenInstance == null) throw new ApplicationException("Please initialize Yitter.IdGeneratorOptions first."); return _IdGenInstance.NewLong(); } diff --git a/C#.NET/source/Yitter.IdGenerator/Yitter.IdGenerator.csproj b/C#.NET/source/Yitter.IdGenerator/Yitter.IdGenerator.csproj index 3e634fa..4d1bec1 100644 --- a/C#.NET/source/Yitter.IdGenerator/Yitter.IdGenerator.csproj +++ b/C#.NET/source/Yitter.IdGenerator/Yitter.IdGenerator.csproj @@ -18,8 +18,10 @@ Yitter https://github.com/yitter/idgenerator MIT - 1.0.12 + 1.0.14 + 1.0.0.* + 1.0.0.* diff --git a/C/source/.gitignore b/C/source/.gitignore index 67cc059..7ceceb7 100644 --- a/C/source/.gitignore +++ b/C/source/.gitignore @@ -1,7 +1,7 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. -build/* +build # User-specific files *.suo @@ -29,6 +29,7 @@ bld/ **/.vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ +.vscode # MSTest test Results [Tt]est[Rr]esult*/ @@ -254,7 +255,8 @@ paket-files/ .idea/ *.sln.iml target/ -cmake-build*/ +cmake-build-* +source.code-* # macOS .DS_Store diff --git a/C/source/CMakeLists.txt b/C/source/CMakeLists.txt index 38d8db8..2628ab0 100644 --- a/C/source/CMakeLists.txt +++ b/C/source/CMakeLists.txt @@ -8,18 +8,17 @@ set(CMAKE_C_STANDARD 11) aux_source_directory(. DIR_SRCS) add_subdirectory(idgen) - #编译动态库 -#set(LIB_SRC YitIdHelper.h YitIdHelper.c) -#add_library(YitIdGenLib SHARED ${LIB_SRC}) -#target_link_libraries(YitIdGenLib idgen) -#set_target_properties(YitIdGenLib PROPERTIES -# LINKER_LANGUAGE C -# OUTPUT_NAME "yitidgenc" -# PREFIX "") - -##编译执行文件 set(LIB_SRC YitIdHelper.h YitIdHelper.c) +add_library(YitIdGenLib SHARED ${LIB_SRC}) +target_link_libraries(YitIdGenLib idgen) +set_target_properties(YitIdGenLib PROPERTIES + LINKER_LANGUAGE C + OUTPUT_NAME "yitidgenc" + PREFIX "") + +# 编译执行文件 +# set(LIB_SRC YitIdHelper.h YitIdHelper.c) add_library(YitIdHelper ${LIB_SRC}) add_executable(YitIdGen main.c) target_link_libraries(YitIdGen YitIdHelper pthread) diff --git a/C/source/idgen/IdGenerator.c b/C/source/idgen/IdGenerator.c index b498371..d1938ca 100644 --- a/C/source/idgen/IdGenerator.c +++ b/C/source/idgen/IdGenerator.c @@ -9,107 +9,147 @@ #include #include "IdGenerator.h" - -static inline uint64_t WorkerM1Id() { +static inline uint64_t WorkerM1Id() +{ return WorkerM1NextId(_idGenerator->Worker); } -static inline uint64_t WorkerM2Id() { +static inline uint64_t WorkerM2Id() +{ return WorkerM2NextId(_idGenerator->Worker); } - -extern IdGenerator *GetIdGenInstance() { +extern IdGenerator *GetIdGenInstance() +{ if (_idGenerator != NULL) return _idGenerator; - else { - _idGenerator = (IdGenerator *) malloc(sizeof(IdGenerator)); + else + { + _idGenerator = (IdGenerator *)malloc(sizeof(IdGenerator)); _idGenerator->Worker = NewSnowFlakeWorker(); return _idGenerator; } } -extern void SetOptions(IdGeneratorOptions options) { - if (GetIdGenInstance() == NULL) { +extern void SetOptions(IdGeneratorOptions options) +{ + if (GetIdGenInstance() == NULL) + { exit(1); } // 1.BaseTime - if (options.BaseTime == 0) { + if (options.BaseTime == 0) + { _idGenerator->Worker->BaseTime = 1582136402000; - } else if (options.BaseTime < 631123200000 || options.BaseTime > GetCurrentTime()) { + } + else if (options.BaseTime < 631123200000 || options.BaseTime > GetCurrentTime()) + { perror("BaseTime error."); exit(1); - } else { + } + else + { _idGenerator->Worker->BaseTime = options.BaseTime; } // 2.WorkerIdBitLength - if (options.WorkerIdBitLength <= 0) { + if (options.WorkerIdBitLength <= 0) + { perror("WorkerIdBitLength error.(range:[1, 21])"); exit(1); } - if (options.SeqBitLength + options.WorkerIdBitLength > 22) { + if (options.SeqBitLength + options.WorkerIdBitLength > 22) + { perror("error:WorkerIdBitLength + SeqBitLength <= 22"); exit(1); - } else { + } + else + { // _idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength; _idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength <= 0 ? 6 : options.WorkerIdBitLength; } // 3.WorkerId uint32_t maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1; - if (maxWorkerIdNumber == 0) { + if (maxWorkerIdNumber == 0) + { maxWorkerIdNumber = 63; } - if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { + if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) + { perror("WorkerId error. (range:[0, {2^options.WorkerIdBitLength-1]}"); exit(1); - } else { + } + else + { _idGenerator->Worker->WorkerId = options.WorkerId; } // 4.SeqBitLength - if (options.SeqBitLength < 2 || options.SeqBitLength > 21) { + if (options.SeqBitLength < 2 || options.SeqBitLength > 21) + { perror("SeqBitLength error. (range:[2, 21])"); exit(1); - } else { + } + else + { // _idGenerator->Worker->SeqBitLength = options.SeqBitLength; _idGenerator->Worker->SeqBitLength = options.SeqBitLength <= 0 ? 6 : options.SeqBitLength; } // 5.MaxSeqNumber uint32_t maxSeqNumber = (1 << options.SeqBitLength) - 1; - if (maxSeqNumber == 0) { + if (maxSeqNumber == 0) + { maxSeqNumber = 63; } - if (options.MaxSeqNumber > maxSeqNumber) { + if (options.MaxSeqNumber > maxSeqNumber) + { perror("MaxSeqNumber error. (range:[1, {2^options.SeqBitLength-1}]"); exit(1); - } else { + } + else + { _idGenerator->Worker->MaxSeqNumber = options.MaxSeqNumber <= 0 ? maxSeqNumber : options.MaxSeqNumber; } // 6.MinSeqNumber - if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber) { + if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber) + { perror("MinSeqNumber error. (range:[5, {options.MinSeqNumber}]"); exit(1); - } else { + } + else + { _idGenerator->Worker->MinSeqNumber = options.MinSeqNumber <= 0 ? 5 : options.MinSeqNumber; } - // 7.Others - _idGenerator->Worker->TopOverCostCount = options.TopOverCostCount <= 0 ? 2000 : options.TopOverCostCount; + // 7.TopOverCostCount + if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) + { + perror("TopOverCostCount error. (range:[0, 10000]"); + exit(1); + } + else + { + //_idGenerator->Worker->TopOverCostCount = options.TopOverCostCount <= 0 ? 2000 : options.TopOverCostCount; + _idGenerator->Worker->TopOverCostCount = options.TopOverCostCount; + } + + // 8.Others _idGenerator->Worker->_TimestampShift = - _idGenerator->Worker->WorkerIdBitLength + _idGenerator->Worker->SeqBitLength; + _idGenerator->Worker->WorkerIdBitLength + _idGenerator->Worker->SeqBitLength; _idGenerator->Worker->_CurrentSeqNumber = _idGenerator->Worker->MinSeqNumber; _idGenerator->Worker->Method = options.Method; - if (options.Method == 2) { + if (options.Method == 2) + { _idGenerator->NextId = WorkerM2Id; - } else { + } + else + { _idGenerator->NextId = WorkerM1Id; - sleep(1); + usleep(500 * 1000); // 暂停500ms } } - diff --git a/C/source/idgen/SnowWorkerM1.c b/C/source/idgen/SnowWorkerM1.c index 82f9855..5534f9b 100644 --- a/C/source/idgen/SnowWorkerM1.c +++ b/C/source/idgen/SnowWorkerM1.c @@ -162,6 +162,7 @@ extern int64_t GetCurrentMicroTime() { extern int64_t GetNextTimeTick(SnowFlakeWorker *worker) { uint64_t tempTimeTicker = GetCurrentTimeTick(worker); while (tempTimeTicker <= worker->_LastTimeTick) { + usleep(1000); // 暂停1ms tempTimeTicker = GetCurrentTimeTick(worker); } return tempTimeTicker; diff --git a/C/source/main.c b/C/source/main.c index 6be35b5..9289b08 100644 --- a/C/source/main.c +++ b/C/source/main.c @@ -13,51 +13,62 @@ #include "idgen/IdGenerator.h" #include "YitIdHelper.h" - -const int GenIdCount = 50000; +const int GenIdCount = 500000; const bool multiThread = false; const int threadCount = 50; const int method = 1; -void RunMultiThread() { - //int64_t start = GetCurrentMicroTime(); - for (int i = 0; i < GenIdCount / threadCount; i++) { +void RunMultiThread() +{ + // int64_t start = GetCurrentMicroTime(); + for (int i = 0; i < GenIdCount / threadCount; i++) + { int64_t id = NextId(); printf("ID: %D\n", id); } int64_t end = GetCurrentMicroTime(); - //printf("%s,total:%d μs\n", method == 1 ? "1" : "2", (end - start)); + // printf("%s,total:%d μs\n", method == 1 ? "1" : "2", (end - start)); } -void RunSingle() { +void RunSingle() +{ int64_t start = GetCurrentMicroTime(); - for (int i = 0; i < GenIdCount; i++) { + for (int i = 0; i < GenIdCount; i++) + { int64_t id = NextId(); -// printf("ID: %ld\n", id); + // printf("ID: %ld\n", id); } int64_t end = GetCurrentMicroTime(); printf("%s, total: %d us\n", method == 1 ? "1" : "2", (end - start)); } -int main() { +int main() +{ IdGeneratorOptions options = BuildIdGenOptions(1); options.Method = method; options.WorkerId = 1; - options.SeqBitLength = 6; + options.SeqBitLength = 10; + // options.TopOverCostCount = 2000; SetIdGenerator(options); pthread_t tid[threadCount]; - while (1) { - if (multiThread) { - for (int i = 0; i < threadCount; i++) { - if (pthread_create(&tid[i], NULL, (void *) RunMultiThread, NULL) != 0) { + while (1) + { + if (multiThread) + { + for (int i = 0; i < threadCount; i++) + { + if (pthread_create(&tid[i], NULL, (void *)RunMultiThread, NULL) != 0) + { printf("thread creation failed\n"); exit(1); } } - } else { + } + else + { RunSingle(); } diff --git a/Go/README.md b/Go/README.md index a68ae46..c8d0e3b 100644 --- a/Go/README.md +++ b/Go/README.md @@ -31,7 +31,7 @@ var newId = idgen.NextId() ## 关于Go环境 -1.SDK,go1.14 +1.SDK,go1.16 2.启用 Go-Modules ``` diff --git a/Go/regworkerid/.gitignore b/Go/regworkerid/.gitignore new file mode 100644 index 0000000..af01ed3 --- /dev/null +++ b/Go/regworkerid/.gitignore @@ -0,0 +1,262 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates +*.editorconfig +.vscode +__commit.bat +__download.bat +target + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +**/.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +*.snupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + + +# macOS +.DS_Store diff --git a/Go/regworkerid/go.mod b/Go/regworkerid/go.mod new file mode 100644 index 0000000..10d458c --- /dev/null +++ b/Go/regworkerid/go.mod @@ -0,0 +1,10 @@ +module github.com/yitter/idgenerator-go + +go 1.17 + +require github.com/go-redis/redis/v8 v8.11.5 + +require ( + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect +) diff --git a/Go/regworkerid/go.sum b/Go/regworkerid/go.sum new file mode 100644 index 0000000..c2f5cad --- /dev/null +++ b/Go/regworkerid/go.sum @@ -0,0 +1,106 @@ +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/Go/regworkerid/main.go b/Go/regworkerid/main.go new file mode 100644 index 0000000..c857af0 --- /dev/null +++ b/Go/regworkerid/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "C" + "fmt" + "time" + + "github.com/yitter/idgenerator-go/regworkerid" +) + +func main() { + ip := "localhost" + password := "" + + ipChar := C.CString(ip) + passChar := C.CString(password) + + workerIdList := RegisterMany(ipChar, 6379, passChar, 4, 3, 0) + for _, value := range workerIdList { + fmt.Println("注册的WorkerId:", value) + } + + id := RegisterOne(ipChar, 6379, passChar, 4, 0) + fmt.Println("注册的WorkerId:", id) + + // var workerId = regworkerid.RegisterOne(ip, 6379, "", 4) + // fmt.Println("注册的WorkerId:", workerId) + + fmt.Println("end") + time.Sleep(time.Duration(300) * time.Second) +} + +//export RegisterOne +// 注册一个 WorkerId +func RegisterOne(ip *C.char, port int32, password *C.char, maxWorkerId int32, database int) int32 { + return regworkerid.RegisterOne(C.GoString(ip), port, C.GoString(password), maxWorkerId, database) +} + +//export UnRegister +// 注销本机已注册的 WorkerId +func UnRegister() { + regworkerid.UnRegister() +} + +// export Validate +// 检查本地WorkerId是否有效(0-有效,其它-无效) +func Validate(workerId int32) int32 { + return regworkerid.Validate(workerId) +} + +// RegisterMany +// 注册多个 WorkerId,会先注销所有本机已注册的记录 +func RegisterMany(ip *C.char, port int32, password *C.char, maxWorkerId, totalCount int32, database int) []int32 { + // return (*C.int)(unsafe.Pointer(&values)) + //return regworkerid.RegisterMany(ip, port, password, maxWorkerId, totalCount, database) + return regworkerid.RegisterMany(C.GoString(ip), port, C.GoString(password), maxWorkerId, totalCount, database) +} + +// To Build a dll/so: + +// windows: +// go build -o ./target/yitidgengo.dll -buildmode=c-shared main.go +// // go build -o ./target/yitidgengo.dll -buildmode=c-shared main.go reg.go + +// linux init: go install -buildmode=shared -linkshared std +// go build -o ./target/yitidgengo.so -buildmode=c-shared main.go +// go build -o ./target/yitidgengo.so -buildmode=c-shared main.go reg.go + +// https://books.studygolang.com/advanced-go-programming-book/ch2-cgo/ch2-09-static-shared-lib.html diff --git a/Go/regworkerid/reg.go b/Go/regworkerid/reg.go new file mode 100644 index 0000000..ab3f677 --- /dev/null +++ b/Go/regworkerid/reg.go @@ -0,0 +1,5 @@ +package main + +import ( + "C" +) diff --git a/Go/source/regworkerid/reghelper.go b/Go/regworkerid/regworkerid/reghelper.go similarity index 100% rename from Go/source/regworkerid/reghelper.go rename to Go/regworkerid/regworkerid/reghelper.go diff --git a/Go/source/.gitignore b/Go/source/.gitignore new file mode 100644 index 0000000..af01ed3 --- /dev/null +++ b/Go/source/.gitignore @@ -0,0 +1,262 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates +*.editorconfig +.vscode +__commit.bat +__download.bat +target + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +**/.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +*.snupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + + +# macOS +.DS_Store diff --git a/Go/source/go.mod b/Go/source/go.mod index 6de6bfa..7561ad3 100644 --- a/Go/source/go.mod +++ b/Go/source/go.mod @@ -1,5 +1,8 @@ -module yitidgen - -go 1.16 - -require github.com/go-redis/redis/v8 v8.8.0 // indirect +module github.com/yitter/idgenerator-go + +go 1.17 + +require ( + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect +) diff --git a/Go/source/go.sum b/Go/source/go.sum index 3e2ce7f..c2f5cad 100644 --- a/Go/source/go.sum +++ b/Go/source/go.sum @@ -1,15 +1,18 @@ -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= -github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-redis/redis/v8 v8.8.0 h1:fDZP58UN/1RD3DjtTXP/fFZ04TFohSYhjZDkcDe2dnw= -github.com/go-redis/redis/v8 v8.8.0/go.mod h1:F7resOH5Kdug49Otu24RjHWwgK7u9AmtqWMnCV1iP5Y= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -17,38 +20,33 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= -github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= -github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= -github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= -github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v0.19.0 h1:Lenfy7QHRXPZVsw/12CWpxX6d/JkrX8wrx2vO8G80Ng= -go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg= -go.opentelemetry.io/otel/metric v0.19.0 h1:dtZ1Ju44gkJkYvo+3qGqVXmf88tc+a42edOywypengg= -go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc= -go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA= -go.opentelemetry.io/otel/trace v0.19.0 h1:1ucYlenXIDA1OlHVLDZKX0ObXV5RLaq06DtUKz5e5zc= -go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -58,8 +56,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -69,35 +67,40 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/Go/source/idgen/DefaultIdGenerator.go b/Go/source/idgen/DefaultIdGenerator.go index e0d1e00..6c3ca60 100644 --- a/Go/source/idgen/DefaultIdGenerator.go +++ b/Go/source/idgen/DefaultIdGenerator.go @@ -4,6 +4,7 @@ * 代码修订:yitter * 开源地址:https://github.com/yitter/idgenerator */ + package idgen import ( @@ -64,6 +65,11 @@ func NewDefaultIdGenerator(options *IdGeneratorOptions) *DefaultIdGenerator { panic("MinSeqNumber error. (range:[5, " + strconv.FormatUint(uint64(maxSeqNumber), 10) + "]") } + // 7.TopOverCostCount + if options.TopOverCostCount < 0 || options.TopOverCostCount > 10000 { + panic("TopOverCostCount error. (range:[0, 10000]") + } + var snowWorker ISnowWorker switch options.Method { case 1: @@ -87,3 +93,7 @@ func NewDefaultIdGenerator(options *IdGeneratorOptions) *DefaultIdGenerator { func (dig DefaultIdGenerator) NewLong() int64 { return dig.SnowWorker.NextId() } + +func (dig DefaultIdGenerator) ExtractTime(id int64) time.Time { + return time.UnixMilli(id>>(dig.Options.WorkerIdBitLength+dig.Options.SeqBitLength) + dig.Options.BaseTime) +} diff --git a/Go/source/idgen/SnowWorkerM1.go b/Go/source/idgen/SnowWorkerM1.go index cf28b62..02e017c 100644 --- a/Go/source/idgen/SnowWorkerM1.go +++ b/Go/source/idgen/SnowWorkerM1.go @@ -4,6 +4,7 @@ * 代码修订:yitter * 开源地址:https://github.com/yitter/idgenerator */ + package idgen import ( @@ -13,13 +14,13 @@ import ( // SnowWorkerM1 . type SnowWorkerM1 struct { - BaseTime int64 //基础时间 - WorkerId uint16 //机器码 - WorkerIdBitLength byte //机器码位长 - SeqBitLength byte //自增序列数位长 - MaxSeqNumber uint32 //最大序列数(含) - MinSeqNumber uint32 //最小序列数(含) - TopOverCostCount uint32 //最大漂移次数 + BaseTime int64 // 基础时间 + WorkerId uint16 // 机器码 + WorkerIdBitLength byte // 机器码位长 + SeqBitLength byte // 自增序列数位长 + MaxSeqNumber uint32 // 最大序列数(含) + MinSeqNumber uint32 // 最小序列数(含) + TopOverCostCount uint32 // 最大漂移次数 _TimestampShift byte _CurrentSeqNumber uint32 @@ -75,12 +76,13 @@ func NewSnowWorkerM1(options *IdGeneratorOptions) ISnowWorker { // 6.MinSeqNumber var minSeqNumber = options.MinSeqNumber - // 7.Others + // 7.TopOverCostCount var topOverCostCount = options.TopOverCostCount - if topOverCostCount == 0 { - topOverCostCount = 2000 - } + // if topOverCostCount == 0 { + // topOverCostCount = 2000 + // } + // 8.Others timestampShift := (byte)(workerIdBitLength + seqBitLength) currentSeqNumber := minSeqNumber @@ -232,6 +234,7 @@ func (m1 *SnowWorkerM1) GetCurrentTimeTick() int64 { func (m1 *SnowWorkerM1) GetNextTimeTick() int64 { tempTimeTicker := m1.GetCurrentTimeTick() for tempTimeTicker <= m1._LastTimeTick { + time.Sleep(time.Duration(1) * time.Millisecond) tempTimeTicker = m1.GetCurrentTimeTick() } return tempTimeTicker diff --git a/Go/source/idgen/YitIdHelper.go b/Go/source/idgen/YitIdHelper.go index f096210..3cc3cc1 100644 --- a/Go/source/idgen/YitIdHelper.go +++ b/Go/source/idgen/YitIdHelper.go @@ -1,7 +1,15 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码编辑:guoyahao + * 代码修订:yitter + * 开源地址:https://github.com/yitter/idgenerator + */ + package idgen import ( "sync" + "time" ) var singletonMutex sync.Mutex @@ -16,14 +24,20 @@ func SetIdGenerator(options *IdGeneratorOptions) { // NextId . func NextId() int64 { + //if idGenerator == nil { + // singletonMutex.Lock() + // defer singletonMutex.Unlock() + // if idGenerator == nil { + // options := NewIdGeneratorOptions(1) + // idGenerator = NewDefaultIdGenerator(options) + // } + //} if idGenerator == nil { - singletonMutex.Lock() - defer singletonMutex.Unlock() - if idGenerator == nil { - options := NewIdGeneratorOptions(1) - idGenerator = NewDefaultIdGenerator(options) - } + panic("Please initialize Yitter.IdGeneratorOptions first.") } - return idGenerator.NewLong() } + +func ExtractTime(id int64) time.Time { + return idGenerator.ExtractTime(id) +} diff --git a/Go/source/main.go b/Go/source/main.go index 4094c86..4cddd96 100644 --- a/Go/source/main.go +++ b/Go/source/main.go @@ -1,136 +1,52 @@ package main import ( - "C" "fmt" "time" - "yitidgen/idgen" - "yitidgen/regworkerid" + + "github.com/yitter/idgenerator-go/idgen" ) -//export SetOptions func SetOptions(workerId uint16) { var options = idgen.NewIdGeneratorOptions(workerId) idgen.SetIdGenerator(options) } -//export NextId func NextId() int64 { return idgen.NextId() } -// RegisterOne 注册一个 WorkerId,会先注销所有本机已注册的记录 -// address: Redis连接地址,单机模式示例:127.0.0.1:6379,哨兵/集群模式示例:127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382 -// password: Redis连接密码 -// db: Redis指定存储库,示例:1 -// sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster -// maxWorkerId: WorkerId 最大值,示例:63 -//export RegisterOne -func RegisterOne(address *C.char, password *C.char, db int, sentinelMasterName *C.char, maxWorkerId int32) int32 { - return regworkerid.RegisterOne(regworkerid.RegisterConf{ - Address: C.GoString(address), - Password: C.GoString(password), - DB: db, - MasterName: C.GoString(sentinelMasterName), - MaxWorkerId: maxWorkerId, - }) -} - -// RegisterMany 注册多个 WorkerId,会先注销所有本机已注册的记录 -// address: Redis连接地址,单机模式示例:127.0.0.1:6379,哨兵/集群模式示例:127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382 -// password: Redis连接密码 -// db: Redis指定存储库,示例:1 -// sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster -// maxWorkerId: WorkerId 最大值,示例:63 -// totalCount: 获取N个WorkerId,示例:5 -//export RegisterMany -func RegisterMany(address *C.char, password *C.char, db int, sentinelMasterName *C.char, maxWorkerId int32, totalCount int32) []int32 { - return regworkerid.RegisterMany(regworkerid.RegisterConf{ - Address: C.GoString(address), - Password: C.GoString(password), - DB: db, - MasterName: C.GoString(sentinelMasterName), - MaxWorkerId: maxWorkerId, - TotalCount: totalCount, - }) -} - -// UnRegister 注销本机已注册的 WorkerId -//export UnRegister -func UnRegister() { - regworkerid.UnRegister() -} - -// Validate 检查本地WorkerId是否有效(0-有效,其它-无效) -//export Validate -func Validate(workerId int32) int32 { - return regworkerid.Validate(workerId) -} - func main() { - const testGenId = true // 测试设置 - - if testGenId { - // 自定义参数 - var options = idgen.NewIdGeneratorOptions(1) - options.WorkerIdBitLength = 6 - options.SeqBitLength = 6 - options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 - idgen.SetIdGenerator(options) + // 自定义参数 + var options = idgen.NewIdGeneratorOptions(1) + options.WorkerIdBitLength = 6 + options.SeqBitLength = 10 + options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 + idgen.SetIdGenerator(options) - var genCount = 50000 + var genCount = 500000 + for j := 0; j < 100000; j++ { for { - var begin = time.Now().UnixNano() / 1e3 + var begin = time.Now().UnixNano() / 1e6 for i := 0; i < genCount; i++ { // 生成ID - id := idgen.NextId() - fmt.Println(id) + idgen.NextId() + // fmt.Println(id) } - var end = time.Now().UnixNano() / 1e3 + var end = time.Now().UnixNano() / 1e6 - fmt.Println(end - begin) + fmt.Println("耗时:", (end - begin), "ms") time.Sleep(time.Duration(1000) * time.Millisecond) } - } else { - - //// Redis单机模式下,获取多个WorkerId - //workerIdList := regworkerid.RegisterMany(regworkerid.RegisterConf{ - // Address: "127.0.0.1:6379", - // Password: "", - // DB: 0, - // MaxWorkerId: 4, - // TotalCount: 3, - //}) - //for _, value := range workerIdList { - // fmt.Println("RegisterMany--注册的WorkerId:", value) - //} - - // Redis单机模式下,获取一个WorkerId - var workerId = regworkerid.RegisterOne(regworkerid.RegisterConf{ - Address: "127.0.0.1:6379", - Password: "", - DB: 0, - MaxWorkerId: 4, - }) - fmt.Println("RegisterOne--注册的WorkerId:", workerId) - - //// Redis哨兵模式下,获取一个WorkerId - //var workerId = regworkerid.RegisterOne(regworkerid.RegisterConf{ - // //Address: "127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382", - // Password: "", - // DB: 0, - // MasterName: "mymaster", // 哨兵模式下的服务名称 - // MaxWorkerId: 4, - //}) - //fmt.Println("RegisterOne--注册的WorkerId:", workerId) - - fmt.Println("end") - time.Sleep(time.Duration(300) * time.Second) } } +// To Build a dll/so: + // windows: // go build -o ./target/yitidgengo.dll -buildmode=c-shared main.go // linux init: go install -buildmode=shared -linkshared std // go build -o ./target/yitidgengo.so -buildmode=c-shared main.go + +// https://books.studygolang.com/advanced-go-programming-book/ch2-cgo/ch2-09-static-shared-lib.html diff --git a/Java/source/.gitignore b/Java/source/.gitignore index b551e8b..e4b0fc4 100644 --- a/Java/source/.gitignore +++ b/Java/source/.gitignore @@ -19,7 +19,9 @@ *.zip *.tar.gz *.rar -target/ +target +.vscode +*.code-workspace # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* diff --git a/Java/source/pom.xml b/Java/source/pom.xml index 0d8f601..1b154b2 100644 --- a/Java/source/pom.xml +++ b/Java/source/pom.xml @@ -41,9 +41,9 @@ UTF-8 UTF-8 - 1.8 - 1.8 - 1.8 + 11 + 11 + 11 diff --git a/Java/source/src/main/java/com/github/yitter/core/SnowWorkerM1.java b/Java/source/src/main/java/com/github/yitter/core/SnowWorkerM1.java index 52f6ff4..cfee4f9 100644 --- a/Java/source/src/main/java/com/github/yitter/core/SnowWorkerM1.java +++ b/Java/source/src/main/java/com/github/yitter/core/SnowWorkerM1.java @@ -66,7 +66,8 @@ public class SnowWorkerM1 implements ISnowWorker { SeqBitLength = options.SeqBitLength == 0 ? 6 : options.SeqBitLength; MaxSeqNumber = options.MaxSeqNumber <= 0 ? (1 << SeqBitLength) - 1 : options.MaxSeqNumber; MinSeqNumber = options.MinSeqNumber; - TopOverCostCount = options.TopOverCostCount == 0 ? 2000 : options.TopOverCostCount; + // TopOverCostCount = options.TopOverCostCount == 0 ? 2000 : options.TopOverCostCount; + TopOverCostCount = options.TopOverCostCount; _TimestampShift = (byte) (WorkerIdBitLength + SeqBitLength); _CurrentSeqNumber = MinSeqNumber; } @@ -150,11 +151,11 @@ public class SnowWorkerM1 implements ISnowWorker { BeginTurnBackAction(_TurnBackTimeTick); } -// try { -// Thread.sleep(1); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } + // try { + // Thread.sleep(1); + // } catch (InterruptedException e) { + // e.printStackTrace(); + // } return CalcTurnBackId(_TurnBackTimeTick); } @@ -214,6 +215,11 @@ public class SnowWorkerM1 implements ISnowWorker { long tempTimeTicker = GetCurrentTimeTick(); while (tempTimeTicker <= _LastTimeTick) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } tempTimeTicker = GetCurrentTimeTick(); } @@ -227,4 +233,3 @@ public class SnowWorkerM1 implements ISnowWorker { } } } - diff --git a/Java/source/src/main/java/com/github/yitter/idgen/DefaultIdGenerator.java b/Java/source/src/main/java/com/github/yitter/idgen/DefaultIdGenerator.java index 0863d63..2353006 100644 --- a/Java/source/src/main/java/com/github/yitter/idgen/DefaultIdGenerator.java +++ b/Java/source/src/main/java/com/github/yitter/idgen/DefaultIdGenerator.java @@ -11,7 +11,6 @@ import com.github.yitter.contract.IdGeneratorOptions; import com.github.yitter.core.SnowWorkerM1; import com.github.yitter.core.SnowWorkerM2; - public class DefaultIdGenerator implements IIdGenerator { private static ISnowWorker _SnowWorker = null; @@ -40,7 +39,8 @@ public class DefaultIdGenerator implements IIdGenerator { maxWorkerIdNumber = 63; } if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { - throw new IdGeneratorException("WorkerId error. (range:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]"); + throw new IdGeneratorException( + "WorkerId error. (range:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]"); } // 4.SeqBitLength @@ -62,6 +62,11 @@ public class DefaultIdGenerator implements IIdGenerator { throw new IdGeneratorException("MinSeqNumber error. (range:[5, " + maxSeqNumber + "]"); } + // 7.TopOverCostCount + if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) { + throw new IdGeneratorException("TopOverCostCount error. (range:[0, 10000]"); + } + switch (options.Method) { case 2: _SnowWorker = new SnowWorkerM2(options); diff --git a/Java/source/src/main/java/com/github/yitter/idgen/YitIdHelper.java b/Java/source/src/main/java/com/github/yitter/idgen/YitIdHelper.java index 31b6005..b501d0b 100644 --- a/Java/source/src/main/java/com/github/yitter/idgen/YitIdHelper.java +++ b/Java/source/src/main/java/com/github/yitter/idgen/YitIdHelper.java @@ -19,7 +19,6 @@ public class YitIdHelper { return idGenInstance; } - /** * 设置参数,建议程序初始化时执行一次 */ @@ -34,9 +33,12 @@ public class YitIdHelper { * @return */ public static long nextId() throws IdGeneratorException { - if (idGenInstance == null) { - idGenInstance = new DefaultIdGenerator(new IdGeneratorOptions((short) 1)); - } + // if (idGenInstance == null) { + // idGenInstance = new DefaultIdGenerator(new IdGeneratorOptions((short) 1)); + // } + + if (idGenInstance == null) + throw new IdGeneratorException("Please initialize Yitter.IdGeneratorOptions first."); return idGenInstance.newLong(); } diff --git a/Java/source/src/test/java/com/github/yitter/test/GenTest.java b/Java/source/src/test/java/com/github/yitter/test/GenTest.java index 036ec86..4071b71 100644 --- a/Java/source/src/test/java/com/github/yitter/test/GenTest.java +++ b/Java/source/src/test/java/com/github/yitter/test/GenTest.java @@ -26,7 +26,7 @@ public class GenTest { long end = System.currentTimeMillis(); long time = end - start; - System.out.println(id); + // System.out.println(id); System.out.println("++++++++++++++++++++++++++++++++++++++++WorkerId: " + WorkerId + ", total: " + time + " ms"); diff --git a/Java/source/src/test/java/com/github/yitter/test/StartUp.java b/Java/source/src/test/java/com/github/yitter/test/StartUp.java index a2334d4..dbe782c 100644 --- a/Java/source/src/test/java/com/github/yitter/test/StartUp.java +++ b/Java/source/src/test/java/com/github/yitter/test/StartUp.java @@ -12,7 +12,7 @@ public class StartUp { * [不同CPU可能结果有差异,但相对大小不变] * 默认配置下,最佳性能是5W/s-8W/s */ - final static int genIdCount = 50000; + final static int genIdCount = 500000; //1-漂移算法,2-传统算法 final static short method = 1; @@ -20,11 +20,12 @@ public class StartUp { public static void main(String[] args) { IdGeneratorOptions options = new IdGeneratorOptions(); -// options.WorkerIdBitLength = 6; -// options.SeqBitLength = 6; +// options.WorkerIdBitLength = 6; // 默认6 + options.SeqBitLength = 10; // 默认6 // options.BaseTime = 1582206693000L; options.Method = method; options.WorkerId = 1; + // options.TopOverCostCount=2000; // 首先测试一下 IdHelper 方法,获取单个Id YitIdHelper.setIdGenerator(options); @@ -38,7 +39,7 @@ public class StartUp { while (true) { genTest.GenStart(); Thread.sleep(1000); // 每隔1秒执行一次GenStart - System.out.println("Hello World! Java"); + // System.out.println("Hello World! Java"); } } catch (InterruptedException e) { e.printStackTrace(); diff --git a/PHP/Release/php7.3nts-vc15-php_snowdrift.zip b/PHP/Release/php7.3nts-vc15-php_snowdrift.zip new file mode 100644 index 0000000..3eb07ef Binary files /dev/null and b/PHP/Release/php7.3nts-vc15-php_snowdrift.zip differ diff --git a/PHP/Release/php7.4nts-vc15-php_snowdrift.zip b/PHP/Release/php7.4nts-vc15-php_snowdrift.zip new file mode 100644 index 0000000..c34673b Binary files /dev/null and b/PHP/Release/php7.4nts-vc15-php_snowdrift.zip differ diff --git a/PHP/Release/php8.0nts-vs16-php_snowdrift.zip b/PHP/Release/php8.0nts-vs16-php_snowdrift.zip new file mode 100644 index 0000000..639b86a Binary files /dev/null and b/PHP/Release/php8.0nts-vs16-php_snowdrift.zip differ diff --git a/PHP/config.w32 b/PHP/config.w32 index 8d6432e..4a8ded4 100644 --- a/PHP/config.w32 +++ b/PHP/config.w32 @@ -1,18 +1,13 @@ -// $Id$ // vim:ft=javascript -// If your extension references something external, use ARG_WITH -// ARG_WITH("snowdrift", "for snowdrift support", "no"); - -// Otherwise, use ARG_ENABLE -ARG_ENABLE("snowdrift", "enable snowdrift support", "no"); +ARG_ENABLE('snowdrift', 'snowdrift support', 'no'); if (PHP_SNOWDRIFT != "no") { + AC_DEFINE('HAVE_SNOWDRIFT', 1, 'snowdrift support enabled'); snowdrift_source_file="snowdrift.c\ src/snowflake/snowflake.c\ src/snowflake/shm.c\ - src/snowflake/spinlock.c - " - EXTENSION("snowdrift", $snowdrift_source_file, PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + src/snowflake/spinlock.c" + EXTENSION("snowdrift", snowdrift_source_file, null, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); } diff --git a/PHP/snowdrift.c b/PHP/snowdrift.c index 94749bc..8cd13e7 100644 --- a/PHP/snowdrift.c +++ b/PHP/snowdrift.c @@ -66,9 +66,8 @@ static int snowdrift_init() shmctx.size = wid_num * sizeof(snowflake); if (shm_alloc(&shmctx) == -1) { - return FAILURE; + return FAILURE; } - bzero(shmctx.addr, wid_num * sizeof(snowflake)); sf = (snowflake *)shmctx.addr; int i; for (i = 0; i < wid_num; i++) @@ -92,7 +91,6 @@ static int snowdrift_init() { return FAILURE; } - bzero(shmctx.addr, sizeof(snowflake)); sf = (snowflake *)shmctx.addr; sf->Method = SD_G(Method); sf->BaseTime = SD_G(BaseTime); @@ -138,7 +136,7 @@ PHP_METHOD(snowdrift, NextNumId) { zend_long num = 1; zend_long wid = SD_G(WorkerId); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &num, &wid) == FAILURE) + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &num, &wid) == FAILURE) { RETURN_FALSE; } diff --git a/PHP/src/snowflake/shm.c b/PHP/src/snowflake/shm.c index 942e5bb..f515920 100644 --- a/PHP/src/snowflake/shm.c +++ b/PHP/src/snowflake/shm.c @@ -1,65 +1,106 @@ #include #include #include +#ifdef WIN32 +#include "windows.h" +#else #include +#include +#endif #include "shm.h" -#ifdef MAP_ANON +#ifdef WIN32 +#define NAME "SnowDrift" +static HANDLE hMapFile; -int shm_alloc(struct shm *shm) -{ - shm->addr = (void *)mmap(NULL, shm->size, - PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_SHARED, -1, 0); +int shm_alloc(struct shm* shm) { + hMapFile = CreateFileMapping( + INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + 0, + shm->size, + NAME + ); + + if (hMapFile == NULL) + { + return 0; + } + + LPVOID pBuffer = (LPTSTR)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, shm->size); + + if (pBuffer == NULL) + { + CloseHandle(hMapFile); + return 0; + } + memset((char*)pBuffer, 0, shm->size); + shm->addr = (void*)pBuffer; + return 1; +} + +void shm_free(struct shm* shm) { + UnmapViewOfFile(shm->addr); + CloseHandle(hMapFile); +} - if (shm->addr == NULL) - { - return -1; - } +#elif defined(MAP_ANON) - return 0; +int shm_alloc(struct shm* shm) +{ + shm->addr = (void*)mmap(NULL, shm->size, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_SHARED, -1, 0); + + if (shm->addr == NULL) + { + return -1; + } + bzero(shm->addr, shm->size); + return 0; } -void shm_free(struct shm *shm) +void shm_free(struct shm* shm) { - if (shm->addr) - { - munmap((void *)shm->addr, shm->size); - } + if (shm->addr) + { + munmap((void*)shm->addr, shm->size); + } } #else -int shm_alloc(struct shm *shm) +int shm_alloc(struct shm* shm) { - int fd; - - fd = open("/dev/zero", O_RDWR); - if (fd == -1) - { - return -1; - } + int fd; - shm->addr = (void *)mmap(NULL, shm->size, - PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); + fd = open("/dev/zero", O_RDWR); + if (fd == -1) + { + return -1; + } - close(fd); + shm->addr = (void*)mmap(NULL, shm->size, + PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); - if (shm->addr == NULL) - { - return -1; - } + close(fd); - return 0; + if (shm->addr == NULL) + { + return -1; + } + bzero(shm->addr, shm->size); + return 0; } -void shm_free(struct shm *shm) +void shm_free(struct shm* shm) { - if (shm->addr) - { - munmap((void *)shm->addr, shm->size); - } + if (shm->addr) + { + munmap((void*)shm->addr, shm->size); + } } #endif diff --git a/PHP/src/snowflake/snowflake.c b/PHP/src/snowflake/snowflake.c index ff875ea..0f32a6e 100644 --- a/PHP/src/snowflake/snowflake.c +++ b/PHP/src/snowflake/snowflake.c @@ -1,14 +1,16 @@ +#ifdef WIN32 +#include "windows.h" +#include +#else #include #include +#include +#endif #include #include #include "snowflake.h" #include "spinlock.h" -#if defined(WIN32) -#include "windows.h" -#endif - // static void EndOverCostAction(uint64_t useTimeTick, snowflake *flake); static inline uint64_t NextOverCostId(snowflake *flake); static inline uint64_t NextNormalId(snowflake *flake); @@ -16,7 +18,7 @@ static inline uint64_t GetCurrentTimeTick(snowflake *flake); static inline uint64_t GetNextTimeTick(snowflake *flake); static inline uint64_t CalcId(snowflake *flake); static inline uint64_t CalcTurnBackId(snowflake *flake); -static inline uint64_t GetCurrentTime(); +static inline uint64_t GetSysCurrentTime(); int ncpu; uint16_t spin = 2048; @@ -24,102 +26,103 @@ uint32_t pid = 0; void Config(snowflake *flake) { - if (pid == 0) - { - pid = (uint32_t)getpid(); -#if defined(WIN32) - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - ncpu = sysInfo.dwNumberOfProcessors; + if (pid == 0) + { +#ifdef WIN32 + pid = (uint32_t)GetCurrentProcessId(); + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + ncpu = sysInfo.dwNumberOfProcessors; #else - ncpu = sysconf(_SC_NPROCESSORS_ONLN); + pid = (uint32_t)getpid(); + ncpu = sysconf(_SC_NPROCESSORS_ONLN); #endif - if (ncpu <= 0) - { - ncpu = 1; - } - } - if (flake->BaseTime == 0) - { - flake->BaseTime = 1582136402000; - } - else if (flake->BaseTime < 631123200000 || flake->BaseTime > GetCurrentTime()) - { - perror("BaseTime error."); - exit(1); - } + if (ncpu <= 0) + { + ncpu = 1; + } + } + if (flake->BaseTime == 0) + { + flake->BaseTime = 1582136402000; + } + else if (flake->BaseTime < 631123200000 || flake->BaseTime > GetSysCurrentTime()) + { + perror("BaseTime error."); + exit(1); + } - // 2.WorkerIdBitLength - if (flake->WorkerIdBitLength <= 0) - { - perror("WorkerIdBitLength error.(range:[1, 21])"); - exit(1); - } - if (flake->SeqBitLength + flake->WorkerIdBitLength > 22) - { - perror("error:WorkerIdBitLength + SeqBitLength <= 22"); - exit(1); - } - else - { - flake->WorkerIdBitLength = flake->WorkerIdBitLength <= 0 ? 6 : flake->WorkerIdBitLength; - } + // 2.WorkerIdBitLength + if (flake->WorkerIdBitLength <= 0) + { + perror("WorkerIdBitLength error.(range:[1, 21])"); + exit(1); + } + if (flake->SeqBitLength + flake->WorkerIdBitLength > 22) + { + perror("error:WorkerIdBitLength + SeqBitLength <= 22"); + exit(1); + } + else + { + flake->WorkerIdBitLength = flake->WorkerIdBitLength <= 0 ? 6 : flake->WorkerIdBitLength; + } - // 3.WorkerId - uint32_t maxWorkerIdNumber = (1 << flake->WorkerIdBitLength) - 1; - if (maxWorkerIdNumber == 0) - { - maxWorkerIdNumber = 63; - } - if (flake->WorkerId < 0 || flake->WorkerId > maxWorkerIdNumber) - { - perror("WorkerId error. (range:[0, {2^WorkerIdBitLength-1]}"); - exit(1); - } + // 3.WorkerId + uint32_t maxWorkerIdNumber = (1 << flake->WorkerIdBitLength) - 1; + if (maxWorkerIdNumber == 0) + { + maxWorkerIdNumber = 63; + } + if (flake->WorkerId < 0 || flake->WorkerId > maxWorkerIdNumber) + { + perror("WorkerId error. (range:[0, {2^WorkerIdBitLength-1]}"); + exit(1); + } - // 4.SeqBitLength - if (flake->SeqBitLength < 2 || flake->SeqBitLength > 21) - { - perror("SeqBitLength error. (range:[2, 21])"); - exit(1); - } - else - { - flake->SeqBitLength = flake->SeqBitLength <= 0 ? 6 : flake->SeqBitLength; - } + // 4.SeqBitLength + if (flake->SeqBitLength < 2 || flake->SeqBitLength > 21) + { + perror("SeqBitLength error. (range:[2, 21])"); + exit(1); + } + else + { + flake->SeqBitLength = flake->SeqBitLength <= 0 ? 6 : flake->SeqBitLength; + } - // 5.MaxSeqNumber - uint32_t maxSeqNumber = (1 << flake->SeqBitLength) - 1; - if (maxSeqNumber == 0) - { - maxSeqNumber = 63; - } - if (flake->MaxSeqNumber > maxSeqNumber) - { - perror("MaxSeqNumber error. (range:[1, {2^SeqBitLength-1}]"); - exit(1); - } - else - { - flake->MaxSeqNumber = flake->MaxSeqNumber <= 0 ? maxSeqNumber : flake->MaxSeqNumber; - } + // 5.MaxSeqNumber + uint32_t maxSeqNumber = (1 << flake->SeqBitLength) - 1; + if (maxSeqNumber == 0) + { + maxSeqNumber = 63; + } + if (flake->MaxSeqNumber > maxSeqNumber) + { + perror("MaxSeqNumber error. (range:[1, {2^SeqBitLength-1}]"); + exit(1); + } + else + { + flake->MaxSeqNumber = flake->MaxSeqNumber <= 0 ? maxSeqNumber : flake->MaxSeqNumber; + } - // 6.MinSeqNumber - if (flake->MinSeqNumber < 5 || flake->MinSeqNumber > maxSeqNumber) - { - perror("MinSeqNumber error. (range:[5, {MinSeqNumber}]"); - exit(1); - } - else - { - flake->MinSeqNumber = flake->MinSeqNumber <= 0 ? 5 : flake->MinSeqNumber; - } + // 6.MinSeqNumber + if (flake->MinSeqNumber < 5 || flake->MinSeqNumber > maxSeqNumber) + { + perror("MinSeqNumber error. (range:[5, {MinSeqNumber}]"); + exit(1); + } + else + { + flake->MinSeqNumber = flake->MinSeqNumber <= 0 ? 5 : flake->MinSeqNumber; + } - // 7.Others - flake->TopOverCostCount = flake->TopOverCostCount <= 0 ? 2000 : flake->TopOverCostCount; - flake->_TimestampShift = flake->WorkerIdBitLength + flake->SeqBitLength; - flake->_CurrentSeqNumber = flake->MinSeqNumber; - flake->Method = flake->Method; + // 7.Others + flake->TopOverCostCount = flake->TopOverCostCount <= 0 ? 2000 : flake->TopOverCostCount; + flake->_TimestampShift = flake->WorkerIdBitLength + flake->SeqBitLength; + flake->_CurrentSeqNumber = flake->MinSeqNumber; + flake->Method = flake->Method; } // static inline void EndOverCostAction(uint64_t useTimeTick, snowflake *flake) @@ -132,158 +135,178 @@ void Config(snowflake *flake) static inline uint64_t NextOverCostId(snowflake *flake) { - uint64_t currentTimeTick = GetCurrentTimeTick(flake); - if (currentTimeTick > flake->_LastTimeTick) - { - // EndOverCostAction(currentTimeTick, flake); - flake->_LastTimeTick = currentTimeTick; - flake->_CurrentSeqNumber = flake->MinSeqNumber; - flake->_IsOverCost = 0; - flake->_OverCostCountInOneTerm = 0; - // flake->_GenCountInOneTerm = 0; - return CalcId(flake); - } - if (flake->_OverCostCountInOneTerm > flake->TopOverCostCount) - { - // EndOverCostAction(currentTimeTick, flake); - flake->_LastTimeTick = GetNextTimeTick(flake); - flake->_CurrentSeqNumber = flake->MinSeqNumber; - flake->_IsOverCost = 0; - flake->_OverCostCountInOneTerm = 0; - // flake->_GenCountInOneTerm = 0; - return CalcId(flake); - } - if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) - { - flake->_LastTimeTick++; - flake->_CurrentSeqNumber = flake->MinSeqNumber; - flake->_IsOverCost = 1; - flake->_OverCostCountInOneTerm++; - // flake->_GenCountInOneTerm++; - return CalcId(flake); - } + uint64_t currentTimeTick = GetCurrentTimeTick(flake); + if (currentTimeTick > flake->_LastTimeTick) + { + // EndOverCostAction(currentTimeTick, flake); + flake->_LastTimeTick = currentTimeTick; + flake->_CurrentSeqNumber = flake->MinSeqNumber; + flake->_IsOverCost = 0; + flake->_OverCostCountInOneTerm = 0; + // flake->_GenCountInOneTerm = 0; + return CalcId(flake); + } + if (flake->_OverCostCountInOneTerm > flake->TopOverCostCount) + { + // EndOverCostAction(currentTimeTick, flake); + flake->_LastTimeTick = GetNextTimeTick(flake); + flake->_CurrentSeqNumber = flake->MinSeqNumber; + flake->_IsOverCost = 0; + flake->_OverCostCountInOneTerm = 0; + // flake->_GenCountInOneTerm = 0; + return CalcId(flake); + } + if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) + { + flake->_LastTimeTick++; + flake->_CurrentSeqNumber = flake->MinSeqNumber; + flake->_IsOverCost = 1; + flake->_OverCostCountInOneTerm++; + // flake->_GenCountInOneTerm++; + return CalcId(flake); + } - // flake->_GenCountInOneTerm++; - return CalcId(flake); + // flake->_GenCountInOneTerm++; + return CalcId(flake); } static inline uint64_t NextNormalId(snowflake *flake) { - uint64_t currentTimeTick = GetCurrentTimeTick(flake); - if (currentTimeTick < flake->_LastTimeTick) - { - if (flake->_TurnBackTimeTick < 1) - { - flake->_TurnBackTimeTick = flake->_LastTimeTick - 1; - flake->_TurnBackIndex++; - if (flake->_TurnBackIndex > 4) - { - flake->_TurnBackIndex = 1; - } - } - return CalcTurnBackId(flake); - } - if (flake->_TurnBackTimeTick > 0) - { - flake->_TurnBackTimeTick = 0; - } - if (currentTimeTick > flake->_LastTimeTick) - { - flake->_LastTimeTick = currentTimeTick; - flake->_CurrentSeqNumber = flake->MinSeqNumber; - return CalcId(flake); - } - if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) - { - // flake->_TermIndex++; - flake->_LastTimeTick++; - flake->_CurrentSeqNumber = flake->MinSeqNumber; - flake->_IsOverCost = 1; - flake->_OverCostCountInOneTerm = 1; - // flake->_GenCountInOneTerm = 1; - return CalcId(flake); - } - return CalcId(flake); + uint64_t currentTimeTick = GetCurrentTimeTick(flake); + if (currentTimeTick < flake->_LastTimeTick) + { + if (flake->_TurnBackTimeTick < 1) + { + flake->_TurnBackTimeTick = flake->_LastTimeTick - 1; + flake->_TurnBackIndex++; + if (flake->_TurnBackIndex > 4) + { + flake->_TurnBackIndex = 1; + } + } + return CalcTurnBackId(flake); + } + if (flake->_TurnBackTimeTick > 0) + { + flake->_TurnBackTimeTick = 0; + } + if (currentTimeTick > flake->_LastTimeTick) + { + flake->_LastTimeTick = currentTimeTick; + flake->_CurrentSeqNumber = flake->MinSeqNumber; + return CalcId(flake); + } + if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) + { + // flake->_TermIndex++; + flake->_LastTimeTick++; + flake->_CurrentSeqNumber = flake->MinSeqNumber; + flake->_IsOverCost = 1; + flake->_OverCostCountInOneTerm = 1; + // flake->_GenCountInOneTerm = 1; + return CalcId(flake); + } + return CalcId(flake); } -static inline uint64_t GetCurrentTime() +static inline uint64_t GetSysCurrentTime() { - struct timeval t; - gettimeofday(&t, NULL); - return (uint64_t)(t.tv_sec * 1000 + t.tv_usec / 1000); +#ifdef WIN32 + FILETIME file_time; + GetSystemTimeAsFileTime(&file_time); + uint64_t time = ((uint64_t)file_time.dwLowDateTime) + ((uint64_t)file_time.dwHighDateTime << 32); + static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL); + return (uint64_t)((time - EPOCH) / 10000LL); +#else + struct timeval t; + gettimeofday(&t, NULL); + return (uint64_t)(t.tv_sec * 1000 + t.tv_usec / 1000); +#endif } static inline uint64_t GetCurrentTimeTick(snowflake *flake) { - return GetCurrentTime() - flake->BaseTime; + return GetSysCurrentTime() - flake->BaseTime; } static inline uint64_t GetNextTimeTick(snowflake *flake) { - uint64_t tempTimeTicker = GetCurrentTimeTick(flake); - while (tempTimeTicker <= flake->_LastTimeTick) - { - tempTimeTicker = GetCurrentTimeTick(flake); - } - return tempTimeTicker; + uint64_t tempTimeTicker = GetCurrentTimeTick(flake); + struct timespec delay; + delay.tv_sec = 0; + delay.tv_nsec = 500000; + while (1) + { + tempTimeTicker = GetCurrentTimeTick(flake); + if (tempTimeTicker > flake->_LastTimeTick) + { + break; + } +#ifdef WIN32 + SwitchToThread(); +#else + nanosleep(&delay, NULL); +#endif + } + return tempTimeTicker; } static inline uint64_t CalcId(snowflake *flake) { - uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_CurrentSeqNumber); - flake->_CurrentSeqNumber++; - return result; + uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_CurrentSeqNumber); + flake->_CurrentSeqNumber++; + return result; } static inline uint64_t CalcTurnBackId(snowflake *flake) { - uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick); - flake->_TurnBackTimeTick--; - return result; + uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick); + flake->_TurnBackTimeTick--; + return result; } static inline uint64_t NextSonwId(snowflake *flake) { - uint64_t currentTimeTick = GetCurrentTimeTick(flake); - if (flake->_LastTimeTick == currentTimeTick) - { - flake->_CurrentSeqNumber++; - if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) - { - flake->_CurrentSeqNumber = flake->MinSeqNumber; - currentTimeTick = GetNextTimeTick(flake); - } - } - else - { - flake->_CurrentSeqNumber = flake->MinSeqNumber; - } - flake->_LastTimeTick = currentTimeTick; - return (uint64_t)((currentTimeTick << flake->_TimestampShift) | (flake->WorkerId << flake->SeqBitLength) | flake->_CurrentSeqNumber); + uint64_t currentTimeTick = GetCurrentTimeTick(flake); + if (flake->_LastTimeTick == currentTimeTick) + { + flake->_CurrentSeqNumber++; + if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) + { + flake->_CurrentSeqNumber = flake->MinSeqNumber; + currentTimeTick = GetNextTimeTick(flake); + } + } + else + { + flake->_CurrentSeqNumber = flake->MinSeqNumber; + } + flake->_LastTimeTick = currentTimeTick; + return (uint64_t)((currentTimeTick << flake->_TimestampShift) | (flake->WorkerId << flake->SeqBitLength) | flake->_CurrentSeqNumber); } static inline uint64_t GetId(snowflake *flake) { - return flake->Method == 1 ? (flake->_IsOverCost != 0 ? NextOverCostId(flake) : NextNormalId(flake)) : NextSonwId(flake); + return flake->Method == 1 ? (flake->_IsOverCost != 0 ? NextOverCostId(flake) : NextNormalId(flake)) : NextSonwId(flake); } uint64_t NextId(snowflake *flake) { - spin_lock(&flake->_Lock, pid); - uint64_t id = GetId(flake); - spin_unlock(&flake->_Lock, pid); - return id; + spin_lock(&flake->_Lock, pid); + uint64_t id = GetId(flake); + spin_unlock(&flake->_Lock, pid); + return id; } uint64_t *NextNumId(snowflake *flake, uint32_t num) { - uint64_t *arr = (uint64_t *)malloc(sizeof(uint64_t) * num); - spin_lock(&flake->_Lock, pid); - uint32_t i; - for (i = 0; i < num; i++) - { - arr[i] = GetId(flake); - } - spin_unlock(&flake->_Lock, pid); - return arr; + uint64_t *arr = (uint64_t *)malloc(sizeof(uint64_t) * num); + spin_lock(&flake->_Lock, pid); + uint32_t i; + for (i = 0; i < num; i++) + { + arr[i] = GetId(flake); + } + spin_unlock(&flake->_Lock, pid); + return arr; } diff --git a/PHP/src/snowflake/spinlock.c b/PHP/src/snowflake/spinlock.c index 7a2de49..977a409 100644 --- a/PHP/src/snowflake/spinlock.c +++ b/PHP/src/snowflake/spinlock.c @@ -1,47 +1,73 @@ #include +#ifdef WIN32 +#include "windows.h" +#else #include +#endif + #include "spinlock.h" extern int ncpu; extern int spin; -void spin_lock(atomic_t *lock, uint32_t pid) +void spin_lock(atomic_t* lock, uint32_t pid) { - int i, n; - - for (;;) - { - - if (*lock == 0 && - __sync_bool_compare_and_swap(lock, 0, pid)) - { - return; - } - - if (ncpu > 1) - { - - for (n = 1; n < spin; n <<= 1) - { - - for (i = 0; i < n; i++) - { - __asm("pause"); - } - - if (*lock == 0 && - __sync_bool_compare_and_swap(lock, 0, pid)) - { - return; - } - } - } - - sched_yield(); - } + int i, n; + + for (;;) + { + + if (*lock == 0 && +#ifdef WIN32 + InterlockedCompareExchange(lock, pid, 0) == 0 +#else + __sync_bool_compare_and_swap(lock, 0, pid) +#endif + ) + { + return; + } + + if (ncpu > 1) + { + + for (n = 1; n < spin; n <<= 1) + { + + for (i = 0; i < n; i++) + { +#ifdef WIN32 + MemoryBarrier(); +#else + __asm("pause"); +#endif + } + + if (*lock == 0 && +#ifdef WIN32 + InterlockedCompareExchange(lock, pid, 0) == 0 +#else + __sync_bool_compare_and_swap(lock, 0, pid) +#endif + ) + { + return; + } + } + } +#ifdef WIN32 + SwitchToThread(); +#else + sched_yield(); +#endif + } } -void spin_unlock(atomic_t *lock, uint32_t pid) +void spin_unlock(atomic_t* lock, uint32_t pid) { - __sync_bool_compare_and_swap(lock, pid, 0); +#ifdef WIN32 + InterlockedCompareExchange(lock, 0, pid); +#else + __sync_bool_compare_and_swap(lock, pid, 0); +#endif } diff --git a/Python/README.md b/Python/README.md new file mode 100644 index 0000000..ff9aec2 --- /dev/null +++ b/Python/README.md @@ -0,0 +1,12 @@ +# ❄ idgenerator-Python(未完成) + + +## 运行环境 + +Python 3.6+ + +## 引用 包 + + +## 调用示例 + diff --git a/Python/source/DefaultIdGenerator.py b/Python/source/DefaultIdGenerator.py new file mode 100644 index 0000000..586e536 --- /dev/null +++ b/Python/source/DefaultIdGenerator.py @@ -0,0 +1,31 @@ +import time +import traceback +from IdGeneratorOptions import IdGeneratorOptions +from SnowFlake import SnowFlake +from SnowFlakeM1 import SnowFlakeM1 + +class DefaultIdGenerator(object): + + def SetIdGernerator(self, options) : + if options.BaseTime < 100000 : + raise ValueError ("BaseTime error.") + + self.SnowFlake= SnowFlakeM1(options) + + def NextId(self): + return self.SnowFlake.NextId() + +if __name__ == '__main__': + try: + options = IdGeneratorOptions(23) + options.BaseTime = 1231111111 + idgen = DefaultIdGenerator() + idgen.SetIdGernerator(options) + + print (idgen.NextId()) + print (options.__dict__) + + except ValueError as e: + print(e) + + diff --git a/Python/source/IdGeneratorOptions.py b/Python/source/IdGeneratorOptions.py new file mode 100644 index 0000000..2f4d2af --- /dev/null +++ b/Python/source/IdGeneratorOptions.py @@ -0,0 +1,30 @@ +import time + +class IdGeneratorOptions(object): + def __init__(self, workerId = 0, workerIdBitLength = 6, seqBitLength = 6): + + # 雪花计算方法,(1-漂移算法|2-传统算法),默认1。目前只实现了1。 + self.Method = 1 + + # 基础时间(ms单位),不能超过当前系统时间 + self.BaseTime = 1288834974657 + + # 机器码,必须由外部设定,最大值 2^WorkerIdBitLength-1 + self.WorkerId = workerId + + # 机器码位长,默认值6,取值范围 [1, 15](要求:序列数位长+机器码位长不超过22) + self.WorkerIdBitLength = workerIdBitLength + + # 序列数位长,默认值6,取值范围 [3, 21](要求:序列数位长+机器码位长不超过22) + self.SeqBitLength = seqBitLength + + # 最大序列数(含),设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值0,表示最大序列数取最大值(2^SeqBitLength-1]) + self.MaxSeqNumber = 0 + + # 最小序列数(含),默认值5,取值范围 [5, MaxSeqNumber],每毫秒的前5个序列数对应编号0-4是保留位,其中1-4是时间回拨相应预留位,0是手工新值预留位 + self.MinSeqNumber = 5 + + # 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) + self.TopOverCostCount = 2000 + + diff --git a/Python/source/SnowFlake.py b/Python/source/SnowFlake.py new file mode 100644 index 0000000..cb603c8 --- /dev/null +++ b/Python/source/SnowFlake.py @@ -0,0 +1,11 @@ +#!/usr/bin/python +# coding=UTF-8 + +# 组件编号生成器 +class SnowFlake(object): + + def __init__(self, options): + self.Options = options + + def NextId(self): + return 0 diff --git a/Python/source/SnowFlakeM1.py b/Python/source/SnowFlakeM1.py new file mode 100644 index 0000000..985bd08 --- /dev/null +++ b/Python/source/SnowFlakeM1.py @@ -0,0 +1,12 @@ +#!/usr/bin/python +# coding=UTF-8 +from SnowFlake import SnowFlake + +# 组件编号生成器 +class SnowFlakeM1(SnowFlake): + + def __init__(self, options): + self.Options = options + + def NextId(self): + return self.Options.WorkerId diff --git a/README.md b/README.md index 8f515fa..135a197 100644 --- a/README.md +++ b/README.md @@ -222,9 +222,7 @@ QQ群:646049993 #### 动态库下载 -下载链接1:https://github.com/yitter/IdGenerator/releases/download/reg_v1.0/regworkerid_lib_v1.0.zip - -下载链接2:https://gitee.com/yitter/idgenerator/attach_files/662372/download/regworkerid_lib_v1.0.zip +下载链接1:https://github.com/yitter/IdGenerator/releases/download/v1.3.1/regworkerid_lib_v1.3.1.zip #### 动态库接口定义 ``` diff --git a/Rust/source/.gitignore b/Rust/source/.gitignore index 2db4c9f..3dd4666 100644 --- a/Rust/source/.gitignore +++ b/Rust/source/.gitignore @@ -27,6 +27,7 @@ bld/ **/.vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ +.vscode # MSTest test Results [Tt]est[Rr]esult*/ @@ -254,4 +255,4 @@ paket-files/ target/ # macOS -.DS_Store +.DS_Store, diff --git a/Rust/source/src/idgen/snow_worker_m1.rs b/Rust/source/src/idgen/snow_worker_m1.rs index 18f7a58..0af5720 100644 --- a/Rust/source/src/idgen/snow_worker_m1.rs +++ b/Rust/source/src/idgen/snow_worker_m1.rs @@ -2,10 +2,10 @@ * 版权属于:yitter(yitter@126.com) * 开源地址:https://github.com/yitter/idgenerator */ -use std::{thread}; +use crate::idgen::*; use chrono::Utc; +use std::thread; use std::thread::sleep; -use crate::idgen::*; // use lazy_static::lazy_static; pub struct SnowWorkerM1 { @@ -42,26 +42,30 @@ impl SnowWorkerM1 { } pub fn SetOptions(&mut self, options: IdGeneratorOptions) { - // 1.BaseTime if options.BaseTime == 0 { self.BaseTime = 1582136402000; - } else if options.BaseTime < 631123200000 || options.BaseTime > Utc::now().timestamp_millis() { + } else if options.BaseTime < 631123200000 + || options.BaseTime > Utc::now().timestamp_millis() + { panic!("BaseTime error."); } else { self.BaseTime = options.BaseTime; } // 2.WorkerIdBitLength - if options.WorkerIdBitLength <= 0 - { + if options.WorkerIdBitLength <= 0 { panic!("WorkerIdBitLength error.(range:[1, 21])"); } if options.SeqBitLength + options.WorkerIdBitLength > 22 { panic!("error:WorkerIdBitLength + SeqBitLength <= 22"); } else { // self.WorkerIdBitLength = options.WorkerIdBitLength; - self.WorkerIdBitLength = if options.WorkerIdBitLength <= 0 { 6 } else { options.WorkerIdBitLength }; + self.WorkerIdBitLength = if options.WorkerIdBitLength <= 0 { + 6 + } else { + options.WorkerIdBitLength + }; } // 3.WorkerId @@ -80,7 +84,11 @@ impl SnowWorkerM1 { panic!("SeqBitLength error. (range:[2, 21])"); } else { // self.SeqBitLength = options.SeqBitLength; - self.SeqBitLength = if options.SeqBitLength <= 0 { 6 } else { options.SeqBitLength }; + self.SeqBitLength = if options.SeqBitLength <= 0 { + 6 + } else { + options.SeqBitLength + }; } // 5.MaxSeqNumber @@ -91,7 +99,11 @@ impl SnowWorkerM1 { if options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber { panic!("MaxSeqNumber error. (range:[1, {}]", maxSeqNumber); } else { - self.MaxSeqNumber = if options.MaxSeqNumber == 0 { maxSeqNumber } else { options.MaxSeqNumber }; + self.MaxSeqNumber = if options.MaxSeqNumber == 0 { + maxSeqNumber + } else { + options.MaxSeqNumber + }; } // 6.MinSeqNumber @@ -102,8 +114,15 @@ impl SnowWorkerM1 { // self.MinSeqNumber = if options.MinSeqNumber <= 0 { 5 } else { options.MinSeqNumber }; } - // 7.Others - self.TopOverCostCount = if options.TopOverCostCount == 0 { 2000 } else { options.TopOverCostCount }; + // 7.TopOverCostCount + //self.TopOverCostCount = if options.TopOverCostCount == 0 { 2000 } else { options.TopOverCostCount }; + if options.TopOverCostCount < 0 || options.TopOverCostCount > 10000 { + panic!("TopOverCostCount error. (range:[0, 10000]"); + } else { + self.TopOverCostCount = options.TopOverCostCount; + } + + // 8.Others self._TimestampShift = self.WorkerIdBitLength + self.SeqBitLength; self._CurrentSeqNumber = self.MinSeqNumber; @@ -139,7 +158,11 @@ impl SnowWorkerM1 { pub fn NextId(&mut self) -> i64 { // println!("SeqBitLength: {}", self.SeqBitLength); - if self._IsOverCost { self.NextOverCostId() } else { self.NextNormalId() } + if self._IsOverCost { + self.NextOverCostId() + } else { + self.NextNormalId() + } } fn DoGenIdAction(&self, arg: OverCostActionArg) {} @@ -247,17 +270,17 @@ impl SnowWorkerM1 { } fn CalcId(&mut self, useTimeTick: i64) -> i64 { - let result = (useTimeTick << self._TimestampShift) + - (self.WorkerId << self.SeqBitLength) as i64 + - (self._CurrentSeqNumber) as i64; + let result = (useTimeTick << self._TimestampShift) + + (self.WorkerId << self.SeqBitLength) as i64 + + (self._CurrentSeqNumber) as i64; self._CurrentSeqNumber += 1; return result; } fn CalcTurnBackId(&mut self, useTimeTick: i64) -> i64 { - let result = (useTimeTick << self._TimestampShift) + - (self.WorkerId << self.SeqBitLength) as i64 + - (self._TurnBackIndex) as i64; + let result = (useTimeTick << self._TimestampShift) + + (self.WorkerId << self.SeqBitLength) as i64 + + (self._TurnBackIndex) as i64; self._TurnBackTimeTick -= 1; return result; } @@ -270,9 +293,11 @@ impl SnowWorkerM1 { let mut tempTimeTicker = self.GetCurrentTimeTick(); while tempTimeTicker <= self._LastTimeTick { + // 暂停1ms + sleep(std::time::Duration::from_millis(1)); tempTimeTicker = self.GetCurrentTimeTick(); } return tempTimeTicker; } -} \ No newline at end of file +} diff --git a/Rust/source/src/main.rs b/Rust/source/src/main.rs index 70b4e41..382b577 100644 --- a/Rust/source/src/main.rs +++ b/Rust/source/src/main.rs @@ -1,16 +1,15 @@ mod idgen; +use chrono::Utc; use idgen::*; use std::thread; -use chrono::Utc; use std::time::Duration; - fn main() { println!("Hello, world! Rust"); // 总执行次数 - let times = 50000; + let times = 500000; // 是否启用多线程测试 let multiThread = false; @@ -18,7 +17,7 @@ fn main() { // 全局设置一次运行参数 let mut options = IdGeneratorOptions::New(1); options.WorkerIdBitLength = 6; - options.SeqBitLength = 6; + options.SeqBitLength = 10; //... 可以继续设置其它 options 参数 YitIdHelper::SetIdGenerator(options); @@ -32,24 +31,29 @@ fn main() { while i < times { i += 1; - if multiThread { // 这是多线程 - thread::spawn(move || { - id = YitIdHelper::NextId(); - println!("{}, id: {}", i, id); - }); - } else { // 这是单线程 - id = YitIdHelper::NextId(); - } - } + YitIdHelper::NextId(); - println!("最后生成的id: {}", id); - if !multiThread { - // 多线程情况下,时间统计不准确 - let end = Utc::now().timestamp_millis(); - println!("单线程用时 {} ms", end - start); + // if multiThread { // 这是多线程 + // thread::spawn(move || { + // id = YitIdHelper::NextId(); + // println!("{}, id: {}", i, id); + // }); + // } else { // 这是单线程 + // id = YitIdHelper::NextId(); + // } } - thread::sleep(std::time::Duration::from_millis(2000)); + let end = Utc::now().timestamp_millis(); + println!("单线程用时 {} ms", end - start); + + // println!("最后生成的id: {}", id); + // if !multiThread { + // // 多线程情况下,时间统计不准确 + // let end = Utc::now().timestamp_millis(); + // println!("单线程用时 {} ms", end - start); + // } + + thread::sleep(std::time::Duration::from_millis(1000)); } } @@ -71,6 +75,4 @@ fn set_redis() { // }, // Err(error) => println!("Unable to create Redis client: {}", error) // } - - } - +} diff --git a/Tools/AutoRegisterWorkerId/lib/yitidgengo.h b/Tools/AutoRegisterWorkerId/lib/yitidgengo.h index 8daded8..01cad9d 100644 --- a/Tools/AutoRegisterWorkerId/lib/yitidgengo.h +++ b/Tools/AutoRegisterWorkerId/lib/yitidgengo.h @@ -68,14 +68,9 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; extern "C" { #endif -extern __declspec(dllexport) void SetOptions(GoUint16 workerId); -extern __declspec(dllexport) GoUint64 NextId(); // 注册一个 WorkerId,会先注销所有本机已注册的记录 -extern __declspec(dllexport) GoInt32 RegisterOne(char* ip, GoInt32 port, char* password, GoInt32 maxWorkerId); - -// 注册多个 WorkerId,会先注销所有本机已注册的记录 -extern __declspec(dllexport) int* RegisterMany(char* ip, GoInt32 port, char* password, GoInt32 maxWorkerId, GoInt32 totalCount); +extern __declspec(dllexport) GoInt32 RegisterOne(char* ip, GoInt32 port, char* password, GoInt32 maxWorkerId, GoInt database); // 注销本机已注册的 WorkerId extern __declspec(dllexport) void UnRegister();