int DCOPY_close_file(DCOPY_file_cache_t* cache) { int rc = 0; /* close file if we have one */ char* name = cache->name; if (name != NULL) { int fd = cache->fd; /* if open for write, fsync */ int read_flag = cache->read; if (! read_flag) { rc = mfu_fsync(name, fd); } /* close the file and delete the name string */ rc = mfu_close(name, fd); mfu_free(&cache->name); } return rc; }
/* write a chunk of the file */ static void write_file_chunk(mfu_file_chunk* p, const char* out_path) { size_t chunk_size = 1024*1024; uint64_t base = (off_t)p->offset; uint64_t file_size = (off_t)p->file_size; const char *in_path = p->name; uint64_t stripe_size = (off_t)p->length; /* if the file size is 0, there's no data to restripe */ /* if the stripe size is 0, then there's no work to be done */ if (file_size == 0 || stripe_size == 0) { return; } /* allocate buffer */ void* buf = MFU_MALLOC(chunk_size); /* open input file for reading */ int in_fd = mfu_open(in_path, O_RDONLY); if (in_fd < 0) { MFU_LOG(MFU_LOG_ERR, "Failed to open input file %s (%s)", in_path, strerror(errno)); MPI_Abort(MPI_COMM_WORLD, 1); } /* open output file for writing */ int out_fd = mfu_open(out_path, O_WRONLY); if (out_fd < 0) { MFU_LOG(MFU_LOG_ERR, "Failed to open output file %s (%s)", out_path, strerror(errno)); MPI_Abort(MPI_COMM_WORLD, 1); } /* write data */ uint64_t chunk_id = 0; uint64_t stripe_read = 0; while (stripe_read < stripe_size) { /* determine number of bytes to read */ /* try to read a full chunk's worth of bytes */ size_t read_size = chunk_size; /* if the stripe doesn't have that much left */ uint64_t remainder = stripe_size - stripe_read; if (remainder < (uint64_t) read_size) { read_size = (size_t) remainder; } /* get byte offset to read from */ uint64_t offset = base + (chunk_id * chunk_size); if (offset < file_size) { /* the first byte falls within the file size, * now check the last byte */ uint64_t last = offset + (uint64_t) read_size; if (last > file_size) { /* the last byte is beyond the end, set read size * to the most we can read */ read_size = (size_t) (file_size - offset); } } else { /* the first byte we need to read is past the end of * the file, so don't read anything */ read_size = 0; } /* bail if we don't have anything to read */ if (read_size == 0) { break; } /* seek to correct spot in input file */ off_t pos = (off_t) offset; off_t seek_rc = mfu_lseek(in_path, in_fd, pos, SEEK_SET); if (seek_rc == (off_t)-1) { MFU_LOG(MFU_LOG_ERR, "Failed to seek in input file %s (%s)", in_path, strerror(errno)); MPI_Abort(MPI_COMM_WORLD, 1); } /* read chunk from input */ ssize_t nread = mfu_read(in_path, in_fd, buf, read_size); /* check for errors */ if (nread < 0) { MFU_LOG(MFU_LOG_ERR, "Failed to read data from input file %s (%s)", in_path, strerror(errno)); MPI_Abort(MPI_COMM_WORLD, 1); } /* check for short reads */ if (nread != read_size) { MFU_LOG(MFU_LOG_ERR, "Got a short read from input file %s", in_path); MPI_Abort(MPI_COMM_WORLD, 1); } /* seek to correct spot in output file */ seek_rc = mfu_lseek(out_path, out_fd, pos, SEEK_SET); if (seek_rc == (off_t)-1) { MFU_LOG(MFU_LOG_ERR, "Failed to seek in output file %s (%s)", out_path, strerror(errno)); MPI_Abort(MPI_COMM_WORLD, 1); } /* write chunk to output */ ssize_t nwrite = mfu_write(out_path, out_fd, buf, read_size); /* check for errors */ if (nwrite < 0) { MFU_LOG(MFU_LOG_ERR, "Failed to write data to output file %s (%s)", out_path, strerror(errno)); MPI_Abort(MPI_COMM_WORLD, 1); } /* check for short reads */ if (nwrite != read_size) { MFU_LOG(MFU_LOG_ERR, "Got a short write to output file %s", out_path); MPI_Abort(MPI_COMM_WORLD, 1); } /* update our byte count for progress messages */ stripe_prog_bytes += read_size; mfu_progress_update(&stripe_prog_bytes, stripe_prog); /* go on to the next chunk in this stripe, we assume we * read the whole chunk size, if we didn't it's because * the stripe is smaller or we're at the end of the file, * but in either case we're done so it doesn't hurt to * over estimate in this calculation */ stripe_read += (uint64_t) chunk_size; chunk_id++; } /* close files */ mfu_fsync(out_path, out_fd); mfu_close(out_path, out_fd); mfu_close(in_path, in_fd); /* free buffer */ mfu_free(&buf); }