susumu.yata
null+****@clear*****
Tue Feb 26 16:39:38 JST 2013
susumu.yata 2013-02-26 16:39:38 +0900 (Tue, 26 Feb 2013) New Revision: 37739fb8a33451c200d9b8200332427c8556f011 https://github.com/groonga/grnxx/commit/37739fb8a33451c200d9b8200332427c8556f011 Log: Update the interface of grnxx::io::File. resize() does not change the file offset on success. read/write() with "offset" may change the file offset on failure. Modified files: lib/io/file-posix.cpp lib/io/file-windows.cpp lib/io/file.hpp test/test_io_file.cpp Modified: lib/io/file-posix.cpp (+8 -21) =================================================================== --- lib/io/file-posix.cpp 2013-02-25 22:52:41 +0900 (ffaaedb) +++ lib/io/file-posix.cpp 2013-02-26 16:39:38 +0900 (1e34657) @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Brazil, Inc. + Copyright (C) 2012-2013 Brazil, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -175,9 +175,8 @@ bool FileImpl::unlock() { return true; } -// TODO: These should be constexpr. -const uint64_t FILE_IMPL_MAX_OFFSET = std::numeric_limits<off_t>::max(); -const uint64_t FILE_IMPL_MAX_SIZE = std::numeric_limits<ssize_t>::max(); +constexpr uint64_t FILE_IMPL_MAX_OFFSET = std::numeric_limits<off_t>::max(); +constexpr uint64_t FILE_IMPL_MAX_SIZE = std::numeric_limits<ssize_t>::max(); uint64_t FileImpl::read(void *buf, uint64_t size) { if (flags_ & FILE_WRITE_ONLY) { @@ -207,6 +206,7 @@ uint64_t FileImpl::read(void *buf, uint64_t size, uint64_t offset) { << ", max_offset = " << FILE_IMPL_MAX_OFFSET; GRNXX_THROW(); } + const size_t chunk_size = static_cast<size_t>(std::min(size, FILE_IMPL_MAX_SIZE)); #ifdef GRNXX_HAS_PREAD @@ -218,16 +218,10 @@ uint64_t FileImpl::read(void *buf, uint64_t size, uint64_t offset) { << ": '::pwrite' " << Error(errno); } #else // GRNXX_HAS_PREAD - // TODO: To be thread-safe and error-tolerant. + // The resulting file offset is not defined on failure. const uint64_t current_position = tell(); seek(offset, SEEK_SET); - uint64_t result; - try { - result = read(buf, chunk_size); - } catch (...) { - seek(current_position, SEEK_SET); - throw; - } + const uint64_t result = read(buf, chunk_size); seek(current_position, SEEK_SET); #endif // GRNXX_HAS_PREAD return result; @@ -272,16 +266,10 @@ uint64_t FileImpl::write(const void *buf, uint64_t size, uint64_t offset) { << ": '::pwrite' " << Error(errno); } #else // GRNXX_HAS_PWRITE - // TODO: To be thread-safe and error-tolerant. + // The resulting file offset is not defined on failure. const uint64_t current_position = tell(); seek(offset, SEEK_SET); - uint64_t result; - try { - result = write(buf, chunk_size); - } catch (...) { - seek(current_position, SEEK_SET); - throw; - } + const uint64_t result = write(buf, chunk_size); seek(current_position, SEEK_SET); #endif // GRNXX_HAS_PWRITE return result; @@ -348,7 +336,6 @@ void FileImpl::resize(uint64_t size) { << ": [0, " << MAX_SIZE << ']'; GRNXX_THROW(); } - seek(static_cast<int64_t>(size), SEEK_SET); if (::ftruncate(fd_, size) != 0) { GRNXX_ERROR() << "failed to resize file: file = " << *this Modified: lib/io/file-windows.cpp (+7 -17) =================================================================== --- lib/io/file-windows.cpp 2013-02-25 22:52:41 +0900 (31c003a) +++ lib/io/file-windows.cpp 2013-02-26 16:39:38 +0900 (c40a85a) @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Brazil, Inc. + Copyright (C) 2012-2013 Brazil, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -207,16 +207,10 @@ uint64_t FileImpl::read(void *buf, uint64_t size, uint64_t offset) { GRNXX_THROW(); } - // TODO: must be thread-safe. + // The resulting file offset is not defined on failure. const uint64_t current_position = seek(0, SEEK_CUR); seek(offset, SEEK_SET); - uint64_t result; - try { - result = read(buf, size); - } catch (...) { - seek(current_position, SEEK_SET); - throw; - } + const uint64_t result = read(buf, size); seek(current_position, SEEK_SET); return result; } @@ -254,16 +248,10 @@ uint64_t FileImpl::write(const void *buf, uint64_t size, uint64_t offset) { GRNXX_THROW(); } - // TODO: must be thread-safe. + // The resulting file offset is not defined on failure. const uint64_t current_position = seek(0, SEEK_CUR); seek(offset, SEEK_SET); - uint64_t result; - try { - result = write(buf, size); - } catch (...) { - seek(current_position, SEEK_SET); - throw; - } + const uint64_t result = write(buf, size); seek(current_position, SEEK_SET); return result; } @@ -327,6 +315,7 @@ void FileImpl::resize(uint64_t size) { GRNXX_THROW(); } + const uint64_t offset = tell(); seek(size, SEEK_SET); if (!::SetEndOfFile(handle_)) { GRNXX_ERROR() << "failed to resize file: file = " << *this @@ -334,6 +323,7 @@ void FileImpl::resize(uint64_t size) { << ": '::SetEndOfFile' " << Error(::GetLastError()); GRNXX_THROW(); } + seek(offset, SEEK_SET); } uint64_t FileImpl::size() const { Modified: lib/io/file.hpp (+37 -13) =================================================================== --- lib/io/file.hpp 2013-02-25 22:52:41 +0900 (588a439) +++ lib/io/file.hpp 2013-02-26 16:39:38 +0900 (afae480) @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Brazil, Inc. + Copyright (C) 2012-2013 Brazil, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -71,11 +71,15 @@ class File { File(); virtual ~File(); + // Create or open a file. static File *open(FileFlags flags, const char *path = nullptr, int permission = 0644); + // Return true iff "path" refers to a regular file. static bool exists(const char *path); + // Remove a file. static void unlink(const char *path); + // Remove a file and return true on success. static bool unlink_if_exists(const char *path); // The following functions operate advisory locks for files, not for @@ -90,38 +94,58 @@ class File { // unlock() returns false if the file is not locked. virtual bool unlock() = 0; - // The following functions are not thread-safe. + // Note: The following operations are not thread-safe. In practice, it is + // possible to make these operations thread-safe. However, a file might be + // accessed via multiple objects or processes. It is difficult to cover all + // the possible cases. - // read() reads data from file at most size bytes and returns the number of - // actually read bytes. + // Read up to "size" bytes from the file into the buffer starting at "buf" + // and return the number of bytes read. virtual uint64_t read(void *buf, uint64_t size) = 0; + // Read up to "size" bytes from the file at offset "offset" into the buffer + // starting at "buf" and return the number of bytes read. + // The file offset is not changed on success but not defined on failure. virtual uint64_t read(void *buf, uint64_t size, uint64_t offset) = 0; - // write() writes data into file at most size bytes and returns the number - // of actually written bytes. + + // Write "size" bytes from the buffer starting at "buf" to the file and + // return the number of bytes written. virtual uint64_t write(const void *buf, uint64_t size) = 0; + // Write "size" bytes from the buffer starting at "buf" to the file at + // offset "offset" and return the number of bytes written. + // The file offset is not changed on success but not defined on failure. virtual uint64_t write(const void *buf, uint64_t size, uint64_t offset) = 0; + // Flush modified pages. virtual void sync() = 0; - // seek() moves the file pointer and returns the new position. + // Move the file offset and return the new offset. + // "whence" must be SEEK_SET, SEEK_CUR, or SEEK_END as follows: + // - SEEK_SET: "offset" is relative to the start of the file. + // - SEEK_CUR: "offset" is relative to the current offset. + // - SEEK_END: "offset" is relative to the end of the file. virtual uint64_t seek(int64_t offset, int whence = SEEK_SET) = 0; - // tell() returns the current position. + // Return the current offset. virtual uint64_t tell() const = 0; - // resize() resizes the file and moves the file pointer to the new - // end-of-file. + // Extend or truncate a file to "size" bytes. + // The file offset is not changed on success but not defined on failure. + // Note that the contents of the extended part are not defined. virtual void resize(uint64_t size) = 0; - // size() returns the file size in bytes. + // Return the file size. virtual uint64_t size() const = 0; - // If true, the associated path will be unlinked after closing the file - // handle. + // Return the unlink-at-close flag. + // If the flag is true, the file will be unlinked immediately after close. virtual bool unlink_at_close() const = 0; + // Modify the unlink-at-close flag to "value". virtual void set_unlink_at_close(bool value) = 0; + // Return the file path. virtual String path() const = 0; + // Return enabled file flags. virtual FileFlags flags() const = 0; + // Return a pointer to the file handle virtual const void *handle() const = 0; virtual StringBuilder &write_to(StringBuilder &builder) const = 0; Modified: test/test_io_file.cpp (+1 -1) =================================================================== --- test/test_io_file.cpp 2013-02-25 22:52:41 +0900 (59dab38) +++ test/test_io_file.cpp 2013-02-26 16:39:38 +0900 (1671ea8) @@ -97,7 +97,7 @@ void test_resize() { grnxx::io::File::open(grnxx::io::FILE_CREATE, FILE_PATH)); file->resize(FILE_SIZE); - assert(file->tell() == FILE_SIZE); + assert(file->tell() == 0); assert(file->size() == FILE_SIZE); file->resize(0); -------------- next part -------------- HTML����������������������������...Download