@@ -213,20 +213,68 @@ def enforce_versioning(self, req):
213
213
214
214
# We can't use _get_info_from_caches as it would use local worker cache
215
215
# first and an update of versioning mode may not be detected.
216
- memcache = getattr (self .app , 'memcache' , None ) or \
217
- req .environ .get ('swift.cache' )
218
- if memcache is None :
216
+ oio_cache = req .environ .get ('oio.cache' )
217
+ memcache = None
218
+ if oio_cache is None :
219
+ memcache = getattr (self .app , 'memcache' , None ) or \
220
+ req .environ .get ('swift.cache' )
221
+
222
+ if memcache is not None :
223
+ memcache_key = "/" .join (
224
+ ("versioning" , self .account_name , root_container ))
225
+ version_policy = memcache .get (memcache_key )
226
+ if version_policy is not None :
227
+ if version_policy :
228
+ req .headers [FORCEVERSIONING_HEADER ] = version_policy
229
+ return
230
+
231
+ oio_headers = {REQID_HEADER : self .trans_id }
232
+ perfdata = req .environ .get ('oio.perfdata' )
233
+ try :
234
+ meta = self .app .storage .container_get_properties (
235
+ self .account_name , root_container , headers = oio_headers ,
236
+ cache = oio_cache , perfdata = perfdata )
237
+ except exceptions .NoSuchContainer :
238
+ raise HTTPNotFound (request = req )
239
+
240
+ version_policy = meta ['system' ].get ('sys.m2.policy.version' )
241
+ if memcache is not None :
242
+ memcache .set (memcache_key , version_policy or '' )
243
+ if version_policy :
244
+ req .headers [FORCEVERSIONING_HEADER ] = version_policy
245
+
246
+ def use_bucket_storage_policy (self , req ):
247
+ """
248
+ Enforce the storage policy mode of a container just before executing
249
+ an object operation. This is useful when the current object is not
250
+ stored in the "main" container but in a shard,
251
+ where the storage policy mode may not have been set yet.
252
+ """
253
+ if not self .app .use_bucket_storage_policy :
254
+ return None
255
+
256
+ root_container = req .headers .get (BUCKET_NAME_HEADER )
257
+ if root_container is None :
219
258
return None
259
+ if root_container .endswith (MULTIUPLOAD_SUFFIX ):
260
+ root_container = root_container [:- len (MULTIUPLOAD_SUFFIX )]
220
261
221
- key = "/" .join (("versioning" , self .account_name , root_container ))
222
- val = memcache .get (key )
223
- if val is not None :
224
- if val != '' :
225
- req .headers [FORCEVERSIONING_HEADER ] = val
226
- return
262
+ # We can't use _get_info_from_caches as it would use local worker cache
263
+ # first and an update of storage policy mode may not be detected.
264
+ oio_cache = req .environ .get ('oio.cache' )
265
+ memcache = None
266
+ if oio_cache is None :
267
+ memcache = getattr (self .app , 'memcache' , None ) or \
268
+ req .environ .get ('swift.cache' )
269
+
270
+ if memcache is not None :
271
+ memcache_key = "/" .join (
272
+ ("storage_policy" , self .account_name , root_container ))
273
+ storage_policy = memcache .get (memcache_key )
274
+ if storage_policy is not None :
275
+ return storage_policy or None
227
276
228
277
oio_headers = {REQID_HEADER : self .trans_id }
229
- oio_cache = req .environ .get ('oio.cache' )
230
278
perfdata = req .environ .get ('oio.perfdata' )
231
279
try :
232
280
meta = self .app .storage .container_get_properties (
@@ -235,10 +283,10 @@ def enforce_versioning(self, req):
235
283
except exceptions .NoSuchContainer :
236
284
raise HTTPNotFound (request = req )
237
285
238
- val = meta ['system' ].get ('sys.m2.policy.version' , ' ' )
239
- memcache . set ( key , val )
240
- if val :
241
- req . headers [ FORCEVERSIONING_HEADER ] = val
286
+ storage_policy = meta ['system' ].get ('sys.m2.policy.storage ' )
287
+ if memcache is not None :
288
+ memcache . set ( memcache_key , storage_policy or '' )
289
+ return storage_policy
242
290
243
291
def get_object_head_resp (self , req ):
244
292
storage = self .app .storage
@@ -647,15 +695,15 @@ def _object_create(self, account, container, **kwargs):
647
695
def _store_object (self , req , data_source , headers ):
648
696
content_type = req .headers .get ('content-type' , 'octet/stream' )
649
697
policy = None
650
- container_info = self .container_info (self .account_name ,
651
- self .container_name , req )
652
698
if 'X-Oio-Storage-Policy' in req .headers :
653
699
policy = req .headers .get ('X-Oio-Storage-Policy' )
654
700
if not self .app .POLICIES .get_by_name (policy ):
655
701
raise HTTPBadRequest (
656
702
"invalid policy '%s', must be in %s" %
657
703
(policy , self .app .POLICIES .by_name .keys ()))
658
704
else :
705
+ container_info = self .container_info (self .account_name ,
706
+ self .container_name , req )
659
707
try :
660
708
policy_index = int (
661
709
req .headers .get ('X-Backend-Storage-Policy-Index' ,
@@ -665,6 +713,8 @@ def _store_object(self, req, data_source, headers):
665
713
if policy_index != 0 :
666
714
policy = self .app .POLICIES .get_by_index (policy_index ).name
667
715
else :
716
+ policy = self .use_bucket_storage_policy (req )
717
+ if policy is None :
668
718
content_length = int (req .headers .get ('content-length' , 0 ))
669
719
policy = self ._get_auto_policy_from_size (content_length )
670
720
0 commit comments