github.com/decred/politeia@v1.4.0/politeiad/backendv2/tstorebe/store/store.go (about) 1 // Copyright (c) 2020-2022 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package store 6 7 import ( 8 "bytes" 9 "compress/gzip" 10 "encoding/base64" 11 "encoding/gob" 12 "encoding/hex" 13 14 "github.com/decred/politeia/util" 15 "github.com/pkg/errors" 16 ) 17 18 var ( 19 // ErrShutdown is returned when a action is attempted against a store that 20 // is shutdown. 21 ErrShutdown = errors.New("store is shutdown") 22 ) 23 24 const ( 25 // DataTypeStructure describes a blob entry that contains a structure. 26 DataTypeStructure = "struct" 27 ) 28 29 // DataDescriptor provides hints about a data blob. In practice we JSON encode 30 // this struture and stuff it into BlobEntry.DataHint. 31 type DataDescriptor struct { 32 Type string `json:"type"` // Type of data 33 Descriptor string `json:"descriptor"` // Description of the data 34 ExtraData string `json:"extradata,omitempty"` // Value to be freely used 35 } 36 37 // BlobEntry is the structure used to store data in the key-value store. 38 type BlobEntry struct { 39 Digest string `json:"digest"` // SHA256 digest of data, hex encoded 40 DataHint string `json:"datahint"` // Hint that describes data, base64 encoded 41 Data string `json:"data"` // Data payload, base64 encoded 42 } 43 44 // NewBlobEntry returns a new BlobEntry. 45 func NewBlobEntry(dataHint, data []byte) BlobEntry { 46 return BlobEntry{ 47 Digest: hex.EncodeToString(util.Digest(data)), 48 DataHint: base64.StdEncoding.EncodeToString(dataHint), 49 Data: base64.StdEncoding.EncodeToString(data), 50 } 51 } 52 53 // Blobify encodes the provided BlobEntry into a gzipped byte slice. 54 func Blobify(be BlobEntry) ([]byte, error) { 55 var b bytes.Buffer 56 zw := gzip.NewWriter(&b) 57 enc := gob.NewEncoder(zw) 58 err := enc.Encode(be) 59 if err != nil { 60 zw.Close() 61 return nil, err 62 } 63 err = zw.Close() // we must flush gzip buffers 64 if err != nil { 65 return nil, err 66 } 67 return b.Bytes(), nil 68 } 69 70 // Deblob decodes the provided gzipped byte slice into a BlobEntry. 71 func Deblob(blob []byte) (*BlobEntry, error) { 72 zr, err := gzip.NewReader(bytes.NewReader(blob)) 73 if err != nil { 74 return nil, err 75 } 76 r := gob.NewDecoder(zr) 77 var be BlobEntry 78 err = r.Decode(&be) 79 if err != nil { 80 zr.Close() 81 return nil, err 82 } 83 err = zr.Close() 84 if err != nil { 85 return nil, err 86 } 87 return &be, nil 88 } 89 90 // BlobKV represents a blob key-value store. 91 type BlobKV interface { 92 // Put saves the provided key-value entries to the database. New entries are 93 // inserted. Existing entries are updated. 94 // 95 // This operation is atomic. 96 Put(blobs map[string][]byte, encrypt bool) error 97 98 // Del deletes the key-value entries from the database for the provided keys. 99 // 100 // This operation is atomic. 101 Del(keys []string) error 102 103 // Get retrieves the key-value entries from the database for the provided 104 // keys. 105 // 106 // An entry will not exist in the returned map for any blobs that are not 107 // found. It is the responsibility of the caller to ensure a blob was 108 // returned for all provided keys. 109 Get(keys []string) (map[string][]byte, error) 110 111 // Close closes the database connection. 112 Close() 113 }