github.com/cs3org/reva/v2@v2.27.7/pkg/storage/fs/posix/lookup/store_idcache.go (about)

     1  // Copyright 2018-2021 CERN
     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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package lookup
    20  
    21  import (
    22  	"context"
    23  	"strings"
    24  
    25  	microstore "go-micro.dev/v4/store"
    26  
    27  	"github.com/cs3org/reva/v2/pkg/appctx"
    28  	"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options"
    29  	"github.com/cs3org/reva/v2/pkg/store"
    30  )
    31  
    32  type StoreIDCache struct {
    33  	cache microstore.Store
    34  }
    35  
    36  // NewMemoryIDCache returns a new MemoryIDCache
    37  func NewStoreIDCache(o *options.Options) *StoreIDCache {
    38  	return &StoreIDCache{
    39  		cache: store.Create(
    40  			store.Store(o.IDCache.Store),
    41  			store.Size(o.IDCache.Size),
    42  			microstore.Nodes(o.IDCache.Nodes...),
    43  			microstore.Database(o.IDCache.Database),
    44  			microstore.Table(o.IDCache.Table),
    45  			store.DisablePersistence(o.IDCache.DisablePersistence),
    46  			store.Authentication(o.IDCache.AuthUsername, o.IDCache.AuthPassword),
    47  		),
    48  	}
    49  }
    50  
    51  // Delete removes an entry from the cache
    52  func (c *StoreIDCache) Delete(_ context.Context, spaceID, nodeID string) error {
    53  	v, err := c.cache.Read(cacheKey(spaceID, nodeID))
    54  	if err == nil {
    55  		err := c.cache.Delete(reverseCacheKey(string(v[0].Value)))
    56  		if err != nil {
    57  			return err
    58  		}
    59  	}
    60  
    61  	return c.cache.Delete(cacheKey(spaceID, nodeID))
    62  }
    63  
    64  // DeleteByPath removes an entry from the cache
    65  func (c *StoreIDCache) DeleteByPath(ctx context.Context, path string) error {
    66  	spaceID, nodeID, ok := c.GetByPath(ctx, path)
    67  	if !ok {
    68  		appctx.GetLogger(ctx).Error().Str("record", path).Msg("could not get spaceID and nodeID from cache")
    69  	} else {
    70  		err := c.cache.Delete(reverseCacheKey(path))
    71  		if err != nil {
    72  			appctx.GetLogger(ctx).Error().Err(err).Str("record", path).Str("spaceID", spaceID).Str("nodeID", nodeID).Msg("could not get spaceID and nodeID from cache")
    73  		}
    74  
    75  		err = c.cache.Delete(cacheKey(spaceID, nodeID))
    76  		if err != nil {
    77  			appctx.GetLogger(ctx).Error().Err(err).Str("record", path).Str("spaceID", spaceID).Str("nodeID", nodeID).Msg("could not get spaceID and nodeID from cache")
    78  		}
    79  	}
    80  
    81  	list, err := c.cache.List(
    82  		microstore.ListPrefix(reverseCacheKey(path) + "/"),
    83  	)
    84  	if err != nil {
    85  		return err
    86  	}
    87  	for _, record := range list {
    88  		spaceID, nodeID, ok := c.GetByPath(ctx, record)
    89  		if !ok {
    90  			appctx.GetLogger(ctx).Error().Str("record", record).Msg("could not get spaceID and nodeID from cache")
    91  			continue
    92  		}
    93  
    94  		err := c.cache.Delete(reverseCacheKey(record))
    95  		if err != nil {
    96  			appctx.GetLogger(ctx).Error().Err(err).Str("record", record).Str("spaceID", spaceID).Str("nodeID", nodeID).Msg("could not get spaceID and nodeID from cache")
    97  		}
    98  
    99  		err = c.cache.Delete(cacheKey(spaceID, nodeID))
   100  		if err != nil {
   101  			appctx.GetLogger(ctx).Error().Err(err).Str("record", record).Str("spaceID", spaceID).Str("nodeID", nodeID).Msg("could not get spaceID and nodeID from cache")
   102  		}
   103  	}
   104  	return nil
   105  }
   106  
   107  // DeletePath removes only the path entry from the cache
   108  func (c *StoreIDCache) DeletePath(ctx context.Context, path string) error {
   109  	return c.cache.Delete(reverseCacheKey(path))
   110  }
   111  
   112  // Add adds a new entry to the cache
   113  func (c *StoreIDCache) Set(_ context.Context, spaceID, nodeID, val string) error {
   114  	err := c.cache.Write(&microstore.Record{
   115  		Key:   cacheKey(spaceID, nodeID),
   116  		Value: []byte(val),
   117  	})
   118  	if err != nil {
   119  		return err
   120  	}
   121  
   122  	return c.cache.Write(&microstore.Record{
   123  		Key:   reverseCacheKey(val),
   124  		Value: []byte(cacheKey(spaceID, nodeID)),
   125  	})
   126  }
   127  
   128  // Get returns the value for a given key
   129  func (c *StoreIDCache) Get(_ context.Context, spaceID, nodeID string) (string, bool) {
   130  	records, err := c.cache.Read(cacheKey(spaceID, nodeID))
   131  	if err != nil || len(records) == 0 {
   132  		return "", false
   133  	}
   134  	return string(records[0].Value), true
   135  }
   136  
   137  // GetByPath returns the key for a given value
   138  func (c *StoreIDCache) GetByPath(_ context.Context, val string) (string, string, bool) {
   139  	records, err := c.cache.Read(reverseCacheKey(val))
   140  	if err != nil || len(records) == 0 {
   141  		return "", "", false
   142  	}
   143  	parts := strings.SplitN(string(records[0].Value), "!", 2)
   144  	if len(parts) != 2 {
   145  		return "", "", false
   146  	}
   147  	return parts[0], parts[1], true
   148  }
   149  
   150  func cacheKey(spaceid, nodeID string) string {
   151  	return spaceid + "!" + nodeID
   152  }
   153  
   154  func reverseCacheKey(val string) string {
   155  	return val
   156  }