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(µstore.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(µstore.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 }