Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __MEMORYMAPPEDFILE_H__
00012 #define __MEMORYMAPPEDFILE_H__
00013
00014 #include <shogun/io/SGIO.h>
00015 #include <shogun/base/SGObject.h>
00016
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <sys/mman.h>
00020 #include <sys/stat.h>
00021 #include <sys/types.h>
00022 #include <fcntl.h>
00023 #include <unistd.h>
00024
00025 namespace shogun
00026 {
00031 template <class T> class CMemoryMappedFile : public CSGObject
00032 {
00033 public:
00035 CMemoryMappedFile() :CSGObject()
00036 {
00037 SG_UNSTABLE("CMemoryMappedFile::CMemoryMappedFile()",
00038 "\n");
00039
00040 fd = 0;
00041 length = 0;
00042 address = NULL;
00043 rw = 'r';
00044 last_written_byte = 0;
00045 }
00046
00060 CMemoryMappedFile(const char* fname, char flag='r', int64_t fsize=0)
00061 : CSGObject()
00062 {
00063 last_written_byte=0;
00064 rw=flag;
00065
00066 int open_flags;
00067 int mmap_prot;
00068 int mmap_flags;
00069
00070 if (rw=='w')
00071 {
00072 open_flags=O_RDWR | O_CREAT;
00073 mmap_prot=PROT_READ|PROT_WRITE;
00074 mmap_flags=MAP_SHARED;
00075 }
00076 else if (rw=='r')
00077 {
00078 open_flags=O_RDONLY;
00079 mmap_prot=PROT_READ;
00080 mmap_flags=MAP_PRIVATE;
00081 }
00082 else
00083 SG_ERROR("Unknown flags\n");
00084
00085 fd = open(fname, open_flags, S_IRWXU | S_IRWXG | S_IRWXO);
00086 if (fd == -1)
00087 SG_ERROR("Error opening file\n");
00088
00089 if (rw=='w' && fsize)
00090 {
00091 uint8_t byte=0;
00092 if (lseek(fd, fsize, SEEK_SET) != fsize || write(fd, &byte, 1) != 1)
00093 SG_ERROR("Error creating file of size %ld bytes\n", fsize);
00094 }
00095
00096 struct stat sb;
00097 if (fstat(fd, &sb) == -1)
00098 SG_ERROR("Error determining file size\n");
00099
00100 length = sb.st_size;
00101 address = mmap(NULL, length, mmap_prot, mmap_flags, fd, 0);
00102 if (address == MAP_FAILED)
00103 SG_ERROR("Error mapping file");
00104 }
00105
00107 virtual ~CMemoryMappedFile()
00108 {
00109 munmap(address, length);
00110 if (rw=='w' && last_written_byte && ftruncate(fd, last_written_byte) == -1)
00111
00112 {
00113 close(fd);
00114 SG_ERROR("Error Truncating file to %ld bytes\n", last_written_byte);
00115 }
00116 close(fd);
00117 }
00118
00128 inline T* get_map()
00129 {
00130 return (T*) address;
00131 }
00132
00137 uint64_t get_length()
00138 {
00139 return length/sizeof(T);
00140 }
00141
00146 uint64_t get_size()
00147 {
00148 return length;
00149 }
00150
00162 char* get_line(uint64_t& len, uint64_t& offs)
00163 {
00164 char* s = (char*) address;
00165 for (uint64_t i=offs; i<length; i++)
00166 {
00167 if (s[i] == '\n')
00168 {
00169 char* line=&s[offs];
00170 len=i-offs;
00171 offs=i+1;
00172 return line;
00173 }
00174 }
00175
00176 len=0;
00177 offs=length;
00178 return NULL;
00179 }
00180
00191 void write_line(const char* line, uint64_t len, uint64_t& offs)
00192 {
00193 char* s = ((char*) address) + offs;
00194 if (len+1+offs > length)
00195 SG_ERROR("Writing beyond size of file\n");
00196
00197 for (uint64_t i=0; i<len; i++)
00198 s[i] = line[i];
00199
00200 s[len]='\n';
00201 offs+=length+1;
00202 last_written_byte=offs-1;
00203 }
00204
00216 inline void set_truncate_size(uint64_t sz=0)
00217 {
00218 last_written_byte=sz;
00219 }
00220
00225 int32_t get_num_lines()
00226 {
00227 char* s = (char*) address;
00228 int32_t linecount=0;
00229 for (uint64_t i=0; i<length; i++)
00230 {
00231 if (s[i] == '\n')
00232 linecount++;
00233 }
00234
00235 return linecount;
00236 }
00237
00245 inline T operator[](uint64_t index) const
00246 {
00247 return ((T*)address)[index];
00248 }
00249
00257 inline T operator[](int32_t index) const
00258 {
00259 return ((T*)address)[index];
00260 }
00261
00263 inline virtual const char* get_name() const { return "MemoryMappedFile"; }
00264
00265 protected:
00267 int fd;
00269 uint64_t length;
00271 void* address;
00273 char rw;
00274
00276 uint64_t last_written_byte;
00277 };
00278 }
00279 #endif