static int builtin_posix_module_element_write_strided_nb (hio_element_t element, hio_request_t *request, off_t offset, const void *ptr, size_t count, size_t size, size_t stride) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); builtin_posix_module_t *posix_module = (builtin_posix_module_t *) posix_dataset->base.ds_module; hio_context_t context = hioi_object_context (&element->e_object); ssize_t bytes_written; hio_request_t new_request; pthread_mutex_lock (&posix_dataset->lock); bytes_written = builtin_posix_module_element_write_strided_internal (posix_module, element, offset, ptr, count, size, stride); pthread_mutex_unlock (&posix_dataset->lock); if (request) { new_request = hioi_request_alloc (context); if (NULL == new_request) { return HIO_ERR_OUT_OF_RESOURCE; } *request = new_request; new_request->req_transferred = bytes_written; new_request->req_complete = true; new_request->req_status = posix_dataset->base.ds_status; } return posix_dataset->base.ds_status; }
static int builtin_posix_module_element_flush (hio_element_t element, hio_flush_mode_t mode) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); if (!(posix_dataset->base.ds_flags & HIO_FLAG_WRITE)) { return HIO_ERR_PERM; } if (HIO_FILE_MODE_OPTIMIZED == posix_dataset->base.ds_fmode) { for (int i = 0 ; i < HIO_POSIX_MAX_OPEN_FILES ; ++i) { if (posix_dataset->files[i].f_file.f_hndl) { fflush (posix_dataset->files[i].f_file.f_hndl); if (HIO_FLUSH_MODE_COMPLETE == mode) { fsync (fileno (posix_dataset->files[i].f_file.f_hndl)); } } } } else { if (NULL != element->e_file.f_hndl) { fflush (element->e_file.f_hndl); if (HIO_FLUSH_MODE_COMPLETE == mode) { fsync (fileno (element->e_file.f_hndl)); } } } return HIO_SUCCESS; }
static int builtin_posix_element_translate_strided (builtin_posix_module_t *posix_module, hio_element_t element, uint64_t offset, size_t *size, hio_file_t **file_out) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); size_t block_id, block_base, block_bound, block_offset, file_id, file_block; hio_context_t context = hioi_object_context (&element->e_object); hio_file_t *file; int32_t file_index; char *path; int rc; block_id = offset / posix_dataset->ds_bs; file_id = block_id % posix_dataset->ds_fcount; file_block = block_id / posix_dataset->ds_fcount; block_base = block_id * posix_dataset->ds_bs; block_bound = block_base + posix_dataset->ds_bs; block_offset = file_block * posix_dataset->ds_bs + offset - block_base; hioi_log (context, HIO_VERBOSE_DEBUG_LOW, "builtin_posix_element_translate_strided: element: %s, offset: %" PRIu64 ", file_id: %lu, file_block: %lu, block_offset: %lu, block_size: %" PRIu64, hioi_object_identifier(element), offset, file_id, file_id, block_offset, posix_dataset->ds_bs); if (offset + *size > block_bound) { *size = block_bound - offset; } rc = asprintf (&path, "%s/data/%s_block.%08lu", posix_dataset->base_path, hioi_object_identifier(element), (unsigned long) file_id); if (0 > rc) { return HIO_ERR_OUT_OF_RESOURCE; } /* use crc as a hash to pick a file index to use */ file_index = file_id % HIO_POSIX_MAX_OPEN_FILES; file = posix_dataset->files + file_index; if (file_id != file->f_bid || file->f_element != element) { if (file->f_bid >= 0) { POSIX_TRACE_CALL(posix_dataset, hioi_file_close (file), "file_close", file->f_bid, 0); } file->f_bid = -1; file->f_element = element; POSIX_TRACE_CALL(posix_dataset, rc = builtin_posix_open_file (posix_module, posix_dataset, path, file), "file_open", file_id, 0); if (HIO_SUCCESS != rc) { return rc; } file->f_bid = file_id; } POSIX_TRACE_CALL(posix_dataset, hioi_file_seek (file, block_offset, SEEK_SET), "file_seek", file->f_bid, block_offset); *file_out = file; return HIO_SUCCESS; }
static int builtin_posix_module_element_complete (hio_element_t element) { hio_dataset_t dataset = hioi_element_dataset (element); /* reads in this module are always blocking. need to update this code if * that ever changes */ if (!(dataset->ds_flags & HIO_FLAG_READ)) { return HIO_ERR_PERM; } return HIO_SUCCESS; }
static int builtin_posix_element_translate (builtin_posix_module_t *posix_module, hio_element_t element, off_t offset, size_t *size, hio_file_t **file_out, bool reading) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); if (HIO_FILE_MODE_BASIC == posix_dataset->base.ds_fmode) { *file_out = &element->e_file; if (offset != element->e_file.f_offset) { fseek (element->e_file.f_hndl, offset, SEEK_SET); element->e_file.f_offset = offset; } return HIO_SUCCESS; } if (reading && 0 == element->e_scount) { return builtin_posix_element_translate_opt_old (posix_module, element, offset, size, file_out); } return builtin_posix_element_translate_opt (posix_module, element, offset, size, file_out, reading); }
static int builtin_posix_element_translate (builtin_posix_module_t *posix_module, hio_element_t element, uint64_t offset, size_t *size, hio_file_t **file_out, bool reading) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); int rc = HIO_SUCCESS; switch (posix_dataset->ds_fmode) { case HIO_FILE_MODE_BASIC: *file_out = &element->e_file; hioi_file_seek (&element->e_file, offset, SEEK_SET); break; case HIO_FILE_MODE_STRIDED: rc = builtin_posix_element_translate_strided (posix_module, element, offset, size, file_out); break; case HIO_FILE_MODE_OPTIMIZED: rc = builtin_posix_element_translate_opt (posix_module, element, offset, size, file_out, reading); break; } return rc; }
static int builtin_posix_module_element_read_strided_nb (hio_element_t element, hio_request_t *request, off_t offset, void *ptr, size_t count, size_t size, size_t stride) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); builtin_posix_module_t *posix_module = (builtin_posix_module_t *) posix_dataset->base.ds_module; hio_context_t context = hioi_object_context (&element->e_object); ssize_t bytes_read; hio_request_t new_request; int rc = HIO_SUCCESS; if (!(posix_dataset->base.ds_flags & HIO_FLAG_READ)) { return HIO_ERR_PERM; } if (stride == 0) { size *= count; count = 1; } hioi_object_lock (&posix_dataset->base.ds_object); bytes_read = builtin_posix_module_element_read_strided_internal (posix_module, element, offset, ptr, count, size, stride); hioi_object_unlock (&posix_dataset->base.ds_object); if (0 > bytes_read) { rc = (int) bytes_read; } /* see if a request was requested */ if (request) { new_request = hioi_request_alloc (context); if (NULL == new_request) { return HIO_ERR_OUT_OF_RESOURCE; } *request = new_request; new_request->req_transferred = bytes_read; new_request->req_complete = true; } return rc; }
static int builtin_posix_module_element_flush (hio_element_t element, hio_flush_mode_t mode) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); if (!(posix_dataset->base.ds_flags & HIO_FLAG_WRITE)) { return HIO_ERR_PERM; } if (HIO_FLUSH_MODE_COMPLETE != mode) { /* nothing to do at this time */ return HIO_SUCCESS; } if (HIO_FILE_MODE_BASIC != posix_dataset->ds_fmode) { for (int i = 0 ; i < HIO_POSIX_MAX_OPEN_FILES ; ++i) { hioi_file_flush (posix_dataset->files + i); } } else { hioi_file_flush (&element->e_file); } return HIO_SUCCESS; }
static ssize_t builtin_posix_module_element_read_strided_internal (builtin_posix_module_t *posix_module, hio_element_t element, off_t offset, void *ptr, size_t count, size_t size, size_t stride) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); size_t bytes_read = 0, ret; hio_file_t *file; uint64_t start, stop; int rc; if (!(count * size)) { return 0; } errno = 0; start = hioi_gettime (); for (size_t i = 0 ; i < count ; ++i) { size_t req = size, actual; do { actual = req; rc = builtin_posix_element_translate (posix_module, element, offset, &actual, &file, true); if (HIO_SUCCESS != rc) { break; } ret = fread (ptr, 1, actual, file->f_hndl); if (ret > 0) { bytes_read += ret; file->f_offset += ret; } if (ret < actual) { /* short read */ break; } req -= actual; offset += actual; ptr = (void *) ((intptr_t) ptr + actual); } while (req); if (req || HIO_SUCCESS != rc) { break; } ptr = (void *) ((intptr_t) ptr + stride); } if (0 == bytes_read || HIO_SUCCESS != rc) { if (0 == bytes_read) { rc = hioi_err_errno (errno); } return rc; } stop = hioi_gettime (); posix_dataset->base.ds_stat.s_rtime += stop - start; posix_dataset->base.ds_stat.s_bread += bytes_read; return bytes_read; }
static ssize_t builtin_posix_module_element_write_strided_internal (builtin_posix_module_t *posix_module, hio_element_t element, off_t offset, const void *ptr, size_t count, size_t size, size_t stride) { hio_dataset_t dataset = hioi_element_dataset (element); size_t bytes_written = 0, ret; hio_file_t *file; uint64_t stop, start; int rc; assert (dataset->ds_flags & HIO_FLAG_WRITE); if (!(count * size)) { return 0; } if (0 == stride) { size *= count; count = 1; } start = hioi_gettime (); errno = 0; for (size_t i = 0 ; i < count ; ++i) { size_t req = size, actual; do { actual = req; rc = builtin_posix_element_translate (posix_module, element, offset, &actual, &file, false); assert (file); if (HIO_SUCCESS != rc) { break; } ret = fwrite (ptr, 1, actual, file->f_hndl); if (ret > 0) { bytes_written += ret; file->f_offset += ret; } if (ret < actual) { /* short write */ break; } req -= actual; offset += actual; ptr = (void *) ((intptr_t) ptr + actual); } while (req); if (HIO_SUCCESS != rc || req) { break; } ptr = (void *) ((intptr_t) ptr + stride); } if (0 == bytes_written || HIO_SUCCESS != rc) { if (0 == bytes_written) { rc = hioi_err_errno (errno); } dataset->ds_status = rc; return rc; } if (offset + bytes_written > element->e_size) { element->e_size = offset + bytes_written; } stop = hioi_gettime (); dataset->ds_stat.s_wtime += stop - start; if (0 < bytes_written) { dataset->ds_stat.s_bwritten += bytes_written; } hioi_log (hioi_object_context (&element->e_object), HIO_VERBOSE_DEBUG_LOW, "posix: finished write. bytes written: " "%lu, time: %llu usec", bytes_written, stop - start); return bytes_written; }
static int builtin_posix_element_translate_opt (builtin_posix_module_t *posix_module, hio_element_t element, off_t offset, size_t *size, hio_file_t **file_out, bool reading) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); hio_context_t context = hioi_object_context (&element->e_object); builtin_posix_file_t *file; uint64_t file_offset; int file_index; char *path; int rc; hioi_log (context, HIO_VERBOSE_DEBUG_MED, "translating element %s offset %ld size %lu", hioi_object_identifier (&element->e_object), offset, *size); rc = hioi_element_translate_offset (element, offset, &file_index, &file_offset, size); if (HIO_SUCCESS != rc) { if (reading) { hioi_log (context, HIO_VERBOSE_DEBUG_MED, "offset not found"); /* not found */ return rc; } if (hioi_context_using_mpi (context)) { rc = asprintf (&path, "%s/data.%x", posix_dataset->base_path, posix_dataset->base.ds_shared_control->s_master); if (0 > rc) { return HIO_ERR_OUT_OF_RESOURCE; } } else { rc = asprintf (&path, "%s/data", posix_dataset->base_path); if (0 > rc) { return HIO_ERR_OUT_OF_RESOURCE; } } file_offset = builtin_posix_reserve (posix_dataset, size); file_index = hioi_dataset_add_file (&posix_dataset->base, strrchr (path, '/') + 1); hioi_element_add_segment (element, file_index, file_offset, offset, *size); } else { hioi_log (context, HIO_VERBOSE_DEBUG_MED, "offset found in file @ index %d, offset %lu, size %lu", file_index, file_offset, *size); rc = asprintf (&path, "%s/%s", posix_dataset->base_path, posix_dataset->base.ds_flist[file_index].f_name); if (0 > rc) { return HIO_ERR_OUT_OF_RESOURCE; } } /* use crc as a hash to pick a file index to use */ int internal_index = file_index % HIO_POSIX_MAX_OPEN_FILES; file = posix_dataset->files + internal_index; if (internal_index != file->f_bid) { if (NULL != file->f_file.f_hndl) { fclose (file->f_file.f_hndl); file->f_file.f_hndl = NULL; file->f_bid = -1; } rc = builtin_posix_open_file (posix_module, posix_dataset, path, &file->f_file); if (HIO_SUCCESS != rc) { free (path); return rc; } file->f_bid = file_index; } free (path); if (file_offset != file->f_file.f_offset) { fseek (file->f_file.f_hndl, file_offset, SEEK_SET); file->f_file.f_offset = file_offset; } *file_out = &file->f_file; return HIO_SUCCESS; }
static int builtin_posix_element_translate_opt_old (builtin_posix_module_t *posix_module, hio_element_t element, off_t offset, size_t *size, hio_file_t **file_out) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); hio_context_t context = hioi_object_context (&element->e_object); size_t block_id, block_base, block_bound, block_offset; builtin_posix_file_t *file; int32_t file_index; char *path; int rc, foo; block_id = offset / posix_dataset->base.ds_bs; block_base = block_id * posix_dataset->base.ds_bs; block_bound = block_base + posix_dataset->base.ds_bs; block_offset = offset - block_base; hioi_log (context, HIO_VERBOSE_DEBUG_LOW, "builtin_posix_element_translate: element: %s, offset: %lu, block_id: %lu, " "block_offset: %lu, block_size: %lu", hioi_object_identifier(element), (unsigned long) offset, block_id, block_offset, posix_dataset->base.ds_bs); if (offset + *size > block_bound) { *size = block_bound - offset; } rc = asprintf (&path, "%s_block.%lu", hioi_object_identifier(element), (unsigned long) block_id); if (0 > rc) { return HIO_ERR_OUT_OF_RESOURCE; } if (HIO_FLAG_WRITE & posix_dataset->base.ds_flags) { foo = hioi_dataset_add_file (&posix_dataset->base, path); } char *tmp = path; rc = asprintf (&path, "%s/%s", posix_dataset->base_path, tmp); free (tmp); if (0 > rc) { return HIO_ERR_OUT_OF_RESOURCE; } /* use crc as a hash to pick a file index to use */ file_index = hioi_crc32 ((uint8_t *) path, strlen (path)) % HIO_POSIX_MAX_OPEN_FILES; file = posix_dataset->files + file_index; if (block_id != file->f_bid || file->f_element != element) { if (file->f_file.f_hndl != NULL) { fclose (file->f_file.f_hndl); file->f_file.f_hndl = NULL; file->f_bid = -1; } file->f_element = element; rc = builtin_posix_open_file (posix_module, posix_dataset, path, &file->f_file); if (HIO_SUCCESS != rc) { return rc; } file->f_bid = block_id; } if (block_offset != file->f_file.f_offset) { fseek (file->f_file.f_hndl, block_offset, SEEK_SET); file->f_file.f_offset = block_offset; } if (HIO_FLAG_WRITE & posix_dataset->base.ds_flags) { hioi_element_add_segment (element, foo, block_offset, offset, *size); } *file_out = &file->f_file; return HIO_SUCCESS; }
static ssize_t builtin_posix_module_element_read_strided_internal (builtin_posix_module_t *posix_module, hio_element_t element, uint64_t offset, void *ptr, size_t count, size_t size, size_t stride) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); size_t bytes_read = 0, ret; hio_file_t *file; uint64_t start, stop; int rc; if (0 == count || 0 == size) { return 0; } errno = 0; start = hioi_gettime (); for (size_t i = 0 ; i < count ; ++i) { size_t req = size, actual; do { actual = req; /* find out where the data lives */ POSIX_TRACE_CALL(posix_dataset, rc = builtin_posix_element_translate (posix_module, element, offset, &actual, &file, true), "element_translate", offset, req); if (HIO_SUCCESS != rc) { break; } POSIX_TRACE_CALL(posix_dataset, ret = hioi_file_read (file, ptr, actual), "file_read", offset, actual); if (ret > 0) { bytes_read += ret; } if (ret < actual) { /* short read */ break; } req -= actual; offset += actual; ptr = (void *) ((intptr_t) ptr + actual); } while (req); if (req || HIO_SUCCESS != rc) { break; } ptr = (void *) ((intptr_t) ptr + stride); } if (0 == bytes_read || HIO_SUCCESS != rc) { if (0 == bytes_read && HIO_SUCCESS == rc) { rc = hioi_err_errno (errno); } return rc; } stop = hioi_gettime (); posix_dataset->base.ds_stat.s_rtime += stop - start; posix_dataset->base.ds_stat.s_bread += bytes_read; return bytes_read; }
static int builtin_posix_element_translate_opt (builtin_posix_module_t *posix_module, hio_element_t element, uint64_t offset, size_t *size, hio_file_t **file_out, bool reading) { builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element); hio_context_t context = hioi_object_context (&element->e_object); hio_file_t *file; uint64_t file_offset; int file_index = 0; char *path; int rc; hioi_log (context, HIO_VERBOSE_DEBUG_MED, "translating element %s offset %" PRIu64 " size %lu", hioi_object_identifier (&element->e_object), offset, *size); POSIX_TRACE_CALL(posix_dataset, rc = hioi_element_translate_offset (element, offset, &file_index, &file_offset, size), "translate_offset", offset, *size); #if HIO_MPI_HAVE(3) if (HIO_SUCCESS != rc && reading) { POSIX_TRACE_CALL(posix_dataset, rc = hioi_dataset_map_translate_offset (element, offset, &file_index, &file_offset, size), "map_translate_offset", offset, *size); } #endif if (HIO_SUCCESS != rc) { if (reading) { hioi_log (context, HIO_VERBOSE_DEBUG_MED, "offset %" PRIu64 " not found", offset); /* not found */ return rc; } file_offset = builtin_posix_reserve (posix_dataset, size); if (hioi_context_using_mpi (context)) { file_index = posix_dataset->base.ds_shared_control->s_master; } else { file_index = 0; } rc = asprintf (&path, "%s/data/data.%x", posix_dataset->base_path, file_index); if (0 > rc) { return HIO_ERR_OUT_OF_RESOURCE; } hioi_element_add_segment (element, file_index, file_offset, offset, *size); } else { hioi_log (context, HIO_VERBOSE_DEBUG_MED, "offset found in file @ rank %d, offset %" PRIu64 ", size %lu", file_index, file_offset, *size); rc = asprintf (&path, "%s/data/data.%x", posix_dataset->base_path, file_index); if (0 > rc) { return HIO_ERR_OUT_OF_RESOURCE; } if (access (path, R_OK)) { free (path); rc = asprintf (&path, "%s/data.%x", posix_dataset->base_path, file_index); if (0 > rc) { return HIO_ERR_OUT_OF_RESOURCE; } } } /* use crc as a hash to pick a file index to use */ int internal_index = file_index % HIO_POSIX_MAX_OPEN_FILES; file = posix_dataset->files + internal_index; if (file_index != file->f_bid) { if (file->f_bid >= 0) { POSIX_TRACE_CALL(posix_dataset, hioi_file_close (file), "file_close", file->f_bid, 0); } file->f_bid = -1; POSIX_TRACE_CALL(posix_dataset, rc = builtin_posix_open_file (posix_module, posix_dataset, path, file), "file_open", file_index, 0); if (HIO_SUCCESS != rc) { free (path); return rc; } file->f_bid = file_index; } free (path); POSIX_TRACE_CALL(posix_dataset, hioi_file_seek (file, file_offset, SEEK_SET), "file_seek", file->f_bid, file_offset); *file_out = file; return HIO_SUCCESS; }