MemoryMappedFile.h

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 2009 Soeren Sonnenburg
00008  * Copyright (C) 2009 Fraunhofer Institute FIRST and Max-Planck-Society
00009  */
00010 
00011 #ifndef __MEMORYMAPPEDFILE_H__
00012 #define __MEMORYMAPPEDFILE_H__
00013 
00014 #include "lib/io.h"
00015 #include "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 
00029 template <class T> class CMemoryMappedFile : public CSGObject
00030 {
00031     public:
00045         CMemoryMappedFile(const char* fname, char flag='r', uint64_t fsize=0)
00046         : CSGObject()
00047         {
00048             last_written_byte=0;
00049             rw=flag;
00050 
00051             int open_flags;
00052             int mmap_prot;
00053             int mmap_flags;
00054 
00055             if (rw=='w')
00056             {
00057                 open_flags=O_RDWR | O_CREAT;
00058                 mmap_prot=PROT_READ|PROT_WRITE;
00059                 mmap_flags=MAP_SHARED;
00060             }
00061             else if (rw=='r')
00062             {
00063                 open_flags=O_RDONLY;
00064                 mmap_prot=PROT_READ;
00065                 mmap_flags=MAP_PRIVATE;
00066             }
00067             else
00068                 SG_ERROR("Unknown flags\n");
00069 
00070             fd = open(fname, open_flags, S_IRWXU | S_IRWXG | S_IRWXO);
00071             if (fd == -1)
00072                 SG_ERROR("Error opening file\n");
00073 
00074             if (rw=='w' && fsize)
00075             {
00076                 uint8_t byte=0;
00077                 if (lseek(fd, fsize, SEEK_SET) != fsize || write(fd, &byte, 1) != 1)
00078                     SG_ERROR("Error creating file of size %ld bytes\n", fsize);
00079             }
00080 
00081             struct stat sb;
00082             if (fstat(fd, &sb) == -1)
00083                 SG_ERROR("Error determining file size\n");
00084 
00085             length = sb.st_size;
00086             address = mmap(NULL, length, mmap_prot, mmap_flags, fd, 0);
00087             if (address == MAP_FAILED)
00088                 SG_ERROR("Error mapping file");
00089         }
00090 
00092         virtual ~CMemoryMappedFile()
00093         {
00094             munmap(address, length);
00095             if (rw=='w' && last_written_byte && ftruncate(fd, last_written_byte) == -1)
00096 
00097             {
00098                 close(fd);
00099                 SG_ERROR("Error Truncating file to %ld bytes\n", last_written_byte);
00100             }
00101             close(fd);
00102         }
00103 
00113         inline T* get_map()
00114         {
00115             return (T*) address;
00116         }
00117 
00122         uint64_t get_length()
00123         {
00124             return length/sizeof(T);
00125         }
00126 
00131         uint64_t get_size()
00132         {
00133             return length;
00134         }
00135 
00147         char* get_line(uint64_t& len, uint64_t& offs)
00148         {
00149             char* s = (char*) address;
00150             for (uint64_t i=offs; i<length; i++)
00151             {
00152                 if (s[i] == '\n')
00153                 {
00154                     char* line=&s[offs];
00155                     len=i-offs;
00156                     offs=i+1;
00157                     return line;
00158                 }
00159             }
00160 
00161             len=0;
00162             offs=length;
00163             return NULL;
00164         }
00165 
00176         void write_line(const char* line, uint64_t len, uint64_t& offs)
00177         {
00178             char* s = ((char*) address) + offs;
00179             if (len+1+offs > length)
00180                 SG_ERROR("Writing beyond size of file\n");
00181 
00182             for (uint64_t i=0; i<len; i++)
00183                 s[i] = line[i];
00184 
00185             s[len]='\n';
00186             offs+=length+1;
00187             last_written_byte=offs-1;
00188         }
00200         inline void set_truncate_size(uint64_t* sz=0)
00201         {
00202             last_written_byte=sz;
00203         }
00204 
00209         int32_t get_num_lines()
00210         {
00211             char* s = (char*) address;
00212             int32_t linecount=0;
00213             for (uint64_t i=0; i<length; i++)
00214             {
00215                 if (s[i] == '\n')
00216                     linecount++;
00217             }
00218 
00219             return linecount;
00220         }
00221 
00229         inline T operator[](int32_t index) const
00230         {
00231             return ((T*)address)[index];
00232         }
00233 
00235         inline virtual const char* get_name() const { return "MemoryMappedFile"; }
00236 
00237     protected:
00239         int fd;
00241         uint64_t length;
00243         void* address;
00245         char rw;
00246 
00247         /* last_written_byte */
00248         uint64_t last_written_byte;
00249 };
00250 #endif
00251 

SHOGUN Machine Learning Toolbox - Documentation