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  }