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 MappedFileView::open(FileHandle* fh, off64_t offset,
00059 size_type size, ios::openmode mode)
00060 {
00061 size_ = size;
00062 if (!size)
00063 return true;
00064
00065 # ifdef _WIN32
00066 map_ = ::CreateFileMapping(fh->fd_, NULL,
00067 mode & ios::out ? PAGE_READWRITE : PAGE_READONLY,
00068 0, 0, NULL);
00069 if (!map_)
00070 return false;
00071
00072 off64_t aligned = offset & ~(PAGE_SIZE-1);
00073 off64_t delta = offset - aligned;
00074
00075 addr_ = ::MapViewOfFile(map_,
00076 mode & ios::out ? FILE_MAP_WRITE : FILE_MAP_READ,
00077 ((DWORD*)&aligned)[1], ((DWORD*)&aligned)[0],
00078 (SIZE_T)(size + ((SIZE_T*)&delta)[0]));
00079 if (!addr_)
00080 return false;
00081 # else
00082 int prot = PROT_NONE;
00083 if (mode & ios::in)
00084 prot |= PROT_READ;
00085 if (mode & ios::out)
00086 prot |= PROT_WRITE;
00087
00088
00089 off64_t aligned = offset & ~(PAGE_SIZE-1);
00090 off64_t delta = offset - aligned;
00091 addr_ = ::mmap(0, size_ + delta, prot, MAP_SHARED, fh->fd_, aligned);
00092 if (addr_ == MAP_FAILED) {
00093 addr_ = 0;
00094 return false;
00095 }
00096 # endif // _WIN32
00097 ptr_ = (char*)addr_ + delta;
00098 return true;
00099 }
00100
00101 void MappedFileView::close()
00102 {
00103 # ifdef _WIN32
00104 if (addr_)
00105 ::UnmapViewOfFile(addr_);
00106 if (map_)
00107 ::CloseHandle(map_);
00108 map_ = 0;
00109 # else
00110 if (addr_)
00111 ::munmap(static_cast<char *>(addr_), size_ + (char*)ptr_ - (char*)addr_);
00112 addr_ = 0;
00113 # endif
00114 }
00115
00116
00129
00130
00131 #ifdef RLIMIT_VMEM
00132 extern "C" void
00133 max_out_limits()
00134 {
00135 struct rlimit r;
00136 ::getrlimit(RLIMIT_VMEM, &r);
00137 r.rlim_cur = r.rlim_max;
00138 ::setrlimit(RLIMIT_VMEM, &r);
00139 }
00140 #endif
00141
00142
00148
00149
00150 void mappedFile::init()
00151 {
00152 #ifdef RLIMIT_VMEM
00153
00154
00155
00156
00157
00158 # ifdef MULTI_THREADED
00159 static pthread_once_t max_out = PTHREAD_ONCE_INIT;
00160 ::pthread_once(&max_out, max_out_limits);
00161 # else
00162 static bool maxed_out;
00163 if (!maxed_out)
00164 {
00165 max_out_limits();
00166 maxed_out = true;
00167 }
00168 # endif
00169 #endif
00170
00171 errno_ = 0;
00172 }
00173
00174
00183
00184
00185 bool mappedFile::open(char const *path, ios::openmode mode)
00186 {
00187 if (!fh_.open(path, mode))
00188 return false;
00189 off64_t size = size_ ? size_ : fh_.size();
00190 if (size == 0 && !(mode & ios::out))
00191
00192
00193 return false;
00194
00195 return ((MappedFileView*)this)->open(&fh_, 0, size, mode);
00196 }
00197
00198
00204
00205 bool
00206 mappedFile::remap(Size new_size, ios::openmode mode)
00207 {
00208 if (new_size > size_)
00209 if (!fh_.truncate(new_size))
00210 return false;
00211 if (size_) {
00212 # ifdef _GNU_SOURCE
00213 addr_ = (char*)::mremap(ptr_, size_, new_size, MREMAP_MAYMOVE);
00214 if (addr_ == MAP_FAILED)
00215 return false;
00216 # else
00217 ((MappedFileView*)this)->close();
00218 if (!((MappedFileView*)this)->open(&fh_, 0, new_size, mode))
00219 return false;
00220 # endif
00221 } else {
00222 if (!((MappedFileView*)this)->open(&fh_, 0, new_size, mode))
00223 return false;
00224 }
00225 size_ = new_size;
00226 ptr_ = addr_;
00227 return true;
00228 }
00229
00230
00235
00236 bool
00237 mappedFile::write(off64_t offset, void const* data, Size length)
00238 {
00239 return !fh_.write(offset, data, length);
00240 }
00241
00242
00251
00252
00253 void
00254 mappedFile::close()
00255 {
00256 ((MappedFileView*)this)->close();
00257 fh_.close();
00258 }
00259
00260 }
00261
00262 }