2
* Copyright (C) 2009-2010 Codership Oy <info@codership.com>
6
#include "gcache_fd.hpp"
8
#include <galerautils.hpp>
11
#define _XOPEN_SOURCE 600
15
#include <sys/types.h>
20
#ifndef O_CLOEXEC // CentOS does not have it
26
static const int OPEN_FLAGS = O_RDWR | O_NOATIME | O_CLOEXEC;
27
static const int CREATE_FLAGS = OPEN_FLAGS | O_CREAT | O_TRUNC;
29
FileDescriptor::FileDescriptor (const std::string& fname,
32
: value (open (fname.c_str(), OPEN_FLAGS, S_IRUSR | S_IWUSR)),
34
size (lseek (value, 0, SEEK_END)),
40
FileDescriptor::FileDescriptor (const std::string& fname,
45
: value (open (fname.c_str(), CREATE_FLAGS, S_IRUSR | S_IWUSR)),
54
prealloc (); // reserve space
58
write_byte (size - 1); // reserve size
63
FileDescriptor::constructor_common() throw (gu::Exception)
66
gu_throw_error(errno) << "Failed to open file '" + name + '\'';
68
/* benefits are questionable
69
int err(posix_fadvise (value, 0, size, POSIX_FADV_SEQUENTIAL));
73
log_warn << "Failed to set POSIX_FADV_SEQUENTIAL on "
74
<< name << ": " << err << " (" << strerror(err) << ")";
77
log_debug << "Opened file '" << name << "'";
78
log_debug << "File descriptor: " << value;
81
FileDescriptor::~FileDescriptor ()
83
if (sync && fsync(value) != 0)
85
int const err (errno);
86
log_error << "Failed to flush file '" << name << "': "
87
<< gu::to_string(err) << " (" << strerror(err) << '\'';
90
if (close(value) != 0)
92
int const err (errno);
93
log_error << "Failed to close file '" << name << "': "
94
<< gu::to_string(err) << " (" << strerror(err) << '\'';
98
log_debug << "Closed file '" << name << "'";
103
FileDescriptor::flush () const throw (gu::Exception)
105
log_debug << "Flushing file '" << name << "'";
107
if (fsync (value) < 0) {
108
gu_throw_error(errno) << "fsync() failed on '" + name + '\'';
111
log_debug << "Flushed file '" << name << "'";
115
FileDescriptor::write_byte (ssize_t offset) throw (gu::Exception)
117
unsigned char const byte (0);
119
if (lseek (value, offset, SEEK_SET) != offset)
120
gu_throw_error(errno) << "lseek() failed on '" << name << '\'';
122
if (write (value, &byte, sizeof(byte)) != sizeof(byte))
123
gu_throw_error(errno) << "write() failed on '" << name << '\'';
130
FileDescriptor::prealloc() throw (gu::Exception)
132
size_t const page_size = sysconf (_SC_PAGE_SIZE);
134
size_t offset = page_size - 1; // last byte of the page
136
log_info << "Preallocating " << size << " bytes in '" << name
139
while (offset < size && write_byte (offset))
144
if (offset > size && write_byte (size - 1) && fsync (value) == 0) {
145
log_info << "Preallocating " << size << " bytes in '" << name
150
gu_throw_error (errno) << "File preallocation failed";
154
FileDescriptor::prealloc() throw (gu::Exception)
156
log_info << "Preallocating " << size << " bytes in '" << name
159
if (0 != posix_fallocate (value, 0, size))
161
gu_throw_error (errno) << "File preallocation failed";