gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/sync/map.go (about) 1 package sync 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "encoding/json" 7 "fmt" 8 "sort" 9 10 "gitee.com/liuxuezhan/go-micro-v1.18.0/store" 11 ckv "gitee.com/liuxuezhan/go-micro-v1.18.0/store/etcd" 12 lock "gitee.com/liuxuezhan/go-micro-v1.18.0/sync/lock/etcd" 13 ) 14 15 type syncMap struct { 16 opts Options 17 } 18 19 func ekey(k interface{}) string { 20 b, _ := json.Marshal(k) 21 return base64.StdEncoding.EncodeToString(b) 22 } 23 24 func (m *syncMap) Read(key, val interface{}) error { 25 if key == nil { 26 return fmt.Errorf("key is nil") 27 } 28 29 kstr := ekey(key) 30 31 // lock 32 if err := m.opts.Lock.Acquire(kstr); err != nil { 33 return err 34 } 35 defer m.opts.Lock.Release(kstr) 36 37 // get key 38 kval, err := m.opts.Store.Read(kstr) 39 if err != nil { 40 return err 41 } 42 43 if len(kval) == 0 { 44 return store.ErrNotFound 45 } 46 47 // decode value 48 return json.Unmarshal(kval[0].Value, val) 49 } 50 51 func (m *syncMap) Write(key, val interface{}) error { 52 if key == nil { 53 return fmt.Errorf("key is nil") 54 } 55 56 kstr := ekey(key) 57 58 // lock 59 if err := m.opts.Lock.Acquire(kstr); err != nil { 60 return err 61 } 62 defer m.opts.Lock.Release(kstr) 63 64 // encode value 65 b, err := json.Marshal(val) 66 if err != nil { 67 return err 68 } 69 70 // set key 71 return m.opts.Store.Write(&store.Record{ 72 Key: kstr, 73 Value: b, 74 }) 75 } 76 77 func (m *syncMap) Delete(key interface{}) error { 78 if key == nil { 79 return fmt.Errorf("key is nil") 80 } 81 82 kstr := ekey(key) 83 84 // lock 85 if err := m.opts.Lock.Acquire(kstr); err != nil { 86 return err 87 } 88 defer m.opts.Lock.Release(kstr) 89 return m.opts.Store.Delete(kstr) 90 } 91 92 func (m *syncMap) Iterate(fn func(key, val interface{}) error) error { 93 keyvals, err := m.opts.Store.List() 94 if err != nil { 95 return err 96 } 97 98 sort.Slice(keyvals, func(i, j int) bool { 99 return keyvals[i].Key < keyvals[j].Key 100 }) 101 102 for _, keyval := range keyvals { 103 // lock 104 if err := m.opts.Lock.Acquire(keyval.Key); err != nil { 105 return err 106 } 107 // unlock 108 defer m.opts.Lock.Release(keyval.Key) 109 110 // unmarshal value 111 var val interface{} 112 113 if len(keyval.Value) > 0 && keyval.Value[0] == '{' { 114 if err := json.Unmarshal(keyval.Value, &val); err != nil { 115 return err 116 } 117 } else { 118 val = keyval.Value 119 } 120 121 // exec func 122 if err := fn(keyval.Key, val); err != nil { 123 return err 124 } 125 126 // save val 127 b, err := json.Marshal(val) 128 if err != nil { 129 return err 130 } 131 132 // no save 133 if i := bytes.Compare(keyval.Value, b); i == 0 { 134 return nil 135 } 136 137 // set key 138 if err := m.opts.Store.Write(&store.Record{ 139 Key: keyval.Key, 140 Value: b, 141 }); err != nil { 142 return err 143 } 144 } 145 146 return nil 147 } 148 149 func NewMap(opts ...Option) Map { 150 var options Options 151 for _, o := range opts { 152 o(&options) 153 } 154 155 if options.Lock == nil { 156 options.Lock = lock.NewLock() 157 } 158 159 if options.Store == nil { 160 options.Store = ckv.NewStore() 161 } 162 163 return &syncMap{ 164 opts: options, 165 } 166 }