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