# Path: oioswift/common/middleware/versioned_writes.py
# DELETE_MARKER_CONTENT_TYPE = vw.DELETE_MARKER_CONTENT_TYPE
# 
# Path: oioswift/utils.py
# def check_if_none_match(fnc):
#     """Check if object exists, and if etag matches."""
#     @wraps(fnc)
#     def _if_none_match_wrapper(self, req, *args, **kwargs):
#         if req.if_none_match is None:
#             return fnc(self, req, *args, **kwargs)
#         oio_headers = {REQID_HEADER: self.trans_id}
#         try:
#             metadata = self.app.storage.object_get_properties(
#                 self.account_name, self.container_name, self.object_name,
#                 version=req.environ.get('oio.query', {}).get('version'),
#                 headers=oio_headers)
#         except (NoSuchObject, NoSuchContainer):
#             return fnc(self, req, *args, **kwargs)
#         # req.if_none_match will check for '*'.
#         if metadata.get('hash') in req.if_none_match:
#             if req.method in ('HEAD', 'GET'):
#                 raise HTTPNotModified(request=req)
#             else:
#                 raise HTTPPreconditionFailed(request=req)
#         return fnc(self, req, *args, **kwargs)
#     return _if_none_match_wrapper
# 
# def handle_not_allowed(fnc):
#     """Handle MethodNotAllowed ('405 Method not allowed') errors."""
#     @wraps(fnc)
#     def _not_allowed_wrapper(self, req, *args, **kwargs):
#         try:
#             return fnc(self, req, *args, **kwargs)
#         except MethodNotAllowed as exc:
#             headers = dict()
#             if 'worm' in exc.message.lower():
#                 headers['Allow'] = 'GET, HEAD, PUT'
#             else:
#                 # TODO(FVE): load Allow header from exception attributes
#                 pass
#             return HTTPMethodNotAllowed(request=req, headers=headers)
#     return _not_allowed_wrapper
# 
# def handle_oio_timeout(fnc):
#     """
#     Catch DeadlineReached and OioTimeout errors
#     and return '503 Service Unavailable'.
#     """
#     @wraps(fnc)
#     def _oio_timeout_wrapper(self, req, *args, **kwargs):
#         try:
#             return fnc(self, req, *args, **kwargs)
#         except (DeadlineReached, OioTimeout) as exc:
#             headers = dict()
#             # TODO(FVE): choose the value according to the timeout
#             headers['Retry-After'] = '1'
#             return HTTPServiceUnavailable(request=req, headers=headers,
#                                           body=str(exc))
#     return _oio_timeout_wrapper
# 
# def handle_service_busy(fnc):
#     @wraps(fnc)
#     def _service_busy_wrapper(self, req, *args, **kwargs):
#         try:
#             return fnc(self, req, *args, **kwargs)
#         except (ServiceBusy, ServiceUnavailable) as err:
#             headers = dict()
#             headers['Retry-After'] = '1'
#             return HTTPServiceUnavailable(request=req, headers=headers,
#                                           body=err.message)
#     return _service_busy_wrapper
# 
# REQID_HEADER = 'x-oio-req-id'
# 
# BUCKET_NAME_PROP = "sys.m2.bucket.name"
# 
# MULTIUPLOAD_SUFFIX = '+segments'


import json
import mimetypes
import time
import math
from swift import gettext_ as _
from swift.common.utils import (
    clean_content_type, config_true_value, Timestamp, public,
    close_if_possible, closing_if_possible)
from swift.common.constraints import check_metadata, check_object_creation
from swift.common.header_key_dict import HeaderKeyDict
from oioswift.common.middleware.versioned_writes import \
    DELETE_MARKER_CONTENT_TYPE
from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPNotFound, \
    HTTPConflict, HTTPPreconditionFailed, HTTPRequestTimeout, \
    HTTPUnprocessableEntity, HTTPClientDisconnect, HTTPCreated, \
    HTTPNoContent, Response, HTTPInternalServerError, multi_range_iterator, \
    HTTPServiceUnavailable
from swift.common.request_helpers import is_sys_or_user_meta, \
    is_object_transient_sysmeta, resolve_etag_is_at_header
from swift.common.wsgi import make_subrequest
from swift.proxy.controllers.base import set_object_info_cache, \
        delay_denial, cors_validation, get_object_info
from swift.proxy.controllers.obj import check_content_type
from swift.proxy.controllers.obj import BaseObjectController as \
        BaseObjectController
from oio.common import exceptions
    from oio.common.constants import FORCEVERSIONING_HEADER
from oio.common.http import ranges_from_http_header
from oio.common.storage_method import STORAGE_METHODS
from oio.api.object_storage import _sort_chunks
from oio.common.exceptions import SourceReadTimeout
from oioswift.utils import check_if_none_match, \
    handle_not_allowed, handle_oio_timeout, handle_service_busy, \
    REQID_HEADER, BUCKET_NAME_PROP, MULTIUPLOAD_SUFFIX
        Enforce the versioning mode of a container just before executing
        an object operation. This is useful when the current object is not
        stored in the "main" container but in a shard, where the versioning
        mode may not have been set yet.
        """
        if not SUPPORT_VERSIONING:
            return None

        # There is no reason to save several versions of segments:
        # a new version of a multipart object manifest will point to a
        # completely different set of segments, with another uploadId.
        root_container = req.headers.get(BUCKET_NAME_HEADER)
        if (root_container is None or
                root_container.endswith(MULTIUPLOAD_SUFFIX)):
            return None

        # We can't use _get_info_from_caches as it would use local worker cache
        # first and an update of versioning mode may not be detected.
        memcache = getattr(self.app, 'memcache', None) or \
            req.environ.get('swift.cache')
        if memcache is None:
            return None

        key = "/".join(("versioning", self.account_name, root_container))
        val = memcache.get(key)
        if val is not None:
            if val != '':
                req.headers[FORCEVERSIONING_HEADER] = val
            return


# Path: oioswift/common/middleware/versioned_writes.py
# DELETE_MARKER_CONTENT_TYPE = vw.DELETE_MARKER_CONTENT_TYPE
# 
# Path: oioswift/utils.py
# def check_if_none_match(fnc):
#     """Check if object exists, and if etag matches."""
#     @wraps(fnc)
#     def _if_none_match_wrapper(self, req, *args, **kwargs):
#         if req.if_none_match is None:
#             return fnc(self, req, *args, **kwargs)
#         oio_headers = {REQID_HEADER: self.trans_id}
#         try:
#             metadata = self.app.storage.object_get_properties(
#                 self.account_name, self.container_name, self.object_name,
#                 version=req.environ.get('oio.query', {}).get('version'),
#                 headers=oio_headers)
#         except (NoSuchObject, NoSuchContainer):
#             return fnc(self, req, *args, **kwargs)
#         # req.if_none_match will check for '*'.
#         if metadata.get('hash') in req.if_none_match:
#             if req.method in ('HEAD', 'GET'):
#                 raise HTTPNotModified(request=req)
#             else:
#                 raise HTTPPreconditionFailed(request=req)
#         return fnc(self, req, *args, **kwargs)
#     return _if_none_match_wrapper
# 
# def handle_not_allowed(fnc):
#     """Handle MethodNotAllowed ('405 Method not allowed') errors."""
#     @wraps(fnc)
#     def _not_allowed_wrapper(self, req, *args, **kwargs):
#         try:
#             return fnc(self, req, *args, **kwargs)
#         except MethodNotAllowed as exc:
#             headers = dict()
#             if 'worm' in exc.message.lower():
#                 headers['Allow'] = 'GET, HEAD, PUT'
#             else:
#                 # TODO(FVE): load Allow header from exception attributes
#                 pass
#             return HTTPMethodNotAllowed(request=req, headers=headers)
#     return _not_allowed_wrapper
# 
# def handle_oio_timeout(fnc):
#     """
#     Catch DeadlineReached and OioTimeout errors
#     and return '503 Service Unavailable'.
#     """
#     @wraps(fnc)
#     def _oio_timeout_wrapper(self, req, *args, **kwargs):
#         try:
#             return fnc(self, req, *args, **kwargs)
#         except (DeadlineReached, OioTimeout) as exc:
#             headers = dict()
#             # TODO(FVE): choose the value according to the timeout
#             headers['Retry-After'] = '1'
#             return HTTPServiceUnavailable(request=req, headers=headers,
#                                           body=str(exc))
#     return _oio_timeout_wrapper
# 
# def handle_service_busy(fnc):
#     @wraps(fnc)
#     def _service_busy_wrapper(self, req, *args, **kwargs):
#         try:
#             return fnc(self, req, *args, **kwargs)
#         except (ServiceBusy, ServiceUnavailable) as err:
#             headers = dict()
#             headers['Retry-After'] = '1'
#             return HTTPServiceUnavailable(request=req, headers=headers,
#                                           body=err.message)
#     return _service_busy_wrapper
# 
# REQID_HEADER = 'x-oio-req-id'
# 
# BUCKET_NAME_PROP = "sys.m2.bucket.name"
# 
# MULTIUPLOAD_SUFFIX = '+segments'


# Path: oioswift/proxy/controllers/obj.py
import json
import mimetypes
import time
import math
from swift import gettext_ as _
from swift.common.utils import (
    clean_content_type, config_true_value, Timestamp, public,
    close_if_possible, closing_if_possible)
from swift.common.constraints import check_metadata, check_object_creation
from swift.common.header_key_dict import HeaderKeyDict
from oioswift.common.middleware.versioned_writes import \
    DELETE_MARKER_CONTENT_TYPE
from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPNotFound, \
    HTTPConflict, HTTPPreconditionFailed, HTTPRequestTimeout, \
    HTTPUnprocessableEntity, HTTPClientDisconnect, HTTPCreated, \
    HTTPNoContent, Response, HTTPInternalServerError, multi_range_iterator, \
    HTTPServiceUnavailable
from swift.common.request_helpers import is_sys_or_user_meta, \
    is_object_transient_sysmeta, resolve_etag_is_at_header
from swift.common.wsgi import make_subrequest
from swift.proxy.controllers.base import set_object_info_cache, \
        delay_denial, cors_validation, get_object_info
from swift.proxy.controllers.obj import check_content_type
from swift.proxy.controllers.obj import BaseObjectController as \
        BaseObjectController
from oio.common import exceptions
    from oio.common.constants import FORCEVERSIONING_HEADER
from oio.common.http import ranges_from_http_header
from oio.common.storage_method import STORAGE_METHODS
from oio.api.object_storage import _sort_chunks
from oio.common.exceptions import SourceReadTimeout
from oioswift.utils import check_if_none_match, \
    handle_not_allowed, handle_oio_timeout, handle_service_busy, \
    REQID_HEADER, BUCKET_NAME_PROP, MULTIUPLOAD_SUFFIX

        Enforce the versioning mode of a container just before executing
        an object operation. This is useful when the current object is not
        stored in the "main" container but in a shard, where the versioning
        mode may not have been set yet.
        """
        if not SUPPORT_VERSIONING:
            return None

        # There is no reason to save several versions of segments:
        # a new version of a multipart object manifest will point to a
        # completely different set of segments, with another uploadId.
        root_container = req.headers.get(BUCKET_NAME_HEADER)
        if (root_container is None or
                root_container.endswith(MULTIUPLOAD_SUFFIX)):
            return None

        # We can't use _get_info_from_caches as it would use local worker cache
        # first and an update of versioning mode may not be detected.
        memcache = getattr(self.app, 'memcache', None) or \
            req.environ.get('swift.cache')
        if memcache is None:
            return None

        key = "/".join(("versioning", self.account_name, root_container))
        val = memcache.get(key)
        if val is not None:
            if val != '':
                req.headers[FORCEVERSIONING_HEADER] = val
            return


        oio_headers = {REQID_HEADER: self.trans_id}