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  }