/* * Obtaines a filesetentry entity for a file to be placed in a * (sub)directory of a fileset. The size of the file may be * specified by fs_meansize, or calculated from a gamma * distribution of parameter fs_sizegamma and of mean size * fs_meansize. The filesetentry entity is placed on the file * list in the specified parent filesetentry entity, which may * be a directory filesetentry, or the root filesetentry in the * fileset. It is also placed on the fileset's list of all * contained files. Returns 0 if successful or -1 if ipc memory * for the path string cannot be allocated. */ static int fileset_populate_file(fileset_t *fileset, filesetentry_t *parent, int serial) { char tmpname[16]; filesetentry_t *entry; double drand; double gamma; if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) == NULL) { filebench_log(LOG_ERROR, "fileset_populate_file: Can't malloc filesetentry"); return (-1); } (void) pthread_mutex_init(&entry->fse_lock, ipc_mutexattr()); entry->fse_parent = parent; entry->fse_fileset = fileset; entry->fse_flags |= FSE_FREE; fileset_insfilelist(fileset, entry); (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { filebench_log(LOG_ERROR, "fileset_populate_file: Can't alloc path string"); return (-1); } gamma = *(fileset->fs_sizegamma) / 1000.0; if (gamma > 0) { drand = gamma_dist_knuth(gamma, fileset->fs_meansize / gamma); entry->fse_size = (off64_t)drand; } else { entry->fse_size = (off64_t)fileset->fs_meansize; } fileset->fs_bytes += entry->fse_size; fileset->fs_realfiles++; return (0); }
/* * Creates a directory node in a fileset, by obtaining a * filesetentry entity for the node and initializing it * according to parameters of the fileset. It determines a * directory tree depth and directory width, optionally using * a gamma distribution. If its calculated depth is less then * its actual depth in the directory tree, it becomes a leaf * node and files itself with "width" number of file type * filesetentries, otherwise it files itself with "width" * number of directory type filesetentries, using recursive * calls to fileset_populate_subdir. The end result of the * initial call to this routine is a tree of directories of * random width and varying depth with sufficient leaf * directories to contain all required files. * Returns 0 on success. Returns -1 if ipc path string memory * cannot be allocated and returns an error code (currently * also -1) from calls to fileset_populate_file or recursive * calls to fileset_populate_subdir. */ static int fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent, int serial, double depth) { double randepth, drand, ranwidth, gamma; int isleaf = 0; char tmpname[16]; filesetentry_t *entry; int i; depth += 1; /* Create dir node */ if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) == NULL) { filebench_log(LOG_ERROR, "fileset_populate_subdir: Can't malloc filesetentry"); return (-1); } (void) pthread_mutex_init(&entry->fse_lock, ipc_mutexattr()); (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { filebench_log(LOG_ERROR, "fileset_populate_subdir: Can't alloc path string"); return (-1); } entry->fse_parent = parent; entry->fse_flags |= FSE_DIR | FSE_FREE; fileset_insdirlist(fileset, entry); gamma = *(fileset->fs_dirgamma) / 1000.0; if (gamma > 0) { drand = gamma_dist_knuth(gamma, fileset->fs_meandepth / gamma); randepth = (int)drand; } else { randepth = (int)fileset->fs_meandepth; } gamma = *(fileset->fs_sizegamma) / 1000.0; if (gamma > 0) { drand = gamma_dist_knuth(gamma, fileset->fs_meanwidth / gamma); ranwidth = drand; } else { ranwidth = fileset->fs_meanwidth; } if (randepth == 0) randepth = 1; if (ranwidth == 0) ranwidth = 1; if (depth >= randepth) isleaf = 1; /* * Create directory of random width according to distribution, or * if root directory, continue until #files required */ for (i = 1; ((parent == NULL) || (i < ranwidth + 1)) && (fileset->fs_realfiles < *(fileset->fs_entries)); i++) { int ret = 0; if (parent && isleaf) ret = fileset_populate_file(fileset, entry, i); else ret = fileset_populate_subdir(fileset, entry, i, depth); if (ret != 0) return (ret); } return (0); }
/* * Obtaines a filesetentry entity for a file to be placed in a * (sub)directory of a fileset. The size of the file may be * specified by fs_meansize, or calculated from a gamma * distribution of parameter fs_sizegamma and of mean size * fs_meansize. The filesetentry entity is placed on the file * list in the specified parent filesetentry entity, which may * be a directory filesetentry, or the root filesetentry in the * fileset. It is also placed on the fileset's list of all * contained files. Returns 0 if successful or -1 if ipc memory * for the path string cannot be allocated, or if a RAW device * cannot be located. */ static int fileset_populate_file(fileset_t *fileset, filesetentry_t *parent, char *path, int serial) { char tmpname[16]; filesetentry_t *entry; double drand; double gamma; struct stat64 sb; int fd; if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) == NULL) { filebench_log(LOG_ERROR, "fileset_populate_file: Can't malloc filesetentry"); return (-1); } (void) pthread_mutex_init(&entry->fse_lock, ipc_mutexattr()); entry->fse_parent = parent; entry->fse_fileset = fileset; entry->fse_flags |= FSE_FREE; /* RAW File name */ if (path) { /* check for raw device */ fd = open(path, O_RDONLY); if ((fstat64(fd, &sb) == 0) && ((sb.st_mode & S_IFMT) == S_IFBLK) && sb.st_rdev) { entry->fse_size = lseek64(fd, 0, SEEK_END); close(fd); fileset->fs_attrs |= FILESET_IS_RAW_DEV; filebench_log(LOG_INFO, "RAW device for %s on %s size %lld", fileset->fs_name, path, entry->fse_size); } else { filebench_log(LOG_ERROR, "fileset_populate_file: Cannot open RAW device %s", path); close(fd); return (-1); } entry->fse_flags &= FSE_FREE; entry->fse_flags |= FSE_EXISTS; if ((entry->fse_path = (char *)ipc_pathalloc(path)) == NULL) { filebench_log(LOG_ERROR, "fileset_populate_file: Can't alloc path string"); return (-1); } } else { (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); gamma = *(fileset->fs_sizegamma) / 1000.0; if (gamma > 0) { drand = gamma_dist_knuth(gamma, fileset->fs_meansize / gamma); entry->fse_size = (off64_t)drand; } else { entry->fse_size = (off64_t)fileset->fs_meansize; } if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { filebench_log(LOG_ERROR, "fileset_populate_file: Can't alloc path string"); return (-1); } } fileset_insfilelist(fileset, entry); fileset->fs_bytes += entry->fse_size; fileset->fs_realfiles++; return (0); }