diff --git a/common.go b/common.go index 33f563e..a1c49a9 100644 --- a/common.go +++ b/common.go @@ -7,7 +7,14 @@ // Date : 2023-12-14 15:51 package easymap -import "sync" +import ( + "encoding/json" + "errors" + "fmt" + "git.zhangdeman.cn/zhangdeman/serialize" + "git.zhangdeman.cn/zhangdeman/util" + "sync" +) // common 公共基础结构 // @@ -15,7 +22,11 @@ import "sync" // // Date : 15:52 2023/12/14 type common struct { - lock *sync.RWMutex // 数据锁 + normalDataTable []map[interface{}]interface{} // 普通数组 + syncMapDataTable []sync.Map // sync_map类型 + dataTableType string // 数据表类型 + segment int // 分片熟练 + lock *sync.RWMutex // 数据锁 } // initLock ... @@ -34,7 +45,7 @@ func (c *common) initLock() { // Date : 21:27 2023/12/24 func (c *common) Lock() { if nil == c.lock { - + return } c.lock.Lock() } @@ -45,6 +56,9 @@ func (c *common) Lock() { // // Date : 21:27 2023/12/24 func (c *common) Unlock() { + if nil == c.lock { + return + } c.lock.Unlock() } @@ -54,6 +68,9 @@ func (c *common) Unlock() { // // Date : 21:43 2023/12/24 func (c *common) RLock() { + if nil == c.lock { + return + } c.lock.RLock() } @@ -63,5 +80,280 @@ func (c *common) RLock() { // // Date : 21:43 2023/12/24 func (c *common) RUnlock() { + if nil == c.lock { + return + } c.lock.RUnlock() } + +func (c *common) Get(key interface{}) (interface{}, bool) { + segmentIndex := util.Hash.GetHashIDMod(key, c.segment) + c.RLock() + defer c.RUnlock() + if c.dataTableType == normalDataTableType { + data, exist := c.normalDataTable[segmentIndex][key] + return data, exist + } else { + // sync map + return c.syncMapDataTable[segmentIndex].Load(key) + } +} + +func (c *common) GetWithReceiver(key interface{}, dest interface{}) error { + if nil == dest { + return errors.New("dest is nil") + } + val, exist := c.Get(key) + if !exist { + return fmt.Errorf("key %v not exist", key) + } + if nil == val { + return errors.New("value is nil") + } + return util.ConvertAssign(dest, val) +} + +func (c *common) GetUint(key interface{}) (uint, error) { + var ( + val uint + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetUint8(key interface{}) (uint8, error) { + var ( + val uint8 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetUint16(key interface{}) (uint16, error) { + var ( + val uint16 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetUint32(key interface{}) (uint32, error) { + var ( + val uint32 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetUint64(key interface{}) (uint64, error) { + var ( + val uint64 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetInt(key interface{}) (int, error) { + var ( + val int + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetInt8(key interface{}) (int8, error) { + var ( + val int8 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetInt16(key interface{}) (int16, error) { + var ( + val int16 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetInt32(key interface{}) (int32, error) { + var ( + val int32 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetInt64(key interface{}) (int64, error) { + var ( + val int64 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetFloat32(key interface{}) (float32, error) { + var ( + val float32 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetFloat64(key interface{}) (float64, error) { + var ( + val float64 + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetBool(key interface{}) (bool, error) { + var ( + val bool + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) GetString(key interface{}) (string, error) { + var ( + val string + err error + ) + err = c.GetWithReceiver(key, &val) + return val, err +} + +func (c *common) Set(key interface{}, value interface{}) { + segmentIndex := util.Hash.GetHashIDMod(key, c.segment) + c.lock.Lock() + defer c.lock.RUnlock() + if c.dataTableType == normalDataTableType { + c.normalDataTable[segmentIndex][key] = value + } else { + // sync map + c.syncMapDataTable[segmentIndex].Store(key, value) + } +} + +func (c *common) Del(key interface{}) { + segmentIndex := util.Hash.GetHashIDMod(key, c.segment) + c.Lock() + defer c.Unlock() + if c.dataTableType == normalDataTableType { + delete(c.normalDataTable[segmentIndex], key) + } else { + c.syncMapDataTable[segmentIndex].Delete(key) + } +} + +func (c *common) Exist(key interface{}) bool { + _, exist := c.Get(key) + return exist +} + +func (c *common) GetAll() map[interface{}]interface{} { + result := make(map[interface{}]interface{}) + c.RLock() + defer c.RUnlock() + for i := 0; i < c.segment; i++ { + if c.dataTableType == normalDataTableType { + for k, v := range c.normalDataTable[i] { + result[k] = v + } + } else { + c.syncMapDataTable[i].Range(func(key, value interface{}) bool { + result[key] = value + return true + }) + } + } + return result +} + +// GetAllForMapKeyString ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 9:48 下午 2021/9/15 +func (c *common) GetAllForMapKeyString() map[string]interface{} { + fullData := c.GetAll() + finalData := make(map[string]interface{}) + for k, v := range fullData { + finalData[fmt.Sprintf("%v", k)] = v + } + return finalData +} + +// Iterator ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 17:32 2023/3/7 +func (c *common) Iterator(handleFunc IteratorFunc) { + if nil == handleFunc { + return + } + c.Lock() + c.Unlock() + isBreak := false + for i := 0; i < c.segment; i++ { + if c.dataTableType == normalDataTableType { + for k, v := range c.normalDataTable[i] { + if !handleFunc(k, v) { + isBreak = true + break + } + } + if isBreak { + break + } + } else { + c.syncMapDataTable[i].Range(func(key, value any) bool { + return handleFunc(key, value) + }) + } + } +} + +// ToStruct ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:42 2023/8/10 +func (c *common) ToStruct(receiver interface{}) error { + if nil == receiver { + return errors.New("receiver is nil") + } + mapData := c.GetAll() + byteData, err := json.Marshal(mapData) + if nil != err { + return err + } + return serialize.JSON.UnmarshalWithNumber(byteData, receiver) +} + +// ToString 转字符串 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 20:44 2023/8/15 +func (c *common) ToString() string { + mapData := c.GetAllForMapKeyString() + return serialize.JSON.MarshalForString(mapData) +} diff --git a/define.go b/define.go index 3db3d65..82f0b3e 100644 --- a/define.go +++ b/define.go @@ -9,3 +9,8 @@ package easymap // IteratorFunc 迭代函数, 返回值为是否继续迭代,true 继续迭代 false 终止后续迭代 type IteratorFunc func(key interface{}, value interface{}) bool + +const ( + normalDataTableType = "NORMAL" + syncMapDataTableType = "SYNC_MAP" +) diff --git a/segment.go b/segment.go index 8485b61..82ee3a0 100644 --- a/segment.go +++ b/segment.go @@ -7,15 +7,6 @@ // Date : 2021-02-23 10:47 下午 package easymap -import ( - "encoding/json" - "errors" - "fmt" - "git.zhangdeman.cn/zhangdeman/util" - - "git.zhangdeman.cn/zhangdeman/serialize" -) - // NewSegment 获取分段map实例 // // Author : go_developer@163.com<白茶清欢> @@ -26,262 +17,22 @@ func NewSegment(segmentCnt int) (EasyMap, error) { return nil, segmentError() } em := &segment{ - common: &common{}, - segment: segmentCnt, + &common{ + normalDataTable: nil, + syncMapDataTable: nil, + dataTableType: normalDataTableType, + segment: segmentCnt, + lock: nil, + }, } - em.dataTable = make([]map[interface{}]interface{}, segmentCnt) + em.normalDataTable = make([]map[interface{}]interface{}, segmentCnt) for i := 0; i < segmentCnt; i++ { - em.dataTable[i] = make(map[interface{}]interface{}) + em.normalDataTable[i] = make(map[interface{}]interface{}) } em.common.initLock() return em, nil } type segment struct { - common *common - dataTable []map[interface{}]interface{} - segment int -} - -func (s *segment) Get(key interface{}) (interface{}, bool) { - segmentIndex := util.Hash.GetHashIDMod(key, s.segment) - s.common.RLock() - defer s.common.RUnlock() - data, exist := s.dataTable[segmentIndex][key] - return data, exist -} - -func (s *segment) GetWithReceiver(key interface{}, dest interface{}) error { - if nil == dest { - return errors.New("dest is nil") - } - val, exist := s.Get(key) - if !exist { - return fmt.Errorf("key %v not exist", key) - } - if nil == val { - return errors.New("value is nil") - } - return util.ConvertAssign(dest, val) -} - -func (s *segment) GetUint(key interface{}) (uint, error) { - var ( - val uint - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetUint8(key interface{}) (uint8, error) { - var ( - val uint8 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetUint16(key interface{}) (uint16, error) { - var ( - val uint16 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetUint32(key interface{}) (uint32, error) { - var ( - val uint32 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetUint64(key interface{}) (uint64, error) { - var ( - val uint64 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetInt(key interface{}) (int, error) { - var ( - val int - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetInt8(key interface{}) (int8, error) { - var ( - val int8 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetInt16(key interface{}) (int16, error) { - var ( - val int16 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetInt32(key interface{}) (int32, error) { - var ( - val int32 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetInt64(key interface{}) (int64, error) { - var ( - val int64 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetFloat32(key interface{}) (float32, error) { - var ( - val float32 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetFloat64(key interface{}) (float64, error) { - var ( - val float64 - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetBool(key interface{}) (bool, error) { - var ( - val bool - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) GetString(key interface{}) (string, error) { - var ( - val string - err error - ) - err = s.GetWithReceiver(key, &val) - return val, err -} - -func (s *segment) Set(key interface{}, value interface{}) { - segmentIndex := util.Hash.GetHashIDMod(key, s.segment) - s.dataTable[segmentIndex][key] = value -} - -func (s *segment) Del(key interface{}) { - segmentIndex := util.Hash.GetHashIDMod(key, s.segment) - s.common.Lock() - defer s.common.Unlock() - delete(s.dataTable[segmentIndex], key) -} - -func (s *segment) Exist(key interface{}) bool { - _, exist := s.Get(key) - return exist -} - -func (s *segment) GetAll() map[interface{}]interface{} { - result := make(map[interface{}]interface{}) - s.common.RLock() - defer s.common.RUnlock() - for i := 0; i < s.segment; i++ { - for k, v := range s.dataTable[i] { - result[k] = v - } - } - return result -} - -// GetAllForMapKeyString ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 9:48 下午 2021/9/15 -func (s *segment) GetAllForMapKeyString() map[string]interface{} { - fullData := s.GetAll() - finalData := make(map[string]interface{}) - for k, v := range fullData { - finalData[fmt.Sprintf("%v", k)] = v - } - return finalData -} - -// Iterator ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 17:32 2023/3/7 -func (s *segment) Iterator(handleFunc IteratorFunc) { - if nil == handleFunc { - return - } - s.common.Lock() - s.common.Unlock() - isBreak := false - for i := 0; i < s.segment; i++ { - for k, v := range s.dataTable[i] { - if !handleFunc(k, v) { - isBreak = true - break - } - } - if isBreak { - break - } - } -} - -// ToStruct ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 15:42 2023/8/10 -func (s *segment) ToStruct(receiver interface{}) error { - if nil == receiver { - return errors.New("receiver is nil") - } - mapData := s.GetAll() - byteData, err := json.Marshal(mapData) - if nil != err { - return err - } - return serialize.JSON.UnmarshalWithNumber(byteData, receiver) -} - -// ToString 转字符串 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 20:44 2023/8/15 -func (s *segment) ToString() string { - mapData := s.GetAllForMapKeyString() - return serialize.JSON.MarshalForString(mapData) + *common } diff --git a/sync_segment.go b/sync_segment.go index 985a4d2..0b17c7a 100644 --- a/sync_segment.go +++ b/sync_segment.go @@ -8,12 +8,7 @@ package easymap import ( - "bytes" - "encoding/json" - "errors" - "fmt" - - "git.zhangdeman.cn/zhangdeman/util" + "sync" ) // NewSegmentSync 获取SegmentSync实例 @@ -26,164 +21,22 @@ func NewSegmentSync(segment int) (EasyMap, error) { return nil, segmentError() } ss := &segmentSync{ - segment: segment, + &common{ + normalDataTable: nil, + syncMapDataTable: nil, + dataTableType: syncMapDataTableType, + segment: segment, + lock: nil, + }, } - ss.dataTable = make([]EasyMap, segment) + ss.syncMapDataTable = make([]sync.Map, segment) for i := 0; i < segment; i++ { - ss.dataTable[i] = NewSync() + ss.syncMapDataTable[i] = sync.Map{} } + ss.initLock() return ss, nil } type segmentSync struct { - dataTable []EasyMap - segment int -} - -func (s *segmentSync) Get(key interface{}) (interface{}, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].Get(key) -} - -func (s *segmentSync) GetWithReceiver(key interface{}, dest interface{}) error { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetWithReceiver(key, dest) -} - -func (s *segmentSync) GetUint(key interface{}) (uint, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetUint(key) -} - -func (s *segmentSync) GetUint8(key interface{}) (uint8, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetUint8(key) -} - -func (s *segmentSync) GetUint16(key interface{}) (uint16, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetUint16(key) -} - -func (s *segmentSync) GetUint32(key interface{}) (uint32, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetUint32(key) -} - -func (s *segmentSync) GetUint64(key interface{}) (uint64, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetUint64(key) -} - -func (s *segmentSync) GetInt(key interface{}) (int, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetInt(key) -} - -func (s *segmentSync) GetInt8(key interface{}) (int8, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetInt8(key) -} - -func (s *segmentSync) GetInt16(key interface{}) (int16, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetInt16(key) -} - -func (s *segmentSync) GetInt32(key interface{}) (int32, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetInt32(key) -} - -func (s *segmentSync) GetInt64(key interface{}) (int64, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetInt64(key) -} - -func (s *segmentSync) GetFloat32(key interface{}) (float32, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetFloat32(key) -} - -func (s *segmentSync) GetFloat64(key interface{}) (float64, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetFloat64(key) -} - -func (s *segmentSync) GetBool(key interface{}) (bool, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetBool(key) -} - -func (s *segmentSync) GetString(key interface{}) (string, error) { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].GetString(key) -} - -func (s *segmentSync) Set(key interface{}, value interface{}) { - s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].Set(key, value) -} - -func (s *segmentSync) Del(key interface{}) { - s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].Del(key) -} - -func (s *segmentSync) Exist(key interface{}) bool { - return s.dataTable[util.Hash.GetHashIDMod(key, s.segment)].Exist(key) -} - -func (s *segmentSync) GetAll() map[interface{}]interface{} { - result := make(map[interface{}]interface{}) - for i := 0; i < s.segment; i++ { - for k, v := range s.dataTable[i].GetAll() { - result[k] = v - } - } - return result -} - -// GetAllForMapKeyString ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 9:48 下午 2021/9/15 -func (s *segmentSync) GetAllForMapKeyString() map[string]interface{} { - fullData := s.GetAll() - finalData := make(map[string]interface{}) - for k, v := range fullData { - finalData[fmt.Sprintf("%v", k)] = v - } - return finalData -} - -func (s *segmentSync) Iterator(handleFunc IteratorFunc) { - if nil == handleFunc { - return - } - isBreak := false - for i := 0; i < s.segment; i++ { - for k, v := range s.dataTable[i].GetAll() { - if !handleFunc(k, v) { - isBreak = true - break - } - } - if isBreak { - break - } - } -} - -// ToStruct ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 15:48 2023/8/10 -func (s *segmentSync) ToStruct(receiver interface{}) error { - if nil == receiver { - return errors.New("receiver is nil") - } - mapData := s.GetAll() - byteData, err := json.Marshal(mapData) - if nil != err { - return err - } - decoder := json.NewDecoder(bytes.NewReader(byteData)) - decoder.UseNumber() - return decoder.Decode(receiver) -} - -// ToString 转字符串 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 20:44 2023/8/15 -func (s *segmentSync) ToString() string { - mapData := s.GetAllForMapKeyString() - byteData, _ := json.Marshal(mapData) - return string(byteData) + *common }