天天看點

Swift源碼分析----swift-account-auditor

感謝朋友支援本部落格,歡迎共同探讨交流,由于能力和時間有限,錯誤之處在所難免,歡迎指正!

如果轉載,請保留作者資訊。

部落格位址:http://blog.csdn.net/gaoxingnengjisuan

郵箱位址:[email protected]

PS:最近沒有登入部落格,很多朋友的留言沒有看見,這裡道歉!還有就是本人較少上QQ,可以郵件交流。

概述部分:

賬戶審計守護程序;  

審計的主要的職責就是檢查賬戶資料是否被删除(通過解析賬戶目錄下的.db檔案);

這裡定義的once=True,說明系統預設調用守護程序類Daemon中的run_once方法,有人說run_once主要應用于測試,這個沒有驗證;

進而最終實作調用AccountAuditor類中的run_once方法;

如果調用的是AccountAuditor類中的run_forever方法,則會實作循環實作檢查指定賬戶資料是否被删除;

源碼解析部分:

from swift.account.auditor import AccountAuditor
from swift.common.utils import parse_options
from swift.common.daemon import run_daemon

if __name__ == '__main__':
    conf_file, options = parse_options(once=True)
    run_daemon(AccountAuditor, conf_file, **options)
           
def run_daemon(klass, conf_file, section_name='', once=False, **kwargs):
    """ 
    從配置檔案加載設定,然後執行個體化守護程序“klass”并運作這個守護程序通過指定的參數kwarg;
    """
    ......

   try:
       klass(conf).run(once=once, **kwargs)
   except KeyboardInterrupt:
       logger.info('User quit')
   logger.info('Exited')
           
def run(self, once=False, **kwargs):
    """
   Run the daemon
    運作守護程序程式;
    即運作方法run_once,或者方法run_forever;
    """
    # 配置參數相關;
   utils.validate_configuration()
   utils.drop_privileges(self.conf.get('user', 'swift'))
    # 日志相關處理;
   utils.capture_stdio(self.logger, **kwargs)

   def kill_children(*args):
       signal.signal(signal.SIGTERM, signal.SIG_IGN)
       os.killpg(0, signal.SIGTERM)
       sys.exit()

   signal.signal(signal.SIGTERM, kill_children)
   if once:
       self.run_once(**kwargs)
   else:
       self.run_forever(**kwargs)
           
def run_once(self, *args, **kwargs):
    """
   Override this to run the script once
    子類中的方法需要被重寫;
    """
   raise NotImplementedError('run_once not implemented')
           
def run_once(self, *args, **kwargs):
    """
   Run the account audit once.
    運作一次賬戶審計;
    調用方法_one_audit_pass,首先計算獲得path,device,partition;
    然後通過方法account_audit對這些賬戶内容進行審計,看是否被删除;
    """
   self.logger.info(_('Begin account audit "once" mode'))
   begin = reported = time.time()
   self._one_audit_pass(reported)
   elapsed = time.time() - begin
   self.logger.info(
     _('Account audit "once" mode completed: %.02fs'), elapsed)
     dump_recon_cache({'account_auditor_pass_completed': elapsed},
                      self.rcache, self.logger)
           
def _one_audit_pass(self, reported):
    """
    首先通過方法audit_location_generator方法計算獲得所有以.db為字尾的檔案生成path,device,partition;
    然後通過方法account_audit對這些賬戶内容進行審計,看是否被删除;
    """
        
    # 基于給定的裝置路徑和檔案字尾,為在這個資料目錄中的所有以.db為字尾的檔案生成元組(path, device, partition);
    # 通過方法audit_location_generator方法計算獲得path,device,partition;
   all_locs = audit_location_generator(self.devices, DATADIR, '.db',
                                       mount_check=self.mount_check,
                                       logger=self.logger)
   for path, device, partition in all_locs:
        # 審計給定的賬戶,看看是否已經被删除,如果沒有删除,則為賬戶擷取全局資料;
        # 擷取包括account, created_at, put_timestamp, delete_timestamp, container_count, object_count, bytes_used, hash, id等值的字典;
       self.account_audit(path)
       if time.time() - reported >= 3600:  # once an hour
           self.logger.info(_('Since %(time)s: Account audits: '
                              '%(passed)s passed audit,'
                              '%(failed)s failed audit'),
                              {'time': time.ctime(reported),
                               'passed': self.account_passes,
                               'failed': self.account_failures})
           dump_recon_cache({'account_audits_since': reported,
                             'account_audits_passed': self.account_passes,
                             'account_audits_failed':
                             self.account_failures},
                             self.rcache, self.logger)
           reported = time.time()
           self.account_passes = 0
           self.account_failures = 0
       self.accounts_running_time = ratelimit_sleep(self.accounts_running_time, self.max_accounts_per_second)
   return reported
           

1.調用方法audit_location_generator,實作基于給定的裝置路徑(self.devices,DATADIR=accounts)和檔案字尾(.db),為在這個資料目錄中的所有以.db為字尾的檔案生成元組(path, device, partition);

生成路徑示例如下:

path = /devices/device/accounts/partition/asuffix/hsh/****.db

device:self.devices下具體的一個裝置名稱;

partition:/devices/device/accounts/下具體的一個分區名稱;

2.周遊元組(path, device, partition)中的每一個比對對,調用方法account_audit實作審計給定的賬戶,看看是否已經被删除,如果沒有删除,則為賬戶擷取全局資料;

轉到2,來看方法account_audit:

def account_audit(self, path):
        """
        審計給定的賬戶,看看是否已經被删除,如果沒有删除,則為賬戶擷取全局資料;
        擷取包括account, created_at, put_timestamp, delete_timestamp, container_count, object_count, bytes_used, hash, id等值的字典;
        """
      start_time = time.time()
      try:
          broker = AccountBroker(path)
          # is_deleted:檢測帳号的資料庫是否被删除;
          if not broker.is_deleted():
                  # 為賬戶擷取全局資料;
                  # 傳回包括account, created_at, put_timestamp, delete_timestamp, container_count, object_count, bytes_used, hash, id等值的字典;
              broker.get_info()
              self.logger.increment('passes')
              self.account_passes += 1
              self.logger.debug(_('Audit passed for %s') % broker)
      except (Exception, Timeout):
          self.logger.increment('failures')
          self.account_failures += 1
          self.logger.exception(_('ERROR Could not get account info %s'),
                                  path)
      self.logger.timing_since('timing', start_time)
           

這個方法的實作比較簡單,這裡就不再進一步進行解析;