github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/structure/hash.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package structure 15 16 import ( 17 "bytes" 18 "context" 19 "encoding/binary" 20 "strconv" 21 22 "github.com/whtcorpsinc/errors" 23 "github.com/whtcorpsinc/milevadb/ekv" 24 ) 25 26 // HashPair is the pair for (field, value) in a hash. 27 type HashPair struct { 28 Field []byte 29 Value []byte 30 } 31 32 type hashMeta struct { 33 FieldCount int64 34 } 35 36 func (spacetime hashMeta) Value() []byte { 37 buf := make([]byte, 8) 38 binary.BigEndian.PutUint64(buf[0:8], uint64(spacetime.FieldCount)) 39 return buf 40 } 41 42 func (spacetime hashMeta) IsEmpty() bool { 43 return spacetime.FieldCount <= 0 44 } 45 46 // HSet sets the string value of a hash field. 47 func (t *TxStructure) HSet(key []byte, field []byte, value []byte) error { 48 if t.readWriter == nil { 49 return ErrWriteOnSnapshot 50 } 51 return t.uFIDelateHash(key, field, func([]byte) ([]byte, error) { 52 return value, nil 53 }) 54 } 55 56 // HGet gets the value of a hash field. 57 func (t *TxStructure) HGet(key []byte, field []byte) ([]byte, error) { 58 dataKey := t.encodeHashDataKey(key, field) 59 value, err := t.reader.Get(context.TODO(), dataKey) 60 if ekv.ErrNotExist.Equal(err) { 61 err = nil 62 } 63 return value, errors.Trace(err) 64 } 65 66 func (t *TxStructure) hashFieldIntegerVal(val int64) []byte { 67 return []byte(strconv.FormatInt(val, 10)) 68 } 69 70 // EncodeHashAutoIDKeyValue returns the hash key-value generated by the key and the field 71 func (t *TxStructure) EncodeHashAutoIDKeyValue(key []byte, field []byte, val int64) (k, v []byte) { 72 return t.encodeHashDataKey(key, field), t.hashFieldIntegerVal(val) 73 } 74 75 // HInc increments the integer value of a hash field, by step, returns 76 // the value after the increment. 77 func (t *TxStructure) HInc(key []byte, field []byte, step int64) (int64, error) { 78 if t.readWriter == nil { 79 return 0, ErrWriteOnSnapshot 80 } 81 base := int64(0) 82 err := t.uFIDelateHash(key, field, func(oldValue []byte) ([]byte, error) { 83 if oldValue != nil { 84 var err error 85 base, err = strconv.ParseInt(string(oldValue), 10, 64) 86 if err != nil { 87 return nil, errors.Trace(err) 88 } 89 } 90 base += step 91 return t.hashFieldIntegerVal(base), nil 92 }) 93 94 return base, errors.Trace(err) 95 } 96 97 // HGetInt64 gets int64 value of a hash field. 98 func (t *TxStructure) HGetInt64(key []byte, field []byte) (int64, error) { 99 value, err := t.HGet(key, field) 100 if err != nil || value == nil { 101 return 0, errors.Trace(err) 102 } 103 104 var n int64 105 n, err = strconv.ParseInt(string(value), 10, 64) 106 return n, errors.Trace(err) 107 } 108 109 func (t *TxStructure) uFIDelateHash(key []byte, field []byte, fn func(oldValue []byte) ([]byte, error)) error { 110 dataKey := t.encodeHashDataKey(key, field) 111 oldValue, err := t.loadHashValue(dataKey) 112 if err != nil { 113 return errors.Trace(err) 114 } 115 116 newValue, err := fn(oldValue) 117 if err != nil { 118 return errors.Trace(err) 119 } 120 121 // Check if new value is equal to old value. 122 if bytes.Equal(oldValue, newValue) { 123 return nil 124 } 125 126 if err = t.readWriter.Set(dataKey, newValue); err != nil { 127 return errors.Trace(err) 128 } 129 130 spacetimeKey := t.encodeHashMetaKey(key) 131 spacetime, err := t.loadHashMeta(spacetimeKey) 132 if err != nil { 133 return errors.Trace(err) 134 } 135 136 if oldValue == nil { 137 spacetime.FieldCount++ 138 if err = t.readWriter.Set(spacetimeKey, spacetime.Value()); err != nil { 139 return errors.Trace(err) 140 } 141 } 142 143 return nil 144 } 145 146 // HLen gets the number of fields in a hash. 147 func (t *TxStructure) HLen(key []byte) (int64, error) { 148 spacetimeKey := t.encodeHashMetaKey(key) 149 spacetime, err := t.loadHashMeta(spacetimeKey) 150 if err != nil { 151 return 0, errors.Trace(err) 152 } 153 return spacetime.FieldCount, nil 154 } 155 156 // HDel deletes one or more hash fields. 157 func (t *TxStructure) HDel(key []byte, fields ...[]byte) error { 158 if t.readWriter == nil { 159 return ErrWriteOnSnapshot 160 } 161 spacetimeKey := t.encodeHashMetaKey(key) 162 spacetime, err := t.loadHashMeta(spacetimeKey) 163 if err != nil || spacetime.IsEmpty() { 164 return errors.Trace(err) 165 } 166 167 var value []byte 168 for _, field := range fields { 169 dataKey := t.encodeHashDataKey(key, field) 170 171 value, err = t.loadHashValue(dataKey) 172 if err != nil { 173 return errors.Trace(err) 174 } 175 176 if value != nil { 177 if err = t.readWriter.Delete(dataKey); err != nil { 178 return errors.Trace(err) 179 } 180 181 spacetime.FieldCount-- 182 } 183 } 184 185 if spacetime.IsEmpty() { 186 err = t.readWriter.Delete(spacetimeKey) 187 } else { 188 err = t.readWriter.Set(spacetimeKey, spacetime.Value()) 189 } 190 191 return errors.Trace(err) 192 } 193 194 // HKeys gets all the fields in a hash. 195 func (t *TxStructure) HKeys(key []byte) ([][]byte, error) { 196 var keys [][]byte 197 err := t.iterateHash(key, func(field []byte, value []byte) error { 198 keys = append(keys, append([]byte{}, field...)) 199 return nil 200 }) 201 202 return keys, errors.Trace(err) 203 } 204 205 // HGetAll gets all the fields and values in a hash. 206 func (t *TxStructure) HGetAll(key []byte) ([]HashPair, error) { 207 var res []HashPair 208 err := t.iterateHash(key, func(field []byte, value []byte) error { 209 pair := HashPair{ 210 Field: append([]byte{}, field...), 211 Value: append([]byte{}, value...), 212 } 213 res = append(res, pair) 214 return nil 215 }) 216 217 return res, errors.Trace(err) 218 } 219 220 // HGetLastN gets latest N fields and values in hash. 221 func (t *TxStructure) HGetLastN(key []byte, num int) ([]HashPair, error) { 222 res := make([]HashPair, 0, num) 223 err := t.iterReverseHash(key, func(field []byte, value []byte) (bool, error) { 224 pair := HashPair{ 225 Field: append([]byte{}, field...), 226 Value: append([]byte{}, value...), 227 } 228 res = append(res, pair) 229 if len(res) >= num { 230 return false, nil 231 } 232 return true, nil 233 }) 234 return res, errors.Trace(err) 235 } 236 237 // HClear removes the hash value of the key. 238 func (t *TxStructure) HClear(key []byte) error { 239 spacetimeKey := t.encodeHashMetaKey(key) 240 spacetime, err := t.loadHashMeta(spacetimeKey) 241 if err != nil || spacetime.IsEmpty() { 242 return errors.Trace(err) 243 } 244 245 err = t.iterateHash(key, func(field []byte, value []byte) error { 246 k := t.encodeHashDataKey(key, field) 247 return errors.Trace(t.readWriter.Delete(k)) 248 }) 249 250 if err != nil { 251 return errors.Trace(err) 252 } 253 254 return errors.Trace(t.readWriter.Delete(spacetimeKey)) 255 } 256 257 func (t *TxStructure) iterateHash(key []byte, fn func(k []byte, v []byte) error) error { 258 dataPrefix := t.hashDataKeyPrefix(key) 259 it, err := t.reader.Iter(dataPrefix, dataPrefix.PrefixNext()) 260 if err != nil { 261 return errors.Trace(err) 262 } 263 264 var field []byte 265 266 for it.Valid() { 267 if !it.Key().HasPrefix(dataPrefix) { 268 break 269 } 270 271 _, field, err = t.decodeHashDataKey(it.Key()) 272 if err != nil { 273 return errors.Trace(err) 274 } 275 276 if err = fn(field, it.Value()); err != nil { 277 return errors.Trace(err) 278 } 279 280 err = it.Next() 281 if err != nil { 282 return errors.Trace(err) 283 } 284 } 285 286 return nil 287 } 288 289 // ReverseHashIterator is the reverse hash iterator. 290 type ReverseHashIterator struct { 291 t *TxStructure 292 iter ekv.Iterator 293 prefix []byte 294 done bool 295 field []byte 296 } 297 298 // Next implements the Iterator Next. 299 func (i *ReverseHashIterator) Next() error { 300 err := i.iter.Next() 301 if err != nil { 302 return errors.Trace(err) 303 } 304 if !i.iter.Key().HasPrefix(i.prefix) { 305 i.done = true 306 return nil 307 } 308 309 _, field, err := i.t.decodeHashDataKey(i.iter.Key()) 310 if err != nil { 311 return errors.Trace(err) 312 } 313 i.field = field 314 return nil 315 } 316 317 // Valid implements the Iterator Valid. 318 func (i *ReverseHashIterator) Valid() bool { 319 return i.iter.Valid() && !i.done 320 } 321 322 // Key implements the Iterator Key. 323 func (i *ReverseHashIterator) Key() []byte { 324 return i.field 325 } 326 327 // Value implements the Iterator Value. 328 func (i *ReverseHashIterator) Value() []byte { 329 return i.iter.Value() 330 } 331 332 // Close Implements the Iterator Close. 333 func (i *ReverseHashIterator) Close() { 334 } 335 336 // NewHashReverseIter creates a reverse hash iterator. 337 func NewHashReverseIter(t *TxStructure, key []byte) (*ReverseHashIterator, error) { 338 dataPrefix := t.hashDataKeyPrefix(key) 339 it, err := t.reader.IterReverse(dataPrefix.PrefixNext()) 340 if err != nil { 341 return nil, errors.Trace(err) 342 } 343 return &ReverseHashIterator{ 344 t: t, 345 iter: it, 346 prefix: dataPrefix, 347 }, nil 348 } 349 350 func (t *TxStructure) iterReverseHash(key []byte, fn func(k []byte, v []byte) (bool, error)) error { 351 dataPrefix := t.hashDataKeyPrefix(key) 352 it, err := t.reader.IterReverse(dataPrefix.PrefixNext()) 353 if err != nil { 354 return errors.Trace(err) 355 } 356 357 var field []byte 358 for it.Valid() { 359 if !it.Key().HasPrefix(dataPrefix) { 360 break 361 } 362 363 _, field, err = t.decodeHashDataKey(it.Key()) 364 if err != nil { 365 return errors.Trace(err) 366 } 367 368 more, err := fn(field, it.Value()) 369 if !more || err != nil { 370 return errors.Trace(err) 371 } 372 373 err = it.Next() 374 if err != nil { 375 return errors.Trace(err) 376 } 377 } 378 return nil 379 } 380 381 func (t *TxStructure) loadHashMeta(spacetimeKey []byte) (hashMeta, error) { 382 v, err := t.reader.Get(context.TODO(), spacetimeKey) 383 if ekv.ErrNotExist.Equal(err) { 384 err = nil 385 } 386 if err != nil { 387 return hashMeta{}, errors.Trace(err) 388 } 389 390 spacetime := hashMeta{FieldCount: 0} 391 if v == nil { 392 return spacetime, nil 393 } 394 395 if len(v) != 8 { 396 return spacetime, ErrInvalidListMetaData 397 } 398 399 spacetime.FieldCount = int64(binary.BigEndian.Uint64(v[0:8])) 400 return spacetime, nil 401 } 402 403 func (t *TxStructure) loadHashValue(dataKey []byte) ([]byte, error) { 404 v, err := t.reader.Get(context.TODO(), dataKey) 405 if ekv.ErrNotExist.Equal(err) { 406 err = nil 407 v = nil 408 } 409 if err != nil { 410 return nil, errors.Trace(err) 411 } 412 413 return v, nil 414 }