@@ -213,20 +213,68 @@ def enforce_versioning(self, req):
213213
214214 # We can't use _get_info_from_caches as it would use local worker cache
215215 # 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 :
219258 return None
259+ if root_container .endswith (MULTIUPLOAD_SUFFIX ):
260+ root_container = root_container [:- len (MULTIUPLOAD_SUFFIX )]
220261
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
227276
228277 oio_headers = {REQID_HEADER : self .trans_id }
229- oio_cache = req .environ .get ('oio.cache' )
230278 perfdata = req .environ .get ('oio.perfdata' )
231279 try :
232280 meta = self .app .storage .container_get_properties (
@@ -235,10 +283,10 @@ def enforce_versioning(self, req):
235283 except exceptions .NoSuchContainer :
236284 raise HTTPNotFound (request = req )
237285
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
242290
243291 def get_object_head_resp (self , req ):
244292 storage = self .app .storage
@@ -647,15 +695,15 @@ def _object_create(self, account, container, **kwargs):
647695 def _store_object (self , req , data_source , headers ):
648696 content_type = req .headers .get ('content-type' , 'octet/stream' )
649697 policy = None
650- container_info = self .container_info (self .account_name ,
651- self .container_name , req )
652698 if 'X-Oio-Storage-Policy' in req .headers :
653699 policy = req .headers .get ('X-Oio-Storage-Policy' )
654700 if not self .app .POLICIES .get_by_name (policy ):
655701 raise HTTPBadRequest (
656702 "invalid policy '%s', must be in %s" %
657703 (policy , self .app .POLICIES .by_name .keys ()))
658704 else :
705+ container_info = self .container_info (self .account_name ,
706+ self .container_name , req )
659707 try :
660708 policy_index = int (
661709 req .headers .get ('X-Backend-Storage-Policy-Index' ,
@@ -665,6 +713,8 @@ def _store_object(self, req, data_source, headers):
665713 if policy_index != 0 :
666714 policy = self .app .POLICIES .get_by_index (policy_index ).name
667715 else :
716+ policy = self .use_bucket_storage_policy (req )
717+ if policy is None :
668718 content_length = int (req .headers .get ('content-length' , 0 ))
669719 policy = self ._get_auto_policy_from_size (content_length )
670720
0 commit comments