Skip to content

Instantly share code, notes, and snippets.

@zaitcev
Created March 22, 2014 01:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zaitcev/9699561 to your computer and use it in GitHub Desktop.
Save zaitcev/9699561 to your computer and use it in GitHub Desktop.
Semantic diff for PBE from the standpoint of Broker/Backend API in the servers
Semanic diff for https://review.openstack.org/47713
Use 142 columns
Use '*' in vi to highlight broker
## Account (HEAD) ## Account (PBE)
class AccountController(object): class AccountController(object):
def HEAD(self, req): def HEAD(self, req):
broker = self._get_account_broker(drive, part, account, ...) broker = self.get_account_backend(drive, part, account,...)
if broker.is_deleted():
return self._deleted_response(broker, req, HTTPNotFound) try:
info = broker.get_info() info = broker.get_info()
except AccountDeleted as err:
if err.marked:
headers = {'X-Account-Status': 'Deleted'}
else:
headers = {}
return HTTPNotFound(request=req, headers=headers, ...)
[for key, (value, timestamp) in broker.metadata.iteritems()] [for key, (value, timestamp) in info['metadata'].iteritems()]
def GET(self, req): def GET(self, req):
broker = self._get_account_broker(drive, part, account, ...) broker = self.get_account_backend(drive, part, account,
if broker.is_deleted():
return self._deleted_response(broker, req, HTTPNotFound)
return account_listing_response(account,req,o_c_t, broker, ..) return account_listing_response(account, req, o_c_t, broker,..)
def PUT(self, req): def PUT(self, req):
broker = self.get_account_backend(drive, part, account, ...)
if not broker:
return HTTPInsufficientStorage(drive=drive, request=req)
if container: # put account container if container:
broker = self._get_account_broker(drive, part, account,..)
if account.startswith(self.auto_create_account_prefix) \ a_c = account.startswith(self.auto_create_account_prefix)
and not os.path.exists(broker.db_file):
try:
broker.initialize(timestamp)
except DatabaseAlreadyExists:
pass
ovd = req.headers['x-account-override-deleted'] ovd = req.headers['x-account-override-deleted']
if ovd !~= 'yes' and broker.is_deleted(): try:
return HTTPNotFound(request=req) ret = broker.put_container(container, .., a_c, ovd)
broker.put_container(container, req.headers['x-xxxxx'],..) except EntityNotExist:
if req.headers['x-delete-timestamp'] > \ resp = HTTPNotFound
req.headers['x-put-timestamp']: else:
return HTTPNoContent(request=req) if ret:
else: resp = HTTPCreated
return HTTPCreated(request=req) else:
resp = HTTPNoContent
return resp(request=req)
else: # put account else: # put account
broker = self._get_account_broker(drive, part, account)
if not os.path.exists(broker.db_file): # atomic, see c/81104
try: try:
broker.initialize(timestamp) state = broker.create(timestamp, metadata)
created = True
except DatabaseAlreadyExists:
created = False
elif broker.is_status_deleted(): except EntityNotExist:
return self._deleted_response(broker,req,HTTPForbidden) headers = {'X-Account-Status': 'Deleted'}
resp = HTTPForbidden(request=req, headers=headers,...)
else:
created = broker.is_deleted()
broker.update_put_timestamp(timestamp)
if broker.is_deleted():
return HTTPConflict(request=req) except EntityConflict:
if metadata: resp = HTTPConflict(request=req)
broker.update_metadata(metadata..(req, timestamp)) else:
if created: if state:
return HTTPCreated(request=req) resp = HTTPCreated(request=req)
else: else:
return HTTPAccepted(request=req) resp = HTTPAccepted(request=req)
return resp
def POST(self, req): def POST(self, req):
broker = self._get_account_broker(drive, part, account) broker = self.get_account_backend(drive, part, account)
if broker.is_deleted():
return self._deleted_response(broker, req, HTTPNotFound)
if metadata: try:
broker.update_metadata(metadata..(req, timestamp)) broker.update_metadata(metadata..(req, timestamp))
except AccountDeleted as err:
if err.marked:
headers = {'X-Account-Status': 'Deleted'}
else:
headers = {}
return HTTPNotFound(request=req, headers=headers, ...)
return HTTPNoContent(request=req) return HTTPNoContent(request=req)
def DELETE(self, req): def DELETE(self, req):
broker = self._get_account_broker(drive, part, account) broker = self.get_account_backend(drive, part, account)
if broker.is_deleted():
return self._deleted_response(broker, req, HTTPNotFound) try:
broker.delete_db(req.headers['x-timestamp']) existed = broker.delete(req.headers['x-timestamp'])
return self._deleted_response(broker, req, HTTPNoContent) except EntityConflict:
resp = HTTPNotFound
headers = {}
else:
if existed:
resp = HTTPNoContent
else:
resp = HTTPNotFound
headers = {'X-Account-Status': 'Deleted'}
return resp(request=req, headers=headers, ...)
@replication
def REPLICATE(self, req):
def _deleted_response(self, broker, req, resp, body=''): # unrolled back in PBE
headers = {}
try:
if broker.is_status_deleted():
headers = {'X-Account-Status': 'Deleted'}
except DatabaseConnectionError:
pass
return resp(request=req, headers=headers, ...)
def _get_account_broker(self, drive, part, a, **kwargs): def get_account_backend(self, drive, part, a, **kwargs):
hsh = hash_path(a)
db_dir = storage_directory(DATADIR, part, hsh)
db_path = os.path.join(self.root, drive, db_dir, hsh + '.db')
kwargs.setdefault('account', a)
kwargs.setdefault('logger', self.logger) kwargs.setdefault('logger', self.logger)
return AccountBroker(db_path, **kwargs) return AccountBackend(self.root, drive, part, a, **kwargs)
# account_listing_response is also used by in proxy's account controller to report just-autocreated accounts
def account_listing_response(account, req, r_c_t, broker=None, ...) def account_listing_response(account, req, r_c_t, broker=None, ...)
if broker is None: if broker is None:
broker = FakeAccountBroker() broker = FakeAccountBroker()
info = broker.get_info() info = broker.get_info()
[for key, (value, timestamp) in broker.metadata.iteritems()] [for key, (value, timestamp) in info['metadata'].iteritems()]
account_list = broker.list_containers_iter(limit, marker, ...) account_list = broker.list_containers_iter(limit, marker, ...)
# using account_list # using account_list
class AccountBroker(DatabaseBroker): class AccountBackend(AccountBroker):
## Full listing of methods and properties used by server: ## Full listing of methods and properties used by server:
# is_deleted
# get_info # get_info
# metadata -- @property
# db_file -- instance variable property
# initialize -- inherited from DatabaseBroker # create
# re-calls _initialize ->
# create_container_table(conn)
# create_account_stat_table(conn, put_timestamp)
# throws DatabaseAlreadyExists, ValueError
# put_container # put_container
# is_status_deleted
# update_put_timestamp -- inherited from DatabaseBroker
# update_metadata -- inherited from DatabaseBroker # update_metadata
# delete_db -- inherited from DatabaseBroker # delete
# re-calls _delete_db
# list_containers_iter # list_containers_iter
## Container (HEAD) ## Container (PBE)
class ContainerController(object): class ContainerController(object):
def HEAD(self, req): def HEAD(self, req):
broker = self._get_container_broker(dr, pt, a, c, ...) broker = self.get_container_backend(drive, part, a, c, ...)
if broker.is_deleted():
return HTTPNotFound(request=req)
info = broker.get_info() info = broker.get_info()
if not info:
return HTTPNotFound(request=req)
[for key, (value, timestamp) in broker.metadata.iteritems()] [for key, (value, timestamp) in info['metadata'].iteritems()]
return HTTPNoContent(request=req, headers=headers, ...) return HTTPNoContent(request=req, headers=headers, ...)
def GET(self, req): def GET(self, req):
broker = self._get_container_broker(dr, pt, a, c, ...) broker = self.get_container_backend(drive, part, a, c, ...)
if broker.is_deleted():
return HTTPNotFound(request=req)
info = broker.get_info() info = broker.get_info()
if not info:
return HTTPNotFound(request=req)
[for key, (value, timestamp) in broker.metadata.iteritems()] [for key, (value, timestamp) in info['metadata'].iteritems()]
container_list = broker.list_objects_iter(....) container_list = broker.list_objects_iter(...)
ret.body = '\n'.join(rec[0] for rec in container_list) + '\n' ret.body = '\n'.join(rec[0] for rec in container_list) + '\n'
def PUT(self, req): def PUT(self, req):
broker = self._get_container_broker(dr, pt, a, c, ...) broker = self.get_container_backend(dr, pt, a, c)
if obj: # put container object if obj: # put container object
if account.startswith(self.auto_create_account_prefix) \ a_c = account.startswith(self.auto_create_account_prefix)
and not os.path.exists(broker.db_file):
try:
broker.initialize(timestamp)
except DatabaseAlreadyExists:
pass
if not os.path.exists(broker.db_file):
return HTTPNotFound() try:
broker.put_object(obj, timestamp, ...) broker.put_object(obj, timestamp, ..., a_c)
except EntityNotInitialized:
return HTTPNotFound(request=req)
return HTTPCreated(request=req) return HTTPCreated(request=req)
else: # put container else: # put container
if not os.path.exists(broker.db_file):
try:
broker.initialize(timestamp)
created = True
except DatabaseAlreadyExists:
created = False
else:
created = broker.is_deleted() try:
broker.update_put_timestamp(timestamp) created = broker.create(timestamp, metadata)
if broker.is_deleted(): except EntityConflict:
return HTTPConflict(request=req) return HTTPConflict(request=req)
if metadata(req):
if 'X-Container-Sync-To' in metadata:
if 'X-Container-Sync-To' not in broker.metadata or \
metadata['X-Container-Sync-To'][0] != \
broker.metadata['X-Container-Sync-To'][0]:
broker.set_x_container_sync_points(-1, -1)
broker.update_metadata(metadata)
resp = self.account_update(req, a, c, broker) resp = self.account_update(req, a, c, broker)
if resp: return resp if resp: return resp
if created: return HTTPCreated(request=req) if created: return HTTPCreated(request=req)
return HTTPAccepted(request=req) return HTTPAccepted(request=req)
def POST(self, req):
broker = self._get_container_broker(dr, pt, a, c, ...) broker = self.get_container_backend(dr, pt, a, c)
if broker.is_deleted():
return HTTPNotFound(request=req)
if metadata(req): try:
if 'X-Container-Sync-To' in metadata: broker.update_metadata(metadata)
if 'X-Container-Sync-To' not in broker.metadata or \ except EntityNotExist:
metadata['X-Container-Sync-To'][0] != \ return HTTPNotFound(request=req)
broker.metadata['X-Container-Sync-To'][0]:
broker.set_x_container_sync_points(-1, -1)
broker.update_metadata(metadata)
def DELETE(self, req): def DELETE(self, req):
broker = self._get_container_broker(dr, pt, a, c, ...) broker = self.get_container_backend(drive, part, a, c)
if a.startswith(self.auto_create_account_prefix) and obj and \
not os.path.exists(broker.db_file):
try:
broker.initialize(normalize_timestamp(
req.headers.get('x-timestamp') or time.time()))
except DatabaseAlreadyExists:
pass
if not os.path.exists(broker.db_file):
return HTTPNotFound()
if obj: # delete object if obj: # delete object
try:
broker.delete_object(obj, req.headers.get('x-timestamp')) broker.delete_object(obj, timestamp, auto_create)
except EntityNotInitialized:
return HTTPNotFound(request=req)
return HTTPNoContent(request=req) return HTTPNoContent(request=req)
else: else: # delete container
if not broker.empty():
return HTTPConflict(request=req) try:
existed = float(broker.get_info()['put_timestamp']) and \ existed = broker.delete(req.headers['x-timestamp'])
not broker.is_deleted() except EntityNotInitialized:
broker.delete_db(req.headers['X-Timestamp']) return HTTPNotFound()
if not broker.is_deleted(): except (EntityNotEmpty, EntityConflict):
return HTTPConflict(request=req) return HTTPConflict(request=req)
resp = self.account_update(req, a, c, broker) resp = self.account_update(req, a, c, broker)
if resp: return resp if resp: return resp
if existed: return HTTPNoContent(request=req) if existed: return HTTPNoContent(request=req)
return HTTPNotFound() return HTTPNotFound()
@replication
def REPLICATE(self, req):
def account_update(self, req, a, c, broker): def account_update(self, req, a, c, broker):
for account_host, account_device in updates(req): for account_host, account_device in updates(req):
info = broker.get_info() info = broker.get_info(ignore_deleted=True)
conn = http_connect(... , 'PUT') conn = http_connect(..., 'PUT'...)
def _get_container_broker(self, drive, part, a, c, **kwargs): def get_container_backend(self, drive, part, a, c, **kwargs):
hsh = hash_path(a, c)
db_dir = storage_directory(DATADIR, part, hsh)
db_path = os.path.join(self.root, drive, db_dir, hsh + '.db')
kwargs.setdefault('account', a)
kwargs.setdefault('container', c)
kwargs.setdefault('logger', self.logger) kwargs.setdefault('logger', self.logger)
return ContainerBroker(db_path, **kwargs) return ContainerBroker(self.root, drive, part, a, c, **kwargs)
class ContainerBroker(DatabaseBroker): class ContainerBackend(ContainerBroker):
## Full listing of methods and properties used by server: ## Full listing of methods and properties used by server:
# get_info # get_info
# db_file #
# initialize #
# delete_object # delete_object
# empty #
# delete_db # delete
# is_deleted #
# put_object # put_object
# update_put_timestamp # create
# metadata (@property) #
# set_x_container_sync_points #
# update_metadata # update_metadata
# list_objects_iter # list_objects_iter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment