Created
March 22, 2014 01:01
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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