00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "io/mappedFile.h"
00027
00028
00029 #include <cerrno>
00030 #include <algorithm>
00031 #ifdef __sun__
00032
00033 # define __PRAGMA_REDEFINE_EXTNAME
00034 #endif
00035 #include <fcntl.h>
00036 #ifndef _WIN32
00037 # include <ctime>
00038 # include <sys/mman.h>
00039 # include <sys/resource.h>
00040 # include <unistd.h>
00041 #endif
00042 #include <sys/stat.h>
00043 #if defined(MULTI_THREADED) && defined(RLIMIT_VMEM)
00044 # include <pthread.h>
00045 #endif
00046
00047
00048
00049
00050 using namespace std;
00051
00052 namespace IXE {
00053
00054 namespace io {
00055
00056
00057
00058 bool
00059 MappedFileView::open(FileHandle* fh, off64_t offset,
00060 size_type size, ios::openmode mode)
00061 {
00062 size_ = size;
00063 if (!size)
00064 return true;
00065
00066 # ifdef _WIN32
00067 map_ = ::CreateFileMapping(fh->fd_, NULL,
00068 mode & ios::out ? PAGE_READWRITE : PAGE_READONLY,
00069 0, 0, NULL);
00070 if (!map_)
00071 return false;
00072
00073 off64_t aligned = offset & ~(PAGE_SIZE-1);
00074 off64_t delta = offset - aligned;
00075
00076 addr_ = ::MapViewOfFile(map_,
00077 mode & ios::out ? FILE_MAP_WRITE : FILE_MAP_READ,
00078 ((DWORD*)&aligned)[1], ((DWORD*)&aligned)[0],
00079 (SIZE_T)(size + ((SIZE_T*)&delta)[0]));
00080 if (!addr_)
00081 return false;
00082 # else
00083 int prot = PROT_NONE;
00084 if (mode & ios::in)
00085 prot |= PROT_READ;
00086 if (mode & ios::out)
00087 prot |= PROT_WRITE;
00088
00089
00090 off64_t aligned = offset & ~(PAGE_SIZE-1);
00091 off64_t delta = offset - aligned;
00092 addr_ = ::mmap(0, size_ + delta, prot, MAP_SHARED, fh->fd_, aligned);
00093 if (addr_ == MAP_FAILED) {
00094 addr_ = 0;
00095 return false;
00096 }
00097 # endif // _WIN32
00098 ptr_ = (char*)addr_ + delta;
00099 return true;
00100 }
00101
00102 void
00103 MappedFileView::close()
00104 {
00105 # ifdef _WIN32
00106 if (addr_)
00107 ::UnmapViewOfFile(addr_);
00108 if (map_)
00109 ::CloseHandle(map_);
00110 map_ = 0;
00111 # else
00112 if (addr_)
00113 ::munmap(static_cast<char *>(addr_), size_ + (char*)ptr_ - (char*)addr_);
00114 addr_ = 0;
00115 # endif
00116 }
00117
00118
00131
00132
00133 #ifdef RLIMIT_VMEM
00134 extern "C" void
00135 max_out_limits()
00136 {
00137 struct rlimit r;
00138 ::getrlimit(RLIMIT_VMEM, &r);
00139 r.rlim_cur = r.rlim_max;
00140 ::setrlimit(RLIMIT_VMEM, &r);
00141 }
00142 #endif
00143
00144
00150
00151
00152 void
00153 mappedFile::init()
00154 {
00155 #ifdef RLIMIT_VMEM
00156
00157
00158
00159
00160
00161 # ifdef MULTI_THREADED
00162 static pthread_once_t max_out = PTHREAD_ONCE_INIT;
00163 ::pthread_once(&max_out, max_out_limits);
00164 # else
00165 static bool maxed_out;
00166 if (!maxed_out)
00167 {
00168 max_out_limits();
00169 maxed_out = true;
00170 }
00171 # endif
00172 #endif
00173
00174 errno_ = 0;
00175 }
00176
00177
00186
00187
00188 bool
00189 mappedFile::open(char const *path, ios::openmode mode)
00190 {
00191 if (!fh_.open(path, mode))
00192 return false;
00193 off64_t size = size_ ? size_ : fh_.size();
00194 if (size == 0 && !(mode & ios::out))
00195
00196
00197 return false;
00198
00199 return ((MappedFileView*)this)->open(&fh_, 0, size, mode);
00200 }
00201
00202
00208
00209 bool
00210 mappedFile::remap(Size new_size, ios::openmode mode)
00211 {
00212 if (new_size > size_)
00213 if (!fh_.truncate(new_size))
00214 return false;
00215 if (size_) {
00216 # ifdef _GNU_SOURCE
00217 addr_ = (char*)::mremap(ptr_, size_, new_size, MREMAP_MAYMOVE);
00218 if (addr_ == MAP_FAILED)
00219 return false;
00220 # else
00221 ((MappedFileView*)this)->close();
00222 if (!((MappedFileView*)this)->open(&fh_, 0, new_size, mode))
00223 return false;
00224 # endif
00225 } else {
00226 if (!((MappedFileView*)this)->open(&fh_, 0, new_size, mode))
00227 return false;
00228 }
00229 size_ = new_size;
00230 ptr_ = addr_;
00231 return true;
00232 }
00233
00234
00239
00240 bool
00241 mappedFile::write(off64_t offset, void const* data, Size length)
00242 {
00243 return !fh_.write(offset, data, length);
00244 }
00245
00246
00255
00256
00257 void
00258 mappedFile::close()
00259 {
00260 ((MappedFileView*)this)->close();
00261 fh_.close();
00262 }
00263
00264 }
00265
00266 }