//ref https://github.com/DeanThompson/syncmap/blob/master/syncmap.go package shardmap import ( "basic.com/pubsub/protomsg.git" "sync" //"encoding/json" //"fmt" "time" ) // var commonmux sync.Mutex const ( BKDR_SEED = 131 // 31 131 1313 13131 131313 etc... ) type shardItem struct { sync.RWMutex data map[string]interface{} } type ShardMap struct { shardCnt uint8 shards []*shardItem lasttime time.Time } var Count = make(chan int) type wfOp func(a []byte, b string) float32 /** * @param uint8, shardCnt must be pow of two */ func New(shardCnt uint8) *ShardMap { s := &ShardMap{ shardCnt: shardCnt, shards: make([]*shardItem, shardCnt), lasttime: time.Now(), } for i, _ := range s.shards { s.shards[i] = &shardItem{ data: make(map[string]interface{}), } } return s } func (s *ShardMap) Get(key string) (interface{}, bool) { si := s.locate(key) si.RLock() value, ok := si.data[key] si.RUnlock() return value, ok } func (s *ShardMap) Gettime() time.Time { tm := s.lasttime return tm } func (s *ShardMap) Settime() { s.lasttime = time.Now() } func (s *ShardMap) Set(key string, value interface{}) { si := s.locate(key) si.Lock() si.data[key] = value si.Unlock() } func (s *ShardMap) Del(key string) { si := s.locate(key) si.Lock() delete(si.data, key) si.Unlock() } type kvItem struct { key string value interface{} } func (s *ShardMap) Walk(wf wfOp, sourceFea []byte, baseScore float32, isWebComp bool, target string) (targets []*protomsg.SdkCompareEach) { var wg sync.WaitGroup var lock sync.Mutex for _, si := range s.shards { var tempsi shardItem = *si if len(tempsi.data) == 0 { continue } wg.Add(1) go func(st *shardItem, fw wfOp, sf []byte, baseSec float32, isWeb bool) { defer wg.Done() for _, feature := range st.data { if eif, ok := feature.(*protomsg.Esinfo); ok { if !isWeb { //不会比对抓拍库,只比对有效的人 if eif.Enable == 1 { score := float32(0) if target == "car" { if eif.CarNo != "" { score = strComp(sf, eif.CarNo) } else { continue } } else { score = fw(sf, eif.FaceFeature) } if score > 0 && score >= baseScore { lock.Lock() targets = append(targets, &protomsg.SdkCompareEach{ Id: eif.Id, CompareScore: score, Tableid: eif.Tableid, }) lock.Unlock() } } } else { //来源是web,会比对抓拍库,不管是否有效都需要比对 score := float32(0) if target == "car" { if eif.CarNo != "" { score = strComp(sf, eif.CarNo) } else { continue } } else { score = fw(sf, eif.FaceFeature) } if score > 0 && score >= baseScore { lock.Lock() targets = append(targets, &protomsg.SdkCompareEach{ Id: eif.Id, CompareScore: score, Tableid: eif.Tableid, }) lock.Unlock() } } } } }(&tempsi, wf, sourceFea, baseScore, isWebComp) } wg.Wait() return targets } // print all func (s *ShardMap) Printall() (infos []interface{}) { var wg sync.WaitGroup for _, si := range s.shards { wg.Add(1) go func(s *shardItem) { defer wg.Done() s.RLock() for _, value := range s.data { infos = append(infos, value) } s.RUnlock() }(si) } wg.Wait() return } func (s *ShardMap) GetLen() int { var slen int for i := 0; i < int(s.shardCnt); i++ { slen += len(s.shards[i].data) } return slen } func (s *ShardMap) locate(key string) *shardItem { i := bkdrHash(key) & uint32(s.shardCnt-1) return s.shards[i] } // https://www.byvoid.com/blog/string-hash-compare/ func bkdrHash(str string) uint32 { var h uint32 for _, c := range str { h = h*BKDR_SEED + uint32(c) } return h } func strComp(source []byte, target string) float32 { sourceStr := string(source) if sourceStr == target { return 100 } else { return 0 } }