github.com/cs3org/reva/v2@v2.27.7/internal/grpc/services/gateway/storageprovidercache.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 gateway 20 21 import ( 22 "context" 23 24 rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" 25 provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 26 registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" 27 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 28 sdk "github.com/cs3org/reva/v2/pkg/sdk/common" 29 "github.com/cs3org/reva/v2/pkg/storage/cache" 30 "github.com/cs3org/reva/v2/pkg/utils" 31 "github.com/pkg/errors" 32 "google.golang.org/grpc" 33 ) 34 35 /* 36 Cached Registry 37 */ 38 39 type cachedRegistryClient struct { 40 c registry.RegistryAPIClient 41 cache cache.ProviderCache 42 } 43 44 func (c *cachedRegistryClient) ListStorageProviders(ctx context.Context, in *registry.ListStorageProvidersRequest, opts ...grpc.CallOption) (*registry.ListStorageProvidersResponse, error) { 45 46 spaceID := sdk.DecodeOpaqueMap(in.Opaque)["space_id"] 47 48 u, ok := ctxpkg.ContextGetUser(ctx) 49 if !ok { 50 return nil, errors.New("user not found in context") 51 } 52 53 key := c.cache.GetKey(u.GetId(), spaceID) 54 if key != "" { 55 s := ®istry.ListStorageProvidersResponse{} 56 if err := c.cache.PullFromCache(key, s); err == nil { 57 return s, nil 58 } 59 } 60 61 resp, err := c.c.ListStorageProviders(ctx, in, opts...) 62 switch { 63 case err != nil: 64 return nil, err 65 case resp.Status.Code != rpc.Code_CODE_OK: 66 return resp, nil 67 case spaceID == "": 68 return resp, nil 69 case spaceID == utils.ShareStorageSpaceID: // TODO do we need to compare providerid and spaceid separately? 70 return resp, nil 71 default: 72 return resp, c.cache.PushToCache(key, resp) 73 } 74 } 75 76 // not cached 77 78 func (c *cachedRegistryClient) GetStorageProviders(ctx context.Context, in *registry.GetStorageProvidersRequest, opts ...grpc.CallOption) (*registry.GetStorageProvidersResponse, error) { 79 return c.c.GetStorageProviders(ctx, in, opts...) 80 } 81 82 func (c *cachedRegistryClient) GetHome(ctx context.Context, in *registry.GetHomeRequest, opts ...grpc.CallOption) (*registry.GetHomeResponse, error) { 83 return c.c.GetHome(ctx, in, opts...) 84 } 85 86 /* 87 Cached Spaces Provider 88 */ 89 90 type cachedSpacesAPIClient struct { 91 c provider.SpacesAPIClient 92 createPersonalSpaceCache cache.CreatePersonalSpaceCache 93 } 94 95 // CreateStorageSpace creates a storage space 96 func (c *cachedSpacesAPIClient) CreateStorageSpace(ctx context.Context, in *provider.CreateStorageSpaceRequest, opts ...grpc.CallOption) (*provider.CreateStorageSpaceResponse, error) { 97 if in.Type == "personal" { 98 u, ok := ctxpkg.ContextGetUser(ctx) 99 if !ok { 100 return nil, errors.New("user not found in context") 101 } 102 103 key := c.createPersonalSpaceCache.GetKey(u.GetId()) 104 if key != "" { 105 s := &provider.CreateStorageSpaceResponse{} 106 if err := c.createPersonalSpaceCache.PullFromCache(key, s); err == nil { 107 return s, nil 108 } 109 } 110 resp, err := c.c.CreateStorageSpace(ctx, in, opts...) 111 switch { 112 case err != nil: 113 return nil, err 114 case resp.Status.Code != rpc.Code_CODE_OK && resp.Status.Code != rpc.Code_CODE_ALREADY_EXISTS: 115 return resp, nil 116 case key == "": 117 return resp, nil 118 default: 119 return resp, c.createPersonalSpaceCache.PushToCache(key, resp) 120 } 121 } 122 return c.c.CreateStorageSpace(ctx, in, opts...) 123 } 124 125 func (c *cachedSpacesAPIClient) ListStorageSpaces(ctx context.Context, in *provider.ListStorageSpacesRequest, opts ...grpc.CallOption) (*provider.ListStorageSpacesResponse, error) { 126 return c.c.ListStorageSpaces(ctx, in, opts...) 127 } 128 func (c *cachedSpacesAPIClient) UpdateStorageSpace(ctx context.Context, in *provider.UpdateStorageSpaceRequest, opts ...grpc.CallOption) (*provider.UpdateStorageSpaceResponse, error) { 129 return c.c.UpdateStorageSpace(ctx, in, opts...) 130 } 131 func (c *cachedSpacesAPIClient) DeleteStorageSpace(ctx context.Context, in *provider.DeleteStorageSpaceRequest, opts ...grpc.CallOption) (*provider.DeleteStorageSpaceResponse, error) { 132 return c.c.DeleteStorageSpace(ctx, in, opts...) 133 } 134 135 /* 136 Cached Storage Provider 137 */ 138 139 type cachedAPIClient struct { 140 c provider.ProviderAPIClient 141 createPersonalSpaceCache cache.CreatePersonalSpaceCache 142 } 143 144 // CreateHome caches calls to CreateHome locally - anyways they only need to be called once per user 145 func (c *cachedAPIClient) CreateHome(ctx context.Context, in *provider.CreateHomeRequest, opts ...grpc.CallOption) (*provider.CreateHomeResponse, error) { 146 u, ok := ctxpkg.ContextGetUser(ctx) 147 if !ok { 148 return nil, errors.New("user not found in context") 149 } 150 151 key := c.createPersonalSpaceCache.GetKey(u.GetId()) 152 if key != "" { 153 s := &provider.CreateHomeResponse{} 154 if err := c.createPersonalSpaceCache.PullFromCache(key, s); err == nil { 155 return s, nil 156 } 157 } 158 resp, err := c.c.CreateHome(ctx, in, opts...) 159 switch { 160 case err != nil: 161 return nil, err 162 case resp.Status.Code != rpc.Code_CODE_OK && resp.Status.Code != rpc.Code_CODE_ALREADY_EXISTS: 163 return resp, nil 164 case key == "": 165 return resp, nil 166 default: 167 return resp, c.createPersonalSpaceCache.PushToCache(key, resp) 168 } 169 } 170 171 // methods below here are not cached, they just call the client directly 172 173 // Stat returns the Resoure info for a given resource 174 func (c *cachedAPIClient) Stat(ctx context.Context, in *provider.StatRequest, opts ...grpc.CallOption) (*provider.StatResponse, error) { 175 return c.c.Stat(ctx, in, opts...) 176 } 177 func (c *cachedAPIClient) AddGrant(ctx context.Context, in *provider.AddGrantRequest, opts ...grpc.CallOption) (*provider.AddGrantResponse, error) { 178 return c.c.AddGrant(ctx, in, opts...) 179 } 180 func (c *cachedAPIClient) CreateContainer(ctx context.Context, in *provider.CreateContainerRequest, opts ...grpc.CallOption) (*provider.CreateContainerResponse, error) { 181 return c.c.CreateContainer(ctx, in, opts...) 182 } 183 func (c *cachedAPIClient) Delete(ctx context.Context, in *provider.DeleteRequest, opts ...grpc.CallOption) (*provider.DeleteResponse, error) { 184 return c.c.Delete(ctx, in, opts...) 185 } 186 func (c *cachedAPIClient) DenyGrant(ctx context.Context, in *provider.DenyGrantRequest, opts ...grpc.CallOption) (*provider.DenyGrantResponse, error) { 187 return c.c.DenyGrant(ctx, in, opts...) 188 } 189 func (c *cachedAPIClient) GetPath(ctx context.Context, in *provider.GetPathRequest, opts ...grpc.CallOption) (*provider.GetPathResponse, error) { 190 return c.c.GetPath(ctx, in, opts...) 191 } 192 func (c *cachedAPIClient) GetQuota(ctx context.Context, in *provider.GetQuotaRequest, opts ...grpc.CallOption) (*provider.GetQuotaResponse, error) { 193 return c.c.GetQuota(ctx, in, opts...) 194 } 195 func (c *cachedAPIClient) InitiateFileDownload(ctx context.Context, in *provider.InitiateFileDownloadRequest, opts ...grpc.CallOption) (*provider.InitiateFileDownloadResponse, error) { 196 return c.c.InitiateFileDownload(ctx, in, opts...) 197 } 198 func (c *cachedAPIClient) InitiateFileUpload(ctx context.Context, in *provider.InitiateFileUploadRequest, opts ...grpc.CallOption) (*provider.InitiateFileUploadResponse, error) { 199 return c.c.InitiateFileUpload(ctx, in, opts...) 200 } 201 func (c *cachedAPIClient) ListGrants(ctx context.Context, in *provider.ListGrantsRequest, opts ...grpc.CallOption) (*provider.ListGrantsResponse, error) { 202 return c.c.ListGrants(ctx, in, opts...) 203 } 204 func (c *cachedAPIClient) ListContainerStream(ctx context.Context, in *provider.ListContainerStreamRequest, opts ...grpc.CallOption) (provider.ProviderAPI_ListContainerStreamClient, error) { 205 return c.c.ListContainerStream(ctx, in, opts...) 206 } 207 func (c *cachedAPIClient) ListContainer(ctx context.Context, in *provider.ListContainerRequest, opts ...grpc.CallOption) (*provider.ListContainerResponse, error) { 208 return c.c.ListContainer(ctx, in, opts...) 209 } 210 func (c *cachedAPIClient) ListFileVersions(ctx context.Context, in *provider.ListFileVersionsRequest, opts ...grpc.CallOption) (*provider.ListFileVersionsResponse, error) { 211 return c.c.ListFileVersions(ctx, in, opts...) 212 } 213 func (c *cachedAPIClient) ListRecycleStream(ctx context.Context, in *provider.ListRecycleStreamRequest, opts ...grpc.CallOption) (provider.ProviderAPI_ListRecycleStreamClient, error) { 214 return c.c.ListRecycleStream(ctx, in, opts...) 215 } 216 func (c *cachedAPIClient) ListRecycle(ctx context.Context, in *provider.ListRecycleRequest, opts ...grpc.CallOption) (*provider.ListRecycleResponse, error) { 217 return c.c.ListRecycle(ctx, in, opts...) 218 } 219 func (c *cachedAPIClient) Move(ctx context.Context, in *provider.MoveRequest, opts ...grpc.CallOption) (*provider.MoveResponse, error) { 220 return c.c.Move(ctx, in, opts...) 221 } 222 func (c *cachedAPIClient) RemoveGrant(ctx context.Context, in *provider.RemoveGrantRequest, opts ...grpc.CallOption) (*provider.RemoveGrantResponse, error) { 223 return c.c.RemoveGrant(ctx, in, opts...) 224 } 225 func (c *cachedAPIClient) PurgeRecycle(ctx context.Context, in *provider.PurgeRecycleRequest, opts ...grpc.CallOption) (*provider.PurgeRecycleResponse, error) { 226 return c.c.PurgeRecycle(ctx, in, opts...) 227 } 228 func (c *cachedAPIClient) RestoreFileVersion(ctx context.Context, in *provider.RestoreFileVersionRequest, opts ...grpc.CallOption) (*provider.RestoreFileVersionResponse, error) { 229 return c.c.RestoreFileVersion(ctx, in, opts...) 230 } 231 func (c *cachedAPIClient) RestoreRecycleItem(ctx context.Context, in *provider.RestoreRecycleItemRequest, opts ...grpc.CallOption) (*provider.RestoreRecycleItemResponse, error) { 232 return c.c.RestoreRecycleItem(ctx, in, opts...) 233 } 234 func (c *cachedAPIClient) UpdateGrant(ctx context.Context, in *provider.UpdateGrantRequest, opts ...grpc.CallOption) (*provider.UpdateGrantResponse, error) { 235 return c.c.UpdateGrant(ctx, in, opts...) 236 } 237 func (c *cachedAPIClient) CreateSymlink(ctx context.Context, in *provider.CreateSymlinkRequest, opts ...grpc.CallOption) (*provider.CreateSymlinkResponse, error) { 238 return c.c.CreateSymlink(ctx, in, opts...) 239 } 240 func (c *cachedAPIClient) CreateReference(ctx context.Context, in *provider.CreateReferenceRequest, opts ...grpc.CallOption) (*provider.CreateReferenceResponse, error) { 241 return c.c.CreateReference(ctx, in, opts...) 242 } 243 func (c *cachedAPIClient) SetArbitraryMetadata(ctx context.Context, in *provider.SetArbitraryMetadataRequest, opts ...grpc.CallOption) (*provider.SetArbitraryMetadataResponse, error) { 244 return c.c.SetArbitraryMetadata(ctx, in, opts...) 245 } 246 func (c *cachedAPIClient) UnsetArbitraryMetadata(ctx context.Context, in *provider.UnsetArbitraryMetadataRequest, opts ...grpc.CallOption) (*provider.UnsetArbitraryMetadataResponse, error) { 247 return c.c.UnsetArbitraryMetadata(ctx, in, opts...) 248 } 249 func (c *cachedAPIClient) SetLock(ctx context.Context, in *provider.SetLockRequest, opts ...grpc.CallOption) (*provider.SetLockResponse, error) { 250 return c.c.SetLock(ctx, in, opts...) 251 } 252 func (c *cachedAPIClient) GetLock(ctx context.Context, in *provider.GetLockRequest, opts ...grpc.CallOption) (*provider.GetLockResponse, error) { 253 return c.c.GetLock(ctx, in, opts...) 254 } 255 func (c *cachedAPIClient) RefreshLock(ctx context.Context, in *provider.RefreshLockRequest, opts ...grpc.CallOption) (*provider.RefreshLockResponse, error) { 256 return c.c.RefreshLock(ctx, in, opts...) 257 } 258 func (c *cachedAPIClient) Unlock(ctx context.Context, in *provider.UnlockRequest, opts ...grpc.CallOption) (*provider.UnlockResponse, error) { 259 return c.c.Unlock(ctx, in, opts...) 260 } 261 func (c *cachedAPIClient) GetHome(ctx context.Context, in *provider.GetHomeRequest, opts ...grpc.CallOption) (*provider.GetHomeResponse, error) { 262 return c.c.GetHome(ctx, in, opts...) 263 } 264 func (c *cachedAPIClient) TouchFile(ctx context.Context, in *provider.TouchFileRequest, opts ...grpc.CallOption) (*provider.TouchFileResponse, error) { 265 return c.c.TouchFile(ctx, in, opts...) 266 }