github.com/cs3org/reva/v2@v2.27.7/pkg/store/memory/multimemstore.go (about) 1 package memory 2 3 import ( 4 "sync" 5 6 "go-micro.dev/v4/store" 7 ) 8 9 // MultiMemStore is a in-memory store implementation using multiple MemStore 10 // to provide support for multiple databases and tables. 11 // Each table will be mapped to its own MemStore, which will be completely 12 // isolated from the rest. In particular, each MemStore will have its own 13 // capacity, so it's possible to have 10 MemStores with full capacity (512 14 // by default) 15 // 16 // The options will be the same for all MemStores unless they're explicitly 17 // initialized otherwise. 18 // 19 // Since each MemStore is isolated, the required synchronization caused by 20 // concurrency will be minimal if the threads use different tables 21 type MultiMemStore struct { 22 storeMap map[string]*MemStore 23 storeMapLock sync.RWMutex 24 genOpts []store.Option 25 } 26 27 // NewMultiMemStore creates a new MultiMemStore. A new MemStore will be mapped based on the options. 28 // A default MemStore will be mapped if no Database and Table aren't used. 29 func NewMultiMemStore(opts ...store.Option) store.Store { 30 m := &MultiMemStore{ 31 storeMap: make(map[string]*MemStore), 32 genOpts: opts, 33 } 34 _ = m.Init(opts...) 35 return m 36 } 37 38 func (m *MultiMemStore) getMemStore(prefix string) *MemStore { 39 m.storeMapLock.RLock() 40 mStore, exists := m.storeMap[prefix] 41 42 if exists { 43 m.storeMapLock.RUnlock() 44 return mStore 45 } 46 47 m.storeMapLock.RUnlock() 48 49 // if not exists 50 newStore := NewMemStore(m.genOpts...).(*MemStore) 51 52 m.storeMapLock.Lock() 53 m.storeMap[prefix] = newStore 54 m.storeMapLock.Unlock() 55 return newStore 56 } 57 58 // Init initializes the mapped MemStore based on the Database and Table values 59 // from the options with the same options. The target MemStore will be 60 // reinitialized if needed. 61 func (m *MultiMemStore) Init(opts ...store.Option) error { 62 optList := store.Options{} 63 for _, opt := range opts { 64 opt(&optList) 65 } 66 67 prefix := optList.Database + "/" + optList.Table 68 69 mStore := m.getMemStore(prefix) 70 return mStore.Init(opts...) 71 } 72 73 // Options returns the options used to create the MultiMemStore. 74 // Specific options for each MemStore aren't available 75 func (m *MultiMemStore) Options() store.Options { 76 optList := store.Options{} 77 for _, opt := range m.genOpts { 78 opt(&optList) 79 } 80 return optList 81 } 82 83 // Write the record in the target MemStore based on the Database and Table 84 // values from the options. A default MemStore will be used if no Database 85 // and Table options are provided. 86 // The write options will be forwarded to the target MemStore 87 func (m *MultiMemStore) Write(r *store.Record, opts ...store.WriteOption) error { 88 wopts := store.WriteOptions{} 89 for _, opt := range opts { 90 opt(&wopts) 91 } 92 93 prefix := wopts.Database + "/" + wopts.Table 94 95 mStore := m.getMemStore(prefix) 96 return mStore.Write(r, opts...) 97 } 98 99 // Read the matching records in the target MemStore based on the Database and Table 100 // values from the options. A default MemStore will be used if no Database 101 // and Table options are provided. 102 // The read options will be forwarded to the target MemStore. 103 // 104 // The expectations regarding the results (sort order, eviction policies, etc) 105 // will be the same as the target MemStore 106 func (m *MultiMemStore) Read(key string, opts ...store.ReadOption) ([]*store.Record, error) { 107 ropts := store.ReadOptions{} 108 for _, opt := range opts { 109 opt(&ropts) 110 } 111 112 prefix := ropts.Database + "/" + ropts.Table 113 114 mStore := m.getMemStore(prefix) 115 return mStore.Read(key, opts...) 116 } 117 118 // Delete the matching records in the target MemStore based on the Database and Table 119 // values from the options. A default MemStore will be used if no Database 120 // and Table options are provided. 121 // 122 // Matching records from other Tables won't be affected. In fact, we won't 123 // access to other Tables 124 func (m *MultiMemStore) Delete(key string, opts ...store.DeleteOption) error { 125 dopts := store.DeleteOptions{} 126 for _, opt := range opts { 127 opt(&dopts) 128 } 129 130 prefix := dopts.Database + "/" + dopts.Table 131 132 mStore := m.getMemStore(prefix) 133 return mStore.Delete(key, opts...) 134 } 135 136 // List the keys in the target MemStore based on the Database and Table 137 // values from the options. A default MemStore will be used if no Database 138 // and Table options are provided. 139 // The list options will be forwarded to the target MemStore. 140 func (m *MultiMemStore) List(opts ...store.ListOption) ([]string, error) { 141 lopts := store.ListOptions{} 142 for _, opt := range opts { 143 opt(&lopts) 144 } 145 146 prefix := lopts.Database + "/" + lopts.Table 147 148 mStore := m.getMemStore(prefix) 149 return mStore.List(opts...) 150 } 151 152 // Close closes the store 153 func (m *MultiMemStore) Close() error { 154 return nil 155 } 156 157 // String returns the name of the store implementation 158 func (m *MultiMemStore) String() string { 159 return "MultiRadixMemStore" 160 }