23
#include <sys/types.h>
26
#include <sys/statvfs.h>
20
#include <boost/cstdint.hpp>
23
#include "mongo/platform/basic.h"
24
#include "mongo/platform/cstdint.h"
33
28
typedef uint64_t fileofs;
35
typedef boost::uint64_t fileofs;
38
/* NOTE: not thread-safe. (at least the windows implementation isn't. */
30
// NOTE: not thread-safe. (at least the windows implementation isn't)
42
void open(const char *fn) {}
43
void write(fileofs o, const char *data, unsigned len) {}
44
void read(fileofs o, char *data, unsigned len) {}
45
bool bad() {return false;}
46
bool is_open() {return false;}
47
fileofs len() { return 0; }
48
void fsync() { verify(false); }
50
// shrink file to size bytes. No-op if file already smaller.
38
bool bad() const { return _bad; }
42
void open(const char* filename, bool readOnly = false, bool direct = false);
43
void read(fileofs o, char* data, unsigned len);
51
44
void truncate(fileofs size);
53
/** @return -1 if error or unavailable */
54
static boost::intmax_t freeSpace(const string &path) { verify(false); return -1; }
60
class File : public FileInterface {
64
void err(BOOL b=false) { /* false = error happened */
67
log() << "File " << _name << "I/O error " << GetLastError() << '\n';
72
fd = INVALID_HANDLE_VALUE;
76
if( is_open() ) CloseHandle(fd);
77
fd = INVALID_HANDLE_VALUE;
79
void open(const char *filename, bool readOnly=false , bool direct=false) {
82
toNativeString(filename).c_str(),
83
( readOnly ? 0 : GENERIC_WRITE ) | GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ,
84
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
86
DWORD e = GetLastError();
87
log() << "Create/Open File failed " << filename << ' ' << errnoWithDescription(e) << endl;
92
static boost::intmax_t freeSpace(const string &path) {
94
if( GetDiskFreeSpaceEx(toNativeString(path.c_str()).c_str(), &avail, NULL, NULL) ) {
95
return avail.QuadPart;
97
DWORD e = GetLastError();
98
log() << "GetDiskFreeSpaceEx fails errno: " << e << endl;
101
void write(fileofs o, const char *data, unsigned len) {
104
SetFilePointerEx(fd, li, NULL, FILE_BEGIN);
106
err( WriteFile(fd, data, len, &written, NULL) );
108
void read(fileofs o, char *data, unsigned len) {
112
SetFilePointerEx(fd, li, NULL, FILE_BEGIN);
113
int ok = ReadFile(fd, data, len, &read, 0);
117
massert( 10438 , "ReadFile error - truncated file?", read == len);
119
bool bad() { return _bad; }
120
bool is_open() { return fd != INVALID_HANDLE_VALUE; }
123
li.LowPart = GetFileSize(fd, (DWORD *) &li.HighPart);
124
if( li.HighPart == 0 && li.LowPart == INVALID_FILE_SIZE ) {
130
void fsync() { FlushFileBuffers(fd); }
132
void truncate(fileofs size) {
138
if (SetFilePointerEx(fd, li, NULL, FILE_BEGIN) == 0){
140
return; //couldn't seek
143
err(SetEndOfFile(fd));
149
class File : public FileInterface {
45
void write(fileofs o, const char* data, unsigned len);
47
static boost::intmax_t freeSpace(const std::string& path);
157
log() << "File I/O " << errnoWithDescription() << '\n';
166
if( is_open() ) ::close(fd);
174
void open(const char *filename, bool readOnly=false , bool direct=false) {
175
fd = ::open(filename,
176
O_CREAT | ( readOnly ? 0 : ( O_RDWR | O_NOATIME ) )
177
#if defined(O_DIRECT)
178
| ( direct ? O_DIRECT : 0 )
183
out() << "couldn't open " << filename << ' ' << errnoWithDescription() << endl;
188
void write(fileofs o, const char *data, unsigned len) {
189
err( ::pwrite(fd, data, len, o) == (int) len );
191
void read(fileofs o, char *data, unsigned len) {
192
ssize_t s = ::pread(fd, data, len, o);
196
else if( s != (int) len ) {
198
log() << "File error read:" << s << " bytes, wanted:" << len << " ofs:" << o << endl;
201
bool bad() { return _bad; }
202
bool is_open() { return fd > 0; }
204
off_t o = lseek(fd, 0, SEEK_END);
205
if( o != (off_t) -1 )
210
void fsync() { ::fsync(fd); }
211
static boost::intmax_t freeSpace ( const string &path ) {
213
verify( !statvfs( path.c_str() , &info ) );
214
return boost::intmax_t( info.f_bavail ) * info.f_frsize;
217
void truncate(fileofs size) {
221
err(ftruncate(fd, size) == 0);