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/main.go b/Go/source/main.go index 34b4d37..37781c5 100644 --- a/Go/source/main.go +++ b/Go/source/main.go @@ -4,47 +4,19 @@ 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() } -// 注册一个 WorkerId,会先注销所有本机已注册的记录 -//export RegisterOne -func RegisterOne(ip *C.char, port int32, password *C.char, maxWorkerId int32) int32 { - return regworkerid.RegisterOne(C.GoString(ip), port, C.GoString(password), maxWorkerId) -} - -// 注册多个 WorkerId,会先注销所有本机已注册的记录 -///export RegisterMany -func RegisterMany(ip *C.char, port int32, password *C.char, maxWorkerId int32, totalCount int32) []int32 { - //values := regworkerid.RegisterMany(C.GoString(ip), port, C.GoString(password), maxWorkerId, totalCount) - //return (*C.int)(unsafe.Pointer(&values)) - return regworkerid.RegisterMany(C.GoString(ip), port, C.GoString(password), maxWorkerId, totalCount) -} - -// 注销本机已注册的 WorkerId -//export UnRegister -func UnRegister() { - regworkerid.UnRegister() -} - -// 检查本地WorkerId是否有效(0-有效,其它-无效) -//export Validate -func Validate(workerId int32) int32 { - return regworkerid.Validate(workerId) -} - func main() { const testGenId = true // 测试设置 @@ -70,21 +42,36 @@ func main() { time.Sleep(time.Duration(1000) * time.Millisecond) } } else { - workerIdList := regworkerid.RegisterMany("localhost", 6379, "", 4, 3) + // ip := "localhost" + ipChar := C.CString("localhost") + passChar := C.CString("") + + workerIdList := RegisterMany(ipChar, 6379, passChar, 4, 3, 0) for _, value := range workerIdList { fmt.Println("注册的WorkerId:", value) } - //var workerId = regworkerid.RegisterOne("localhost", 6379, "", 4) - //fmt.Println("注册的WorkerId:", workerId) + id := RegisterOne(ipChar, 6379, passChar, 4, 0) + fmt.Println("注册的WorkerId:", id) + + // C.free(unsafe.Pointer(ipChar)) + // C.free(unsafe.Pointer(passChar)) + + // var workerId = regworkerid.RegisterOne(ip, 6379, "", 4) + // fmt.Println("注册的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 +// 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/source/reg.go b/Go/source/reg.go new file mode 100644 index 0000000..39f64c4 --- /dev/null +++ b/Go/source/reg.go @@ -0,0 +1,32 @@ +package main + +import ( + "C" +) +import "github.com/yitter/idgenerator-go/regworkerid" + +//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) +} + +// 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) +} + +//export UnRegister +// 注销本机已注册的 WorkerId +func UnRegister() { + regworkerid.UnRegister() +} + +//export Validate +// 检查本地WorkerId是否有效(0-有效,其它-无效) +func Validate(workerId int32) int32 { + return regworkerid.Validate(workerId) +} diff --git a/Go/source/regworkerid/reghelper.go b/Go/source/regworkerid/reghelper.go index b3325ab..1a5be94 100644 --- a/Go/source/regworkerid/reghelper.go +++ b/Go/source/regworkerid/reghelper.go @@ -3,15 +3,17 @@ * 开源地址:https://github.com/yitter/idgenerator */ +// Package regworkerid implements a simple distributed id generator. package regworkerid import ( "context" "fmt" - "github.com/go-redis/redis/v8" "strconv" "sync" "time" + + "github.com/go-redis/redis/v8" ) var _client *redis.Client @@ -27,6 +29,7 @@ var _WorkerIdLifeTimeSeconds = 15 // IdGen:WorkerId:Value:xx 的值在 redis var _MaxLoopCount = 10 // 最大循环次数(无可用WorkerId时循环查找) var _SleepMillisecondEveryLoop = 200 // 每次循环后,暂停时间 var _MaxWorkerId int32 = 0 // 最大WorkerId值,超过此值从0开始 +var _Database int = 0 // 最大WorkerId值,超过此值从0开始 var _RedisConnString = "" var _RedisPassword = "" @@ -34,8 +37,10 @@ var _RedisPassword = "" const _WorkerIdIndexKey string = "IdGen:WorkerId:Index" // redis 中的key const _WorkerIdValueKeyPrefix string = "IdGen:WorkerId:Value:" // redis 中的key const _WorkerIdFlag = "Y" // IdGen:WorkerId:Value:xx 的值(将来可用 _token 替代) -const _Log = false // 是否输出日志 +const _Log = false // 是否输出日志 +// export Validate +// 检查本地WorkerId是否有效(0-有效,其它-无效) func Validate(workerId int32) int32 { for _, value := range _workerIdList { if value == workerId { @@ -45,13 +50,15 @@ func Validate(workerId int32) int32 { return 0 - //if workerId == _usingWorkerId { + // if workerId == _usingWorkerId { // return 0 - //} else { + // } else { // return -1 - //} + // } } +// export UnRegister +// 注销本机已注册的 WorkerId func UnRegister() { _workerIdLock.Lock() @@ -73,7 +80,7 @@ func autoUnRegister() { } } -func RegisterMany(ip string, port int32, password string, maxWorkerId int32, totalCount int32) []int32 { +func RegisterMany(ip string, port int32, password string, maxWorkerId int32, totalCount int32, database int) []int32 { if maxWorkerId < 0 { return []int32{-2} } @@ -87,6 +94,7 @@ func RegisterMany(ip string, port int32, password string, maxWorkerId int32, tot _MaxWorkerId = maxWorkerId _RedisConnString = ip + ":" + strconv.Itoa(int(port)) _RedisPassword = password + _Database = database _client = newRedisClient() if _client == nil { return []int32{-1} @@ -96,15 +104,15 @@ func RegisterMany(ip string, port int32, password string, maxWorkerId int32, tot _ = _client.Close() } }() - //_, err := _client.Ping(_ctx).Result() - //if err != nil { + // _, err := _client.Ping(_ctx).Result() + // if err != nil { // //panic("init redis error") // return []int{-3} - //} else { + // } else { // if _Log { // fmt.Println("init redis ok") // } - //} + // } _lifeIndex++ _workerIdList = make([]int32, totalCount) @@ -117,7 +125,7 @@ func RegisterMany(ip string, port int32, password string, maxWorkerId int32, tot id := register(_lifeIndex) if id > -1 { useExtendFunc = true - _workerIdList[key] = id //= append(_workerIdList, id) + _workerIdList[key] = id // = append(_workerIdList, id) } else { break } @@ -130,7 +138,9 @@ func RegisterMany(ip string, port int32, password string, maxWorkerId int32, tot return _workerIdList } -func RegisterOne(ip string, port int32, password string, maxWorkerId int32) int32 { +// export RegisterOne +// 注册一个 WorkerId,会先注销所有本机已注册的记录 +func RegisterOne(ip string, port int32, password string, maxWorkerId int32, database int) int32 { if maxWorkerId < 0 { return -2 } @@ -141,6 +151,7 @@ func RegisterOne(ip string, port int32, password string, maxWorkerId int32) int3 _RedisConnString = ip + ":" + strconv.Itoa(int(port)) _RedisPassword = password _loopCount = 0 + _Database = database _client = newRedisClient() if _client == nil { return -3 @@ -150,15 +161,15 @@ func RegisterOne(ip string, port int32, password string, maxWorkerId int32) int3 _ = _client.Close() } }() - //_, err := _client.Ping(_ctx).Result() - //if err != nil { + // _, err := _client.Ping(_ctx).Result() + // if err != nil { // // panic("init redis error") // return -3 - //} else { + // } else { // if _Log { // fmt.Println("init redis ok") // } - //} + // } _lifeIndex++ var id = register(_lifeIndex) @@ -179,11 +190,11 @@ func newRedisClient() *redis.Client { return redis.NewClient(&redis.Options{ Addr: _RedisConnString, Password: _RedisPassword, - DB: 0, - //PoolSize: 1000, - //ReadTimeout: time.Millisecond * time.Duration(100), - //WriteTimeout: time.Millisecond * time.Duration(100), - //IdleTimeout: time.Second * time.Duration(60), + DB: _Database, + // PoolSize: 1000, + // ReadTimeout: time.Millisecond * time.Duration(100), + // WriteTimeout: time.Millisecond * time.Duration(100), + // IdleTimeout: time.Second * time.Duration(60), }) } @@ -310,9 +321,9 @@ func extendWorkerIdLifeTime(lifeIndex int, workerId int32) { } // 已经被注销,则终止(此步是上一步的二次验证) - //if _usingWorkerId < 0 { + // if _usingWorkerId < 0 { // break - //} + // } // 延长 redis 数据有效期 extendWorkerIdFlag(myWorkerId)