分享

Swift源码分析----swift-proxy与swift-account

tntzbzc 发表于 2014-11-20 15:34:48 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 18537
问题导读
1. _get_account_broker功能是什么?
2./swift/proxy/controllers/account.py作用是什么?








概述:
    请求信息到达swift-proxy服务之后,会确定获取具体的控制器(ObjectController、ContainerController、AccountController),接下来就是调用/swift/proxy/controllers/account.py或/swift/proxy/controllers/container.py或/swift/proxy/controllers/obj.py下面的PUT,POST,DELETE,GET,HEAD等方法;然后再在具体的方法中实现到具体存储服务(Object-server、Container-server、Account-server)的连接,继而调用其下具体的PUT,POST,DELETE,GET,HEAD等方法来进行请求req的实现;
这篇博客主要关注swift-proxy与swift-account服务中PUT,POST,DELETE,GET,HEAD等方法的对应调用实现;

源码解析部分(代码中较重要的部分已经进行了相关的注释):

GETorHEAD

/swift/proxy/controllers/account.py----class AccountController(Controller)----def GETorHEAD

  1. def GETorHEAD(self, req):  
  2.     """
  3.     通过HTTP处理GET/HEAD请求;
  4.     """  
  5.     if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH:  
  6.         resp = HTTPBadRequest(request=req)  
  7.         resp.body = 'Account name length of %d longer than %d' % (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH)  
  8.         return resp  
  9.   
  10.     # get_nodes:为object获取分区号和所有副本节点信息;  
  11.     partition, nodes = self.app.account_ring.get_nodes(self.account_name)  
  12.          
  13.     # GETorHEAD_base:HTTP GET或HEAD的基本处理;  
  14.     # 返回swob.Response对象;  
  15.     resp = self.GETorHEAD_base(  
  16.         req, _('Account'), self.app.account_ring, partition,  
  17.         req.swift_entity_path.rstrip('/'))  
  18.          
  19.         if resp.status_int == HTTP_NOT_FOUND:  
  20.             if resp.headers.get('X-Account-Status', '').lower() == 'deleted':  
  21.                 resp.status = HTTP_GONE  
  22.             elif self.app.account_autocreate:  
  23.                 resp = account_listing_response(self.account_name, req,  
  24.                                                 get_listing_content_type(req))  
  25.         if req.environ.get('swift_owner'):  
  26.             self.add_acls_from_sys_metadata(resp)  
  27.         else:  
  28.             for header in self.app.swift_owner_headers:  
  29.                 resp.headers.pop(header, None)  
  30.         return resp  
复制代码



1.为object获取分区号和所有副本节点信息;
2.HTTP GET或HEAD的基本处理,实现发送请求到远程对象服务上并调用具体方法来处理请求信息;
  注:这里的具体实现就不详细解析了;


/swift/account/server.py----class AccountController(object)----def HEAD

  1. def HEAD(self, req):  
  2.     """
  3.     处理HTTP协议的HEAD请求;      
  4.     HEAD请求返回account的基本信息,并以key-value的形式保存在HTTPHEAD中返回;
  5.     """  
  6.     drive, part, account = split_and_validate_path(req, 3)  
  7.     out_content_type = get_listing_content_type(req)  
  8.          
  9.     # mount_check是是否进行mount检查;  
  10.     # 如果进行mount检查,并且检查结果没有挂载,则引发http 507错误,提示磁盘没有足够存储空间;  
  11.     if self.mount_check and not check_mount(self.root, drive):  
  12.         return HTTPInsufficientStorage(drive=drive, request=req)  
  13.          
  14.     # _get_account_broker是一个内部方法,功能是返回一个AccountBroker的实例,用于代理对sqlite数据库的操作;  
  15.     broker = self._get_account_broker(drive, part, account,  
  16.                                           pending_timeout=0.1,  
  17.                                           stale_reads_ok=True)  
  18.          
  19.     if broker.is_deleted():  
  20.         return self._deleted_response(broker, req, HTTPNotFound)  
  21.          
  22.     # get_info:为账户获取全局数据,获得account的基本信息;  
  23.     # 返回包括account, created_at, put_timestamp, delete_timestamp, container_count, object_count, bytes_used, hash, id等值的字典;  
  24.     info = broker.get_info()  
  25.     headers = {  
  26.             'X-Account-Container-Count': info['container_count'],  
  27.             'X-Account-Object-Count': info['object_count'],  
  28.             'X-Account-Bytes-Used': info['bytes_used'],  
  29.             'X-Timestamp': info['created_at'],  
  30.             'X-PUT-Timestamp': info['put_timestamp']}  
  31.     headers.update((key, value)  
  32.                    for key, (value, timestamp) in  
  33.                    broker.metadata.iteritems() if value != '')  
  34.     headers['Content-Type'] = out_content_type  
  35.          
  36.         return HTTPNoContent(request=req, headers=headers, charset='utf-8')  
复制代码




注:HEAD请求返回account的基本信息(元数据信息),并以key-value的形式保存在HTTPHEAD中返回;


/swift/account/server.py----class AccountController(object)----def GET


  1. def GET(self, req):  
  2.     """
  3.     处理HTTP协议的GET请求;
  4.     GET同HEAD一样,都是请求返回account的基本信息,并以key-value的形式保存在HTTPHEAD当中;
  5.     不同之处在于GET方法中获取了指定account下的container列表,存储在body中,同HTTPHEAD一同返回;
  6.     """  
  7.     drive, part, account = split_and_validate_path(req, 3)  
  8.     prefix = get_param(req, 'prefix')  
  9.     delimiter = get_param(req, 'delimiter')  
  10.     if delimiter and (len(delimiter) > 1 or ord(delimiter) > 254):  
  11.         # delimiters can be made more flexible later  
  12.         return HTTPPreconditionFailed(body='Bad delimiter')  
  13.     limit = ACCOUNT_LISTING_LIMIT  
  14.     given_limit = get_param(req, 'limit')  
  15.     if given_limit and given_limit.isdigit():  
  16.         limit = int(given_limit)  
  17.         if limit > ACCOUNT_LISTING_LIMIT:  
  18.             return HTTPPreconditionFailed(request=req, body='Maximum limit is %d' % ACCOUNT_LISTING_LIMIT)  
  19.     marker = get_param(req, 'marker', '')  
  20.     end_marker = get_param(req, 'end_marker')  
  21.     out_content_type = get_listing_content_type(req)  
  22.   
  23.     # mount_check是是否进行mount检查;  
  24.     # 如果进行mount检查,并且检查结果没有挂载,则引发http 507错误,提示磁盘没有足够存储空间;  
  25.     if self.mount_check and not check_mount(self.root, drive):  
  26.         return HTTPInsufficientStorage(drive=drive, request=req)  
  27.          
  28.     # _get_account_broker是一个内部方法,功能是返回一个AccountBroker的实例,用于代理对sqlite数据库的操作;  
  29.     broker = self._get_account_broker(drive, part, account,  
  30.                                           pending_timeout=0.1,  
  31.                                           stale_reads_ok=True)  
  32.          
  33.     if broker.is_deleted():  
  34.         return self._deleted_response(broker, req, HTTPNotFound)  
  35.          
  36.     # 获取指定account下的容器列表(包括具体容器的相关信息);  
  37.     return account_listing_response(account, req, out_content_type, broker,  
  38.                                     limit, marker, end_marker, prefix,  
  39.                                     delimiter)  
复制代码





来看方法account_listing_response的具体实现:

  1. def account_listing_response(account, req, response_content_type, broker=None,  
  2.                              limit='', marker='', end_marker='', prefix='',  
  3.                              delimiter=''):  
  4.     """
  5.     获取指定account下的容器列表(包括具体容器的相关信息);
  6.     """  
  7.     if broker is None:  
  8.         broker = FakeAccountBroker()  
  9.   
  10.     info = broker.get_info()  
  11.     resp_headers = {  
  12.         'X-Account-Container-Count': info['container_count'],  
  13.         'X-Account-Object-Count': info['object_count'],  
  14.         'X-Account-Bytes-Used': info['bytes_used'],  
  15.         'X-Timestamp': info['created_at'],  
  16.         'X-PUT-Timestamp': info['put_timestamp']}  
  17.     resp_headers.update((key, value)  
  18.                         for key, (value, timestamp) in  
  19.                         broker.metadata.iteritems() if value != '')  
  20.   
  21.     # 获取容器列表,每个容器信息包括(name, object_count, bytes_used, 0);  
  22.     account_list = broker.list_containers_iter(limit, marker, end_marker,  
  23.                                                prefix, delimiter)  
  24.     if response_content_type == 'application/json':  
  25.         data = []  
  26.         for (name, object_count, bytes_used, is_subdir) in account_list:  
  27.             if is_subdir:  
  28.                 data.append({'subdir': name})  
  29.             else:  
  30.                 data.append({'name': name, 'count': object_count,  
  31.                              'bytes': bytes_used})  
  32.         account_list = json.dumps(data)  
  33.     elif response_content_type.endswith('/xml'):  
  34.         output_list = ['<?xml version="1.0" encoding="UTF-8"?>',  
  35.                        '<account name=%s>' % saxutils.quoteattr(account)]  
  36.         for (name, object_count, bytes_used, is_subdir) in account_list:  
  37.             if is_subdir:  
  38.                 output_list.append(  
  39.                     '<subdir name=%s />' % saxutils.quoteattr(name))  
  40.             else:  
  41.                 item = '<container><name>%s</name><count>%s</count>' \  
  42.                        '<bytes>%s</bytes></container>' % \  
  43.                        (saxutils.escape(name), object_count, bytes_used)  
  44.                 output_list.append(item)  
  45.         output_list.append('</account>')  
  46.         account_list = '\n'.join(output_list)  
  47.     else:  
  48.         if not account_list:  
  49.             resp = HTTPNoContent(request=req, headers=resp_headers)  
  50.             resp.content_type = response_content_type  
  51.             resp.charset = 'utf-8'  
  52.             return resp  
  53.         account_list = '\n'.join(r[0] for r in account_list) + '\n'  
  54.     ret = HTTPOk(body=account_list, request=req, headers=resp_headers)  
  55.     ret.content_type = response_content_type  
  56.     ret.charset = 'utf-8'  
  57.     return ret  
复制代码



下面将继续swift-proxy与swift-account的分析工作。




PUT

/swift/proxy/controllers/account.py----class AccountController(Controller)----def PUT

  1. def PUT(self, req):
  2. """HTTP PUT request handler."""
  3.     if not self.app.allow_account_management:
  4.         return HTTPMethodNotAllowed(
  5.             request=req,
  6.             headers={'Allow': ', '.join(self.allowed_methods)})
  7.     error_response = check_metadata(req, 'account')
  8.     if error_response:
  9.         return error_response
  10.     if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH:
  11.         resp = HTTPBadRequest(request=req)
  12.         resp.body = 'Account name length of %d longer than %d' % \
  13.                         (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH)
  14.         return resp
  15.         
  16.         
  17.     # 获取指定account的分区号和所有副本节点;
  18.     account_partition, accounts = \
  19.             self.app.account_ring.get_nodes(self.account_name)
  20.     # 根据原始请求和额外的头信息,为后端的请求生成头信息字典;
  21.     headers = self.generate_request_headers(req, transfer=True)
  22.     clear_info_cache(self.app, req.environ, self.account_name)
  23.     resp = self.make_requests(
  24.             req, self.app.account_ring, account_partition, 'PUT',
  25.             req.swift_entity_path, [headers] * len(accounts))
  26.         
  27.     self.add_acls_from_sys_metadata(resp)
  28.     return resp
复制代码



这里代码比较好理解,这里来看以下方法make_requests的实现,这个方法是比较重要的:

  1. def make_requests(self, req, ring, part, method, path, headers, query_string=''):  
  2.     """
  3.     发送一个HTTP请求到多个节点,并汇聚所有返回的响应信息;
  4.     根据投票机制,根据现实所有响应信息,返回通过投票机制的响应信息(因为是获取多个节点的响应信息);
  5.          
  6.     调用示例:
  7.     resp = self.make_requests(
  8.         req, self.app.account_ring, account_partition, 'PUT',
  9.         req.path_info, [headers] * len(accounts))
  10.     """  
  11.     # get_part_nodes:获取一个分区所有副本相关的节点信息;  
  12.     start_nodes = ring.get_part_nodes(part)  
  13.     nodes = GreenthreadSafeIterator(self.app.iter_nodes(ring, part))  
  14.     pile = GreenAsyncPile(len(start_nodes))  
  15.          
  16.     for head in headers:   
  17.         # _make_request:发送请求迭代器,实现一次发送请求到一个远程节点;  
  18.         pile.spawn(self._make_request, nodes, part, method, path,  
  19.                    head, query_string, self.app.logger.thread_locals)  
  20.     response = []  
  21.     statuses = []  
  22.     for resp in pile:  
  23.         if not resp:  
  24.             continue  
  25.         response.append(resp)  
  26.         statuses.append(resp[0])  
  27.         if self.have_quorum(statuses, len(start_nodes)):  
  28.             break  
  29.     # give any pending requests *some* chance to finish  
  30.     pile.waitall(self.app.post_quorum_timeout)  
  31.     while len(response) < len(start_nodes):  
  32.         response.append((HTTP_SERVICE_UNAVAILABLE, '', '', ''))  
  33.     statuses, reasons, resp_headers, bodies = zip(*response)  
  34.          
  35.     # 根据投票机制,根据现实所有响应信息,实现返回通过投票机制的响应信息(因为是获取多个节点的响应信息);  
  36.     return self.best_response(req, statuses, reasons, bodies,  
  37.                               '%s %s' % (self.server_type, req.method),  
  38.                               headers=resp_headers)  
复制代码



具体的解释代码注释中已经标注了,也是比较好理解的,再来看一下这里方法best_response的具体实现:

  1. def best_response(self, req, statuses, reasons, bodies, server_type, etag=None, headers=None):
  2.      """
  3.      从一些服务器给定响应的列表,根据投票机制,根据现实所有响应信息,实现返回通过投票机制的响应信息;
  4.      """
  5.     # Response:WSGI相应对象类;
  6.     resp = Response(request=req)
  7.     if len(statuses):
  8.         for hundred in (HTTP_OK, HTTP_MULTIPLE_CHOICES, HTTP_BAD_REQUEST):
  9.             hstatuses = [s for s in statuses if hundred = quorum_size(len(statuses)):
  10.                 status = max(hstatuses)
  11.                 status_index = statuses.index(status)
  12.                 resp.status = '%s %s' % (status, reasons[status_index])
  13.                 resp.body = bodies[status_index]
  14.                 if headers:
  15.                     update_headers(resp, headers[status_index])
  16.                 if etag:
  17.                     resp.headers['etag'] = etag.strip('"')
  18.                 return resp
  19.     self.app.logger.error(_('%(type)s returning 503 for %(statuses)s'),
  20.                           {'type': server_type, 'statuses': statuses})
  21.     resp.status = '503 Internal Server Error'
  22.     return resp
复制代码






/swift/account/server.py----class AccountController(object)----def PUT



  1. def PUT(self, req):
  2. """
  3. 处理HTTP协议PUT请求;      
  4. PUT请求会handle两种类型的HTTP请求:
  5. 当url中有时,会新建/更新container的metadata信息;
  6. 当url中没有时,会更新account的metadata信息;
  7. """
  8.     # 分割和验证给定的请求路径,获取drive, part, account, container;
  9.     drive, part, account, container = split_and_validate_path(req, 3, 4)
  10.         
  11.     # mount_check是是否进行mount检查;
  12.     # 如果进行mount检查,并且检查结果没有挂载,则引发http 507错误,提示磁盘没有足够存储空间;
  13.     if self.mount_check and not check_mount(self.root, drive):
  14.         return HTTPInsufficientStorage(drive=drive, request=req)
  15.         
  16.     # 当url中有时,会新建/更新container的信息;
  17.     if container:   # put account container
  18.         pending_timeout = None
  19.         if 'x-trans-id' in req.headers:
  20.             pending_timeout = 3
  21.             
  22.         # _get_account_broker是一个内部方法,功能是返回一个AccountBroker的实例,用于代理对sqlite数据库的操作;
  23.         broker = self._get_account_broker(drive, part, account, pending_timeout=pending_timeout)
  24.             
  25.         # 如果相关的数据库不存在,则进行数据库的初始化操作;
  26.         if account.startswith(self.auto_create_account_prefix) and not os.path.exists(broker.db_file):
  27.                
  28.             # normalize_timestamp:把timestamp(时间戳)转换为标准格式;
  29.             # initialize:数据库初始化;
  30.             try:
  31.                 broker.initialize(normalize_timestamp(req.headers.get('x-timestamp') or time.time()))
  32.             except DatabaseAlreadyExists:
  33.                 pass
  34.         if req.headers.get('x-account-override-deleted', 'no').lower() != 'yes' and broker.is_deleted():
  35.             return HTTPNotFound(request=req)
  36.             
  37.         # 应用给定的属性建立container(在数据库中);
  38.         broker.put_container(container, req.headers['x-put-timestamp'],
  39.                                  req.headers['x-delete-timestamp'],
  40.                                  req.headers['x-object-count'],
  41.                                  req.headers['x-bytes-used'])
  42.         if req.headers['x-delete-timestamp'] > req.headers['x-put-timestamp']:
  43.             return HTTPNoContent(request=req)
  44.         else:
  45.             return HTTPCreated(request=req)
  46.         
  47.     # 当url中没有时,会更新account的metadata信息
  48.     else:   # put account
  49.         # _get_account_broker是一个内部方法,功能是返回一个AccountBroker的实例,用于代理对sqlite数据库的操作;
  50.         broker = self._get_account_broker(drive, part, account)
  51.         # normalize_timestamp:把timestamp(时间戳)转换为标准格式;
  52.         timestamp = normalize_timestamp(req.headers['x-timestamp'])
  53.             
  54.         # 如果对应的数据库对象不存在,则进行数据库的初始化操作;
  55.         if not os.path.exists(broker.db_file):
  56.             try:
  57.                 broker.initialize(timestamp)
  58.                 created = True
  59.             except DatabaseAlreadyExists:
  60.                 created = False
  61.             
  62.         # is_status_deleted:如果状态标志为DELETED,则返回true;
  63.         elif broker.is_status_deleted():
  64.             return self._deleted_response(broker, req, HTTPForbidden, body='Recently deleted')
  65.         else:
  66.             # 检测帐号的数据库是否被删除;
  67.             created = broker.is_deleted()
  68.             # 如果put_timestamp小于当前的时间戳timestamp,则更新put_timestamp;
  69.             broker.update_put_timestamp(timestamp)
  70.             if broker.is_deleted():
  71.                 return HTTPConflict(request=req)
  72.             
  73.         metadata = {}
  74.         # 根据requesthead中的以'x-account-meta-'开始的key的值更新到metadata;
  75.         metadata.update((key, (value, timestamp))
  76.                         for key, value in req.headers.iteritems()
  77.                         if is_sys_or_user_meta('account', key))
  78.             
  79.         # 更新数据库的metadata字段(AccountBroker#update_metadata);
  80.         # 更新数据库的元数据字典;
  81.         if metadata:
  82.             broker.update_metadata(metadata)
  83.             
  84.         # 如果created==True,返回201Created,否则返回202Accepted
  85.         if created:
  86.             return HTTPCreated(request=req)
  87.         else:
  88.             return HTTPAccepted(request=req)PUT
复制代码


请求会handle两种类型的HTTP请求:
当url中有时,会新建/更新container的metadata信息;
当url中没有时,会更新account的metadata信息;

POST

/swift/proxy/controllers/account.py----class AccountController(Controller)----def POST


  1. def POST(self, req):
  2. """HTTP POST request handler."""
  3.     if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH:
  4.         resp = HTTPBadRequest(request=req)
  5.         resp.body = 'Account name length of %d longer than %d' % (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH)
  6.         return resp
  7.     error_response = check_metadata(req, 'account')
  8.     if error_response:
  9.         return error_response
  10.         
  11.     # 获取指定account的分区号和所有副本节点;
  12.     account_partition, accounts = self.app.account_ring.get_nodes(self.account_name)
  13.         
  14.     # 根据原始请求和额外的头信息,为后端的请求生成头信息字典;
  15.     headers = self.generate_request_headers(req, transfer=True)
  16.         
  17.     clear_info_cache(self.app, req.environ, self.account_name)
  18.         
  19.     resp = self.make_requests(
  20.             req, self.app.account_ring, account_partition, 'POST',
  21.             req.swift_entity_path, [headers] * len(accounts))
  22.         
  23.     # 如果没有找到指定account,则先建立这个account;
  24.     # 再实现对其的POST操作;
  25.     if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate:
  26.         self.autocreate_account(req.environ, self.account_name)
  27.         resp = self.make_requests(
  28.             req, self.app.account_ring, account_partition, 'POST',
  29.             req.swift_entity_path, [headers] * len(accounts))
  30.         
  31.     self.add_acls_from_sys_metadata(resp)
  32.     return resp
复制代码


/swift/account/server.py----class AccountController(object)----def POST

  1. def POST(self, req):
  2.     """
  3.     处理HTTP协议的POST请求;
  4.     实现更新account的元数据信息,从head中取出特定要求的metadata更新至指定account的数据库(AccountBroker#update_metadata);
  5.     """
  6.     drive, part, account = split_and_validate_path(req, 3)
  7.     if 'x-timestamp' not in req.headers or not check_float(req.headers['x-timestamp']):
  8.         return HTTPBadRequest(body='Missing or bad timestamp',
  9.                               request=req,
  10.                               content_type='text/plain')
  11.     if self.mount_check and not check_mount(self.root, drive):
  12.         return HTTPInsufficientStorage(drive=drive, request=req)
  13.         
  14.     # _get_account_broker是一个内部方法,功能是返回一个AccountBroker的实例,用于代理对sqlite数据库的操作;
  15.     broker = self._get_account_broker(drive, part, account)
  16.         
  17.     if broker.is_deleted():
  18.         return self._deleted_response(broker, req, HTTPNotFound)
  19.         
  20.     # 把timestamp(时间戳)转换为标准格式;
  21.     timestamp = normalize_timestamp(req.headers['x-timestamp'])
  22.         
  23.     metadata = {}
  24.     metadata.update((key, (value, timestamp))
  25.                     for key, value in req.headers.iteritems()
  26.                     if is_sys_or_user_meta('account', key))
  27.         
  28.     # 然后从head中取出特定要求的metadata更新至数据库;
  29.     if metadata:
  30.         broker.update_metadata(metadata)
  31.         
  32.     return HTTPNoContent(request=req)
复制代码


DELETE

/swift/proxy/controllers/account.py----class AccountController(Controller)----def DELETE

  1. def DELETE(self, req):
  2. """HTTP DELETE request handler."""
  3.     if req.query_string:
  4.         return HTTPBadRequest(request=req)
  5.     if not self.app.allow_account_management:
  6.         return HTTPMethodNotAllowed(
  7.             request=req,
  8.             headers={'Allow': ', '.join(self.allowed_methods)})
  9.         
  10.     # 获取指定account的分区号和所有副本节点;
  11.     account_partition, accounts = self.app.account_ring.get_nodes(self.account_name)
  12.             
  13.     # 根据原始请求和额外的头信息,为后端的请求生成头信息字典;
  14.     headers = self.generate_request_headers(req)
  15.         
  16.     clear_info_cache(self.app, req.environ, self.account_name)
  17.         
  18.     resp = self.make_requests(
  19.         req, self.app.account_ring, account_partition, 'DELETE',
  20.         req.swift_entity_path, [headers] * len(accounts))
复制代码


/swift/account/server.py----class AccountController(object)----def DELETE

  1. def DELETE(self, req):
  2.     """
  3.     处理HTTP协议DELETE请求;
  4.     DELETE请求会删除当前account,但是这里的删除是逻辑删除,只是标记account为删除状态,并不会真正删除account和相关资源;
  5.     """
  6.     # 分割和验证给定的请求路径,获取drive, part, account;
  7.     drive, part, account = split_and_validate_path(req, 3)
  8.         
  9.     # mount_check是是否进行mount检查;
  10.     # 如果进行mount检查,并且检查结果没有挂载,则引发http 507错误,提示磁盘没有足够存储空间;
  11.     # root是devices所在根目录;
  12.     # self.root = conf.get('devices', '/srv/node')
  13.     if self.mount_check and not check_mount(self.root, drive):
  14.         return HTTPInsufficientStorage(drive=drive, request=req)
  15.         
  16.     # 检查head是否包含特定信息'x-timestamp';
  17.     if 'x-timestamp' not in req.headers or \
  18.             not check_float(req.headers['x-timestamp']):
  19.         return HTTPBadRequest(body='Missing timestamp', request=req, content_type='text/plain')
  20.         
  21.     # _get_account_broker是一个内部方法,功能是返回一个AccountBroker的实例,用于代理对sqlite数据库的操作;
  22.     broker = self._get_account_broker(drive, part, account)
  23.         
  24.     # 如果对应的数据库中的对象已经删除,则引发http错误提示;
  25.     if broker.is_deleted():
  26.         return self._deleted_response(broker, req, HTTPNotFound)
  27.         
  28.     # 对数据库中的对象进行删除状态的标记工作,并不会执行文件的删除工作;
  29.     broker.delete_db(req.headers['x-timestamp'])
  30.     return self._deleted_response(broker, req, HTTPNoContent)
复制代码





博客地址:http://blog.csdn.net/gaoxingnengjisuan
邮箱地址:dong.liu@siat.ac.cn


没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条