@@ -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 |
@@ -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 |
@@ -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) | |||
} |
@@ -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) | |||