/* sort flist by specified fields, given as common-delimitted list * precede field name with '-' character to reverse sort order: * name,user,group,uid,gid,atime,mtime,ctime,size * For example to sort by size in descending order, followed by name * char fields[] = "size,-name"; */ int mfu_flist_sort(const char* sortfields, mfu_flist* pflist) { if (sortfields == NULL || pflist == NULL) { return MFU_FAILURE; } /* get pointer to list */ mfu_flist flist = *pflist; /* start timer */ double start_sort = MPI_Wtime(); /* sort list */ int rc; if (mfu_flist_have_detail(flist)) { rc = sort_files_stat(sortfields, pflist); } else { rc = sort_files_readdir(sortfields, pflist); } /* end timer */ double end_sort = MPI_Wtime(); /* report sort count, time, and rate */ if (mfu_debug_level >= MFU_LOG_VERBOSE && mfu_rank == 0) { uint64_t all_count = mfu_flist_global_size(flist); double secs = end_sort - start_sort; double rate = 0.0; if (secs > 0.0) { rate = ((double)all_count) / secs; } printf("Sorted %lu files in %f seconds (%f files/sec)\n", all_count, secs, rate ); } return rc; }
/* removes list of items, sets write bits on directories from * top-to-bottom, then removes items one level at a time starting * from the deepest */ void mfu_flist_unlink(mfu_flist flist) { int level; /* wait for all tasks and start timer */ MPI_Barrier(MPI_COMM_WORLD); double start_remove = MPI_Wtime(); /* split files into separate lists by directory depth */ int levels, minlevel; mfu_flist* lists; mfu_flist_array_by_depth(flist, &levels, &minlevel, &lists); #if 0 /* dive from shallow to deep, ensure all directories have write bit set */ for (level = 0; level < levels; level++) { /* get list of items for this level */ mfu_flist list = lists[level]; /* determine whether we have details at this level */ int detail = mfu_flist_have_detail(list); /* iterate over items and set write bit on directories if needed */ uint64_t idx; uint64_t size = mfu_flist_size(list); for (idx = 0; idx < size; idx++) { /* check whether we have a directory */ mfu_filetype type = mfu_flist_file_get_type(list, idx); if (type == MFU_TYPE_DIR) { /* assume we have to set the bit */ int set_write_bit = 1; if (detail) { mode_t mode = (mode_t) mfu_flist_file_get_mode(list, idx); if (mode & S_IWUSR) { /* we have the mode of the file, and the bit is already set */ set_write_bit = 0; } } /* set the bit if needed */ if (set_write_bit) { const char* name = mfu_flist_file_get_name(list, idx); int rc = chmod(name, S_IRWXU); if (rc != 0) { MFU_LOG(MFU_LOG_ERR, "Failed to chmod directory `%s' (errno=%d %s)", name, errno, strerror(errno) ); } } } } /* wait for all procs to finish before we start next level */ MPI_Barrier(MPI_COMM_WORLD); } #endif /* now remove files starting from deepest level */ for (level = levels - 1; level >= 0; level--) { double start = MPI_Wtime(); /* get list of items for this level */ mfu_flist list = lists[level]; uint64_t count = 0; //remove_direct(list, &count); remove_spread(list, &count); // remove_map(list, &count); // remove_sort(list, &count); // remove_libcircle(list, &count); // TODO: remove sort w/ spread /* wait for all procs to finish before we start * with files at next level */ MPI_Barrier(MPI_COMM_WORLD); double end = MPI_Wtime(); if (mfu_debug_level >= MFU_LOG_VERBOSE) { uint64_t min, max, sum; MPI_Allreduce(&count, &min, 1, MPI_UINT64_T, MPI_MIN, MPI_COMM_WORLD); MPI_Allreduce(&count, &max, 1, MPI_UINT64_T, MPI_MAX, MPI_COMM_WORLD); MPI_Allreduce(&count, &sum, 1, MPI_UINT64_T, MPI_SUM, MPI_COMM_WORLD); double rate = 0.0; if (end - start > 0.0) { rate = (double)sum / (end - start); } double time_diff = end - start; if (mfu_rank == 0) { printf("level=%d min=%lu max=%lu sum=%lu rate=%f secs=%f\n", (minlevel + level), (unsigned long)min, (unsigned long)max, (unsigned long)sum, rate, time_diff ); fflush(stdout); } } } mfu_flist_array_free(levels, &lists); /* wait for all tasks and stop timer */ MPI_Barrier(MPI_COMM_WORLD); double end_remove = MPI_Wtime(); /* report remove count, time, and rate */ if (mfu_debug_level >= MFU_LOG_VERBOSE && mfu_rank == 0) { uint64_t all_count = mfu_flist_global_size(flist); double time_diff = end_remove - start_remove; double rate = 0.0; if (time_diff > 0.0) { rate = ((double)all_count) / time_diff; } printf("Removed %lu items in %f seconds (%f items/sec)\n", all_count, time_diff, rate ); } return; }
/* print information about a file given the index and rank (used in print_files) */ static void print_file(mfu_flist flist, uint64_t idx) { /* store types as strings for print_file */ char type_str_unknown[] = "UNK"; char type_str_dir[] = "DIR"; char type_str_file[] = "REG"; char type_str_link[] = "LNK"; /* get filename */ const char* file = mfu_flist_file_get_name(flist, idx); if (mfu_flist_have_detail(flist)) { /* get mode */ mode_t mode = (mode_t) mfu_flist_file_get_mode(flist, idx); //uint32_t uid = (uint32_t) mfu_flist_file_get_uid(flist, idx); //uint32_t gid = (uint32_t) mfu_flist_file_get_gid(flist, idx); uint64_t acc = mfu_flist_file_get_atime(flist, idx); uint64_t mod = mfu_flist_file_get_mtime(flist, idx); uint64_t cre = mfu_flist_file_get_ctime(flist, idx); uint64_t size = mfu_flist_file_get_size(flist, idx); const char* username = mfu_flist_file_get_username(flist, idx); const char* groupname = mfu_flist_file_get_groupname(flist, idx); char access_s[30]; char modify_s[30]; char create_s[30]; time_t access_t = (time_t) acc; time_t modify_t = (time_t) mod; time_t create_t = (time_t) cre; size_t access_rc = strftime(access_s, sizeof(access_s) - 1, "%FT%T", localtime(&access_t)); //size_t modify_rc = strftime(modify_s, sizeof(modify_s) - 1, "%FT%T", localtime(&modify_t)); size_t modify_rc = strftime(modify_s, sizeof(modify_s) - 1, "%b %e %Y %H:%M", localtime(&modify_t)); size_t create_rc = strftime(create_s, sizeof(create_s) - 1, "%FT%T", localtime(&create_t)); if (access_rc == 0 || modify_rc == 0 || create_rc == 0) { /* error */ access_s[0] = '\0'; modify_s[0] = '\0'; create_s[0] = '\0'; } char mode_format[11]; mfu_format_mode(mode, mode_format); double size_tmp; const char* size_units; mfu_format_bytes(size, &size_tmp, &size_units); printf("%s %s %s %7.3f %2s %s %s\n", mode_format, username, groupname, size_tmp, size_units, modify_s, file ); #if 0 printf("%s %s %s A%s M%s C%s %lu %s\n", mode_format, username, groupname, access_s, modify_s, create_s, (unsigned long)size, file ); printf("Mode=%lx(%s) UID=%d(%s) GUI=%d(%s) Access=%s Modify=%s Create=%s Size=%lu File=%s\n", (unsigned long)mode, mode_format, uid, username, gid, groupname, access_s, modify_s, create_s, (unsigned long)size, file ); #endif } else { /* get type */ mfu_filetype type = mfu_flist_file_get_type(flist, idx); char* type_str = type_str_unknown; if (type == MFU_TYPE_DIR) { type_str = type_str_dir; } else if (type == MFU_TYPE_FILE) { type_str = type_str_file; } else if (type == MFU_TYPE_LINK) { type_str = type_str_link; } printf("Type=%s File=%s\n", type_str, file ); } }