class Updater(Thread): def __init__(self, walker_map, reader_map, conf, logger): Thread.__init__(self) self.conf = conf self.logger = logger self.logger.info("Updater constructed") self.msg = GlobalVariables(self.logger) self.__complete_all_request = False self._walker_map = walker_map self._reader_map = reader_map self._complete_all_event = self.msg.get_complete_all_event() self._transfer_cmp_event = self.msg.get_transfer_cmp_event() self.__container_dispatcher = ContainerDispatcher(self.conf, self.logger) self._updater_map = {} self.__other_file_list = [] self.put_queue_flag = False def populate_updater_map(self): self.__other_file_list = [] for component, stat_data in self._reader_map.items(): for stat_obj, data in stat_data.items(): if not stat_obj.get_lock_flag(): stat_file = stat_obj.get_stat_file() if not self._updater_map.has_key((component, stat_file)): self._updater_map[(component, stat_file)] = {} if self._reader_map.get(component, None): self._updater_map[(component, stat_file)] = self._reader_map[component][stat_obj] self.__other_file_list.append((component, stat_file)) self.logger.info("Updater map : %s" %self._updater_map) def __updater_check_complete_all_event(self): """ Updater complete all request (Stop) Event check """ if self._complete_all_event.is_set(): self.logger.info("Received complete all request event in updater") self._updater_map = {} self.msg.put_into_Queue() return True def __updater_get_new_ownership(self): """ Updater transfer/accept component request """ if self._transfer_cmp_event.is_set() and not self.put_queue_flag: self.logger.info("Received transfer/accept request event in updater") for comp_tuple in self._updater_map.keys(): if int(comp_tuple[0]) not in self.msg.get_ownershipList(): del self._updater_map[comp_tuple] self.msg.put_into_Queue() self.put_queue_flag = True elif not self._transfer_cmp_event.is_set(): self.put_queue_flag = False def __other_file(self, comp, file): listOfAccounts = [] index = self.__other_file_list.index((comp, file)) rest_comp_tuple_list = self.__other_file_list[:index] + self.__other_file_list[index+1:] for comp_tuple in rest_comp_tuple_list: listOfAccounts.extend(self._updater_map[comp_tuple].keys()) #self.logger.debug("Current component :%s and other stat files having accounts %s" %(comp, listOfAccounts)) return listOfAccounts def run(self): try: while True: self.logger.debug("Updater started") self.populate_updater_map() self.__updater_get_new_ownership() if self.__updater_check_complete_all_event(): self.__complete_all_request = True break waitList = [] delete_list=[] accObjectDict = {} container_list = [] #Container list contains AccountInfo objects where HEAD has been done on Accounts for comp_tuple, map_ in self._updater_map.items(): #NOTE: compTuple = (componentNum, Filename) #NOTE: map_ = {account name : [container name]} self.logger.info("Processing start for stat file : %s, map : %s" %(comp_tuple, map_)) #self.logger.debug("Modified account list: %s" % comp_tuple) if self.__updater_check_complete_all_event(): break for account, cont_list in map_.items(): #NOTE: loop to perform container head for a account and lastly perform account update self.logger.info("Processing account: %s, container_list:%s" %(account, cont_list)) if account not in accObjectDict.keys(): #NOTE: in case account object is already created, no need to re-create the object account_instance = AccountInfo(account, self.conf, self.logger) accObjectDict[account] = account_instance else: account_instance = accObjectDict[account] for container in cont_list: #NOTE: for all container in the account perform container head request if not account_instance.is_container(container): #NOTE: in case container is already existing that means container head has already been performed. #contObj = ContainerClass(container) account_instance.add_container(container) try: #NOTE: perform container HEAD self.logger.debug("Processing for container HEAD request") account_instance.get_container_path() self.__container_dispatcher.dispatcher_executer(account_instance) #If any container HEAD fails then do not perform account update operation and iterate next stat file if "fail" in account_instance.account_map.values(): self.logger.info("Container HEAD is failing on %s, \ skipping stat file %s" %(account, comp_tuple)) break #NOTE: if the account is present in the other stat files than we should not perform account updater # in this iteration. We should add it to waitList and will update account at the end. if account_instance.getAccountName() in self.__other_file(\ comp_tuple[0], comp_tuple[-1]): if account_instance.getAccountName() not in waitList: self.logger.info("Adding account :%s in the waitlist"\ %account_instance.getAccountName()) waitList.append(account_instance.getAccountName()) continue #Performing account update operation if this account is not present in other stat files if self.__container_dispatcher.account_update(account_instance): account_instance.remove_container() else: self.logger.info("Account %s can not be modified" % account) break except Exception as err: self.logger.error("Exception occured :%s", err) # do not create sweeper list of stat_file if any account update(wait list) of that stat_file remains for account in map_.keys(): if account in waitList or ('fail' in accObjectDict[account].account_map.values()) or account_instance.acc_update_failed: break else: self.msg.create_sweeper_list(comp_tuple) del self._updater_map[comp_tuple] self.__other_file_list.remove(comp_tuple) # Sending account update request for accounts exist in waitList at the end for comp_tuple, map_ in self._updater_map.items(): for account in map_.keys(): if account in waitList: if self.__container_dispatcher.account_update(accObjectDict[account]): accObjectDict[account].remove_container() waitList.remove(account) else: self.logger.info("Account %s can not be modified" % account) break elif not accObjectDict.get(account): continue elif ('fail' in accObjectDict[account].account_map.values()): self.logger.info("Container HEAD is failing on %s, \ skipping stat file %s" %(account, comp_tuple)) break elif not accObjectDict[account].acc_update_failed: self.logger.info("Account : %s already updated" %account) elif accObjectDict[account].acc_update_failed: self.logger.info("Account update for %s failed, \ skipping stat file %s" %(account, comp_tuple)) break else: self.msg.create_sweeper_list(comp_tuple) del self._updater_map[comp_tuple] self.__other_file_list.remove(comp_tuple) #self._updater_map = {} # Will be clear after one time processing self.logger.debug("Exiting Updater") time.sleep(40) except Exception as ex: self.logger.error("exception occured : %s" %ex) os._exit(130) except: self.logger.error("unkown exception occured") os._exit(130)
class Reader(Thread): def __init__(self, walker_map, reader_map, conf, logger): Thread.__init__(self) self._walker_map = walker_map self._reader_map = reader_map self.logger = logger self.logger.info("Reader constructed") self._file_location = conf['stat_file_location'] self.msg = GlobalVariables(self.logger) self._complete_all_event = self.msg.get_complete_all_event() self._transfer_cmp_event = self.msg.get_transfer_cmp_event() self.put_queue_flag = False def __reader_check_complete_all_event(self): """ Reader complete all request (Stop) Event check """ if self._complete_all_event.is_set(): self.logger.info("Received complete all request event in reader") self._reader_map = {} self.msg.put_into_Queue() return True def __reader_get_new_ownership(self): """ Reader transfer/accept component request """ if self._transfer_cmp_event.is_set() and not self.put_queue_flag: self.logger.info( "Received transfer/accept request event in reader") for key in self._reader_map.keys(): if int(key) not in self.msg.get_ownershipList(): del self._reader_map[key] self.msg.put_into_Queue() self.put_queue_flag = True elif not self._transfer_cmp_event.is_set(): self.put_queue_flag = False def read_stat_file(self, comp, stat_file): if not os.path.exists( os.path.join(self._file_location, comp, stat_file)): raise StopIteration with open(os.path.join(self._file_location, comp, stat_file), 'rt') as fd: while True: data = fd.read(MAX_CHUNK_SIZE) if not data: break yield data.split(',')[:-1] def check_if_container_limit_exceeded(self): while self._reader_map.getContainerCount() > maxContainerEntries: self.logger.info("Container limit exceeded :%s therefore wait till"\ "update completed" %(self._reader_map.getContainerCount())) time.sleep(10) def run(self): try: self.__perform_reader_operation() except Exception as ex: self.logger.error("error occured : %s" % ex) os._exit(130) except: self.logger.error("Unknown exception occured") os._exit(130) def __perform_reader_operation(self): while True: self.logger.debug("Reader started") if self.__reader_check_complete_all_event(): break try: self.__reader_get_new_ownership() for entry in self._walker_map.getEntries(): comp, stat_file = entry.split("/") self._stat_obj = StatFile(stat_file) self.check_if_container_limit_exceeded() self.logger.debug("Processing start for component:%s stat" " files: %s" % (comp, stat_file)) for file_content in self.read_stat_file(comp, stat_file): self._stat_obj.set_lock_flag(True) for data in file_content: account_name, container_name = data.split("/") if comp not in self._reader_map.keys(): self._reader_map[comp] = {} if self._stat_obj not in self._reader_map[ comp].keys(): self._reader_map[comp][self._stat_obj] = {} if account_name not in self._reader_map[comp][ self._stat_obj].keys(): self._reader_map[comp][ self._stat_obj][account_name] = [] self._reader_map[comp][self._stat_obj][ account_name].append(container_name) self._reader_map.incrementContainer() self._stat_obj.set_lock_flag(False) self.logger.info("Stat File:%s processing done for component:%s count:%s" \ %(stat_file, comp, self._reader_map.getContainerCount())) self.logger.debug( "After completing all stat file processing, reader_map = \ %s" % (self._reader_map)) except Exception as ex: self.logger.error("Exception occured :%s" % ex) self.logger.debug("Exiting Reader") time.sleep(35)
class Walker(Thread): def __init__(self, walker_map, conf, logger): Thread.__init__(self) #self.__conf = conf # TODO : once the complete configuration file will be created correct entries would be fetched self._file_location = conf['stat_file_location'] self._max_update_files = conf['max_update_files'] self._max_files_stored_in_cache = conf['max_files_stored_in_cache'] self._expire_delta_time = conf['updaterfile_expire_delta_time'] self.logger = logger self.msg = GlobalVariables(self.logger) #self.__MainPath = '/remote/hydra042/spsingh/Latest/objectStorage/src/osd/NewUpdater/devesh/sps/upfiles1' #Todo: will be fetched from configuration file #self.__ownershipList = ['X9','X3','X4','X5','X6','X8'] #TODO: dummy value, will be set at service start self._ownership_list = self.msg.get_ownershipList() self._walker_map = walker_map self.logger.info("Walker constructed") self._complete_all_event = self.msg.get_complete_all_event() self._transfer_cmp_event = self.msg.get_transfer_cmp_event() self.put_queue_flag = False """ Service Stop Event Handling """ def __walker_check_complete_all_event(self): """ Walker complete all request (Stop) Event check """ if self._complete_all_event.is_set(): self.logger.info("Received complete all request event in walker") self._walker_map = [] self.msg.put_into_Queue() return True """ Get Component Map Event Handling """ def __walker_get_new_ownership(self): """ Walker transfer/accept component request """ if self._transfer_cmp_event.is_set() and not self.put_queue_flag: self.logger.info( "Received transfer/accept request event in walker") self._ownership_list = self.msg.get_ownershipList() self.msg.put_into_Queue() self.put_queue_flag = True elif not self._transfer_cmp_event.is_set(): self.put_queue_flag = False def run(self): try: self.__perform_walker_operation() except Exception as ex: self.logger.error("error occured : %s" % ex) os._exit(130) except: self.logger.error("Unknown exception occured") os._exit(130) def __perform_walker_operation(self): old_stat_files = {} while True: self.logger.debug("Walker started") temp_structure = [] self._ownership_list = self.msg.get_ownershipList() if self.__walker_check_complete_all_event(): break self.__walker_get_new_ownership() try: if not old_stat_files: old_stat_files = {} all_stat_files = {} for comp in self._ownership_list: if os.path.exists( os.path.join(self._file_location, str(comp))): for file in os.listdir( '%s/%s' % (self._file_location, comp)): all_stat_files[os.path.join(self._file_location, str(comp), file)] = \ os.path.getmtime(os.path.join(self._file_location, str(comp), file)) for old_file, modtime in sorted(all_stat_files.items(), key=lambda file: \ file[1])[:-1][:self._max_files_stored_in_cache]: old_stat_files[os.path.join(old_file.split('/')[-2:-1][0], \ os.path.basename(old_file))] = all_stat_files[old_file] if len( os.listdir( '%s/%s' % (self._file_location, comp))) == 1: left_file = os.listdir( '%s/%s' % (self._file_location, comp))[0] totalsecond_diff = respondsecondsDiff( left_file) if totalsecond_diff > self._expire_delta_time: old_stat_files[os.path.join(str(comp),left_file)] = \ os.path.getmtime(os.path.join(self._file_location, str(comp), left_file)) else: self.logger.debug("Stat file %s not Expired: " \ %os.path.join(self._file_location, str(comp), left_file)) all_stat_files = {} else: self.logger.debug( "Directory :%s not exists" % os.path.join(self._file_location, str(comp))) for stat_file in old_stat_files.keys(): if os.stat(os.path.join(self._file_location, stat_file)).st_size == 0: comp_tuple = (stat_file.split('/')[0], stat_file.split('/')[1]) self.logger.info("Stat file :%s is empty therefore deleting it" \ %os.path.join(self._file_location, stat_file)) self.msg.create_sweeper_list(comp_tuple) del old_stat_files[stat_file] for stat_file, modtime in sorted(old_stat_files.items(), key=lambda file : \ file[1])[:self._max_update_files]: if stat_file not in temp_structure: temp_structure.append(stat_file) del old_stat_files[stat_file] self._walker_map[:] = temp_structure[:self._max_update_files] self.logger.debug("State files to be processed at walker :%s" % self._walker_map) except Exception as ex: self.logger.error("Exception occured :%s", ex) self.logger.debug("Exiting walker") time.sleep(30)