Swift中的Account Server代码解读

用户的HTTP请求被AccountController、ContainerController与ObjectController分别转发给存储节点上的Account Server、Container Server和Object Server,这三个服务与Proxy Server一样也是WSGI Server,通过run_wsgi()函数启动,通过Paste Deploy加载对应的WSGI Application
Account Server的Paste配置文件位于/etc/swift/account-server/目录下:
[pipeline:main]
pipeline = healthcheck recon account-server
[app:account-server]
use = egg:swift#account
setup.cfg文件配置如下:
[entry_points]
paste.app_factory =
    proxy = swift.proxy.server:app_factory
    object = swift.obj.server:app_factory
    mem_object = swift.obj.mem_server:app_factory
    container = swift.container.server:app_factory
    account = swift.account.server:app_factory
结合Paste配置文件与setup.cfg文件的设置,Paste Deply最终将使用swift.account.server模块的app_factory()函数加载Account Server的WSGI Application,即swift.account.server. AccountController
#swift/account/server.py
class AccountController(object):
def app_factory(global_conf, **local_conf):
    """paste.deploy app factory for creating WSGI account server apps"""
    conf = global_conf.copy()
    conf.update(local_conf)
return AccountController(conf)
这里的Controller与上述swift/proxy/controllers目录下的Controller不同,后者的作用是将用户的HTTP请求转发给Account Server,而前者则是对该请求的最终处理。
以PUT操作为例,针对Account的PUT操作有两种语义:
1 创建一个Account
2 创建Account中的Container。它们的区别在于路径参数是否包含Container的信息。
#swift/account/server.py
class AccountController(object):
    """WSGI controller for the account server."""
    def PUT(self, req):
        """Handle HTTP PUT request."""
        #从请求参数req里面获取drive, part, account, container信息
        drive, part, account, container = split_and_validate_path(req, 3, 4)
        if self.mount_check and not check_mount(self.root, drive):
            return HTTPInsufficientStorage(drive=drive, request=req)
        #如果container的信息不为空,则视该请求为创建某个account的container
        if container: # put account container
            if 'x-timestamp' not in req.headers:
                timestamp = Timestamp(time.time())
            else:
                timestamp = valid_timestamp(req)
            pending_timeout = None
            container_policy_index = \
                req.headers.get('X-Backend-Storage-Policy-Index', 0)
            if 'x-trans-id' in req.headers:
                pending_timeout = 3
            #构建并返回一个AccountBroker类的实例。AccountBroker类继承于
            #DatabaseBroker类,其内部包括了针对account数据库文件的操作函数。
            #可以把partition理解为一个目录,每一个partition中的accout数据是以这个目录
            #中的数据库文件形式存在的。
            #该partition中的每一个account都对应一个数据库文件。
            #AccountBroker这个类将操作account数据库文件的函数加以封装,
            #作为其成员函数来使用
            broker = self._get_account_broker(drive, part, account,
                                              pending_timeout=pending_timeout)
            if account.startswith(self.auto_create_account_prefix) and \
                    not os.path.exists(broker.db_file):
                try:
                    #如果该account的数据库文件尚未存在,则调用AccountBroker类的
                    #initialize()函数创建该数据文件。
                    broker.initialize(timestamp.internal)
                except DatabaseAlreadyExists:
                    pass
            if req.headers.get('x-account-override-deleted', 'no').lower() != \
                    'yes' and broker.is_deleted():
                return HTTPNotFound(request=req)
            #通过调用AccountBroker中的put_container()函数将container的信息
            #写入该account的数据库文件中去。
            broker.put_container(container, req.headers['x-put-timestamp'],
                                 req.headers['x-delete-timestamp'],
                                 req.headers['x-object-count'],
                                 req.headers['x-bytes-used'],
                                 container_policy_index)
            if req.headers['x-delete-timestamp'] > \
                    req.headers['x-put-timestamp']:
                return HTTPNoContent(request=req)
            else:
                return HTTPCreated(request=req)
        #如果container的信息为空,则视该请求为创建account
        else: # put account
            timestamp = valid_timestamp(req)
            #获取一个AccountBroker的实例
            broker = self._get_account_broker(drive, part, account)
            #如果该account的数据库文件未存在则创建
            if not os.path.exists(broker.db_file):
                try:
                    broker.initialize(timestamp.internal)
                    created = True
                except DatabaseAlreadyExists:
                    created = False
            elif broker.is_status_deleted():
                return self._deleted_response(broker, req, HTTPForbidden,
                                              body='Recently deleted')
            else:
                created = broker.is_deleted()
                broker.update_put_timestamp(timestamp.internal)
                if broker.is_deleted():
                    return HTTPConflict(request=req)
            metadata = {}
            metadata.update((key, (value, timestamp.internal))
                            for key, value in req.headers.iteritems()
                            if is_sys_or_user_meta('account', key))
            if metadata:
                 #更新元数据
                broker.update_metadata(metadata, validate_metadata=True)
            if created:
                return HTTPCreated(request=req)
            else:
                return HTTPAccepted(request=req)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值