CernVM-FS  2.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mmap_file.cc
Go to the documentation of this file.
1 
7 #ifndef __STDC_FORMAT_MACROS
8 #define __STDC_FORMAT_MACROS
9 #endif
10 
11 #include "cvmfs_config.h"
12 #include "mmap_file.h"
13 
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <sys/mman.h>
17 #include <unistd.h>
18 
19 #include <cassert>
20 
21 #include "logging.h"
22 #include "platform.h"
23 
24 using namespace std; // NOLINT
25 
26 #ifdef CVMFS_NAMESPACE_GUARD
27 namespace CVMFS_NAMESPACE_GUARD {
28 #endif
29 
30 
31 MemoryMappedFile::MemoryMappedFile(const std::string &file_path) :
32  file_path_(file_path),
33  file_descriptor_(-1),
34  mapped_file_(NULL),
35  mapped_size_(0),
36  mapped_(false) {}
37 
39  if (IsMapped()) {
40  Unmap();
41  }
42 }
43 
45  assert(!mapped_);
46 
47  // open the file
48  int fd;
49  if ((fd = open(file_path_.c_str(), O_RDONLY, 0)) == -1) {
50  LogCvmfs(kLogUtility, kLogStderr, "failed to open %s (%d)",
51  file_path_.c_str(), errno);
52  return false;
53  }
54 
55  // get file size
56  platform_stat64 filesize;
57  if (platform_fstat(fd, &filesize) != 0) {
58  LogCvmfs(kLogUtility, kLogStderr, "failed to fstat %s (%d)",
59  file_path_.c_str(), errno);
60  close(fd);
61  return false;
62  }
63 
64  // check if the file is empty and 'pretend' that the file is mapped
65  // --> buffer will then look like a buffer without any size...
66  void *mapping = NULL;
67  if (filesize.st_size > 0) {
68  // map the given file into memory
69  mapping = mmap(NULL, filesize.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
70  if (mapping == MAP_FAILED) {
71  LogCvmfs(kLogUtility, kLogStderr, "failed to mmap %s (file size: %d) "
72  "(errno: %d)",
73  file_path_.c_str(),
74  filesize.st_size,
75  errno);
76  close(fd);
77  return false;
78  }
79  }
80 
81  // save results
82  mapped_file_ = static_cast<unsigned char*>(mapping);
83  file_descriptor_ = fd;
84  mapped_size_ = filesize.st_size;
85  mapped_ = true;
86  LogCvmfs(kLogUtility, kLogVerboseMsg, "mmap'ed %s", file_path_.c_str());
87  return true;
88 }
89 
91  assert(mapped_);
92 
93  if (mapped_file_ == NULL) {
94  return;
95  }
96 
97  // unmap the previously mapped file
98  if ((munmap(static_cast<void*>(mapped_file_), mapped_size_) != 0) ||
99  (close(file_descriptor_) != 0))
100  {
101  LogCvmfs(kLogUtility, kLogStderr, "failed to unmap %s", file_path_.c_str());
102  const bool munmap_failed = false;
103  assert(munmap_failed);
104  }
105 
106  // reset (resettable) data
107  mapped_file_ = NULL;
108  file_descriptor_ = -1;
109  mapped_size_ = 0;
110  mapped_ = false;
111  LogCvmfs(kLogUtility, kLogVerboseMsg, "munmap'ed %s", file_path_.c_str());
112 }
113 
114 #ifdef CVMFS_NAMESPACE_GUARD
115 } // namespace CVMFS_NAMESPACE_GUARD
116 #endif
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
MemoryMappedFile(const std::string &file_path)
Definition: mmap_file.cc:31
struct stat64 platform_stat64
unsigned char * mapped_file_
Definition: mmap_file.h:40
assert((mem||(size==0))&&"Out Of Memory")
const std::string file_path_
Definition: mmap_file.h:38
size_t mapped_size_
Definition: mmap_file.h:41
bool IsMapped() const
Definition: mmap_file.h:35
int file_descriptor_
Definition: mmap_file.h:39
const int kLogVerboseMsg
int platform_fstat(int filedes, platform_stat64 *buf)