def recovery_by_haystack(pid, gid): hpath = get_haystack_path(pid, gid) h = haystack.Haystack(hpath) old_num = h.get_latest_version_num() ver_num, haystack_fpaths = download_haystack(pid, gid) renamed_paths = [] try: attr_sha1 = haystack_version.get_file_sha1( haystack_fpaths['attribute'] ) for fn_key, src_path in haystack_fpaths.items(): dst_path = get_haystack_file_path(pid, gid, ver_num, fn_key) rename_force(src_path, dst_path) renamed_paths.append(dst_path) h.reset_version_num( ver_num, attr_sha1 ) except Exception as e: delete_files( renamed_paths ) delete_files( haystack_fpaths.values() ) raise switch_port = partition.pid_port(pid) switch_url = SWITCH_VERSION_PREFIX + pid + '/' + str(gid) h._switch_version(switch_port, switch_url) if old_num != ver_num: h.delete_version(old_num, switch_port, switch_url)
def create_haystack(pid, gid, files): for fn, fpath in files.items(): checksum = fn.split('-', 1)[0] #一致性 检查 try: s2recovery_util.check_file_consistent(fpath, checksum) except s2recovery_util.FileDamaged as e: logger.info( repr(e) + ' ' + fpath ) raise group.FileDamaged ( ('pid', pid), ('gid', gid), ('fn', fn) ) needle_list = create_needle_list(files) #创建needle-list 格式如下 #[{'file_names': ['069e6fabca59e1ba3db034950b88aa074708cf30-99532'], 'data_parts': [{'path': #'/data6/064247da00014006a370842b2b0c0467/g553698/040/069e6fabca59e1ba3db034950b88aa074708cf30-99532'#, 'size': 229, 'offset': 0}], 'key': #'\x06\x9eo\xab\xcaY\xe1\xba=\xb04\x95\x0b\x88\xaa\x07G\x08\xcf0'}, hpath = get_haystack_path(pid, gid) _mkdir(hpath) #创建 haystack目录 port = partition.pid_port(pid) h = haystack.Haystack(hpath) try: h.create( needle_list, chunk_num = CHUNK_NUM, switch_version_port = port, switch_version_url = SWITCH_VERSION_PREFIX + pid + '/' + str(gid) ) except haystack_version.VersionExisted as e: logger.info( 'haystack %s %s current version is existed ' % (pid, gid) )
def download_haystack_from_part(local_pid, remote_pid, gid): hpath = get_haystack_path(local_pid, gid) spath = os.path.join( hpath, SYNC_HAYSTACK_FOLDER ) _mkdir(spath) files_path = {} hfs = get_haystack_files_list(remote_pid, gid) try: for fn_key, sha1 in hfs['files_sha1'].items(): fpath = os.path.join( spath, 'haystack_%s_%s_'%(hfs['version'], fn_key) + str( time.time() ) ) ips = _get_prt_ips(remote_pid) port = partition.pid_port( remote_pid, mine = False ) uri = stoclient.get_haystack_file_uri( remote_pid, {'group_id': gid, 'version': hfs['version'], 'fn_key': fn_key}, timeout=36000 ) s2recovery_util.download(fpath, ips, port, uri, sha1) files_path[fn_key] = fpath except Exception as e: delete_files( files_path.values() ) raise return hfs['version'], files_path
def download_haystack_file(pid, gid, ver_num, fn_key, sha1): hpath = get_haystack_path(pid, gid) spath = os.path.join( hpath, SYNC_HAYSTACK_FOLDER ) _mkdir(spath) prts = partition_util.get_sorted_prts(gid) for remote_prt in prts: remote_pid = remote_prt['partition_id'] if _prt_dead( remote_pid ) or remote_pid == pid or remote_prt['is_del']: continue ips = _get_prt_ips(remote_pid) port = partition.pid_port( remote_pid, mine = False ) uri = stoclient.get_haystack_file_uri( remote_pid, {'group_id': gid, 'version': ver_num, 'fn_key': fn_key}, timeout=36000 ) fpath = os.path.join( spath, 'haystack_%s_%s_'%(ver_num, fn_key) + str( time.time() ) ) try: s2recovery_util.download(fpath, ips, port, uri, sha1) break except s2recovery_util.DownloadError as e: logger.info( repr(e) + " s2recovery: download pid:%s gid:%d haytack haystack_%s_%s file fail! "% (remote_pid, gid, ver_num, fn_key) ) else: raise return fpath
def create_haystack(pid, gid, files): for fn, fpath in files.items(): checksum = fn.split('-', 1)[0] try: s2recovery_util.check_file_consistent(fpath, checksum) except s2recovery_util.FileDamaged as e: logger.info( repr(e) + ' ' + fpath ) raise group.FileDamaged ( ('pid', pid), ('gid', gid), ('fn', fn) ) needle_list = create_needle_list(files) hpath = get_haystack_path(pid, gid) _mkdir(hpath) port = partition.pid_port(pid) h = haystack.Haystack(hpath) try: h.create( needle_list, chunk_num = CHUNK_NUM, switch_version_port = port, switch_version_url = SWITCH_VERSION_PREFIX + pid + '/' + str(gid) ) except haystack_version.VersionExisted as e: logger.info( 'haystack %s %s current version is existed ' % (pid, gid) )
def get_haystack_files_list(pid, gid): ips = _get_prt_ips(pid) uri = stoclient.get_haystack_files_list_uri( pid, {'group_id': gid}, timeout=36000) port = partition.pid_port(pid, mine = False) buf = s2recovery_util.http_get_to_buf(ips, port, uri) j = s2json.load( buf ) return j
def remerge_by_original_files(pid, gid): logger.info('haystack_check: pid:%s, gid:%d, begin creating new haystack by original files!'%(pid, gid)) clear_haystack_original_fns(pid, gid) try: s2recovery.recover_group(pid, gid) except s2recovery.GroupIncomplete as e: pass hash_files = get_hash_files(pid, gid) needle_list = create_needle_list(hash_files) hpath = get_haystack_path(pid, gid) h = haystack.Haystack(hpath) ver_num = h.get_latest_version_num() if ver_num is not None: try: ver = haystack_version.HaystackVersion(hpath, ver_num) needles = ver.get_valid_needle_list( ver.get_damaged_chunks_indexes() ) needle_list.extend(needles) except (haystack_version.VersionNotFound, haystack_version.FileDamaged) as e: logger.info( repr(e) + 'version %s error!' % ver_num ) new_num = h.create_version(needle_list, CHUNK_NUM, switch_version_port = partition.pid_port(pid), switch_version_url = SWITCH_VERSION_PREFIX + pid + '/' + str(gid), force = True) delete_files( hash_files.values() ) delete_empty_hash_folders(pid, gid) logger.info('haystack_check: pid:%s, gid:%d, finish creating new haystack by original files, version num is %s !' %(pid, gid, ver_num))