Line data Source code
1 : /*
2 : * MapFile.cxx
3 : * ers
4 : *
5 : * Created by Matthias Wiesmann on 07.01.05.
6 : * Copyright 2005 CERN. All rights reserved.
7 : *
8 : */
9 :
10 : #include <sys/types.h>
11 : #include <sys/mman.h>
12 : #include <iostream>
13 : #include <unistd.h>
14 :
15 :
16 : #include "okssystem/Descriptor.hpp"
17 : #include "okssystem/MapFile.hpp"
18 : #include "okssystem/exceptions.hpp"
19 :
20 : #include "ers/Assertion.hpp"
21 :
22 : /** Builds a memory mapped file.
23 : * \param name the path of the file to map.
24 : * \param size the size of the region to memory map - should be a multiple of the pagesize.
25 : * \param offset the offset in the file - should be a multiple of pagesize.
26 : * \param read_mode should the map be read from the file.
27 : * \param write_mode should the map be writable.
28 : * \param permissions the permissions associated with the file
29 : */
30 :
31 0 : OksSystem::MapFile::MapFile(const std::string &name, size_t s, size_t o, bool read_mode, bool write_mode, mode_t perm) : File(name) {
32 0 : ERS_PRECONDITION((read_mode || write_mode));
33 0 : const int page_size = getpagesize();
34 0 : ERS_PRECONDITION((s % page_size)==0);
35 0 : ERS_PRECONDITION((o % page_size)==0);
36 0 : (void) page_size;// to suppress warning when asserts are disabled
37 0 : m_map_read = read_mode;
38 0 : m_map_write = write_mode;
39 0 : m_map_permission = perm;
40 0 : m_map_size = s;
41 0 : m_map_offset = o;
42 0 : m_map_address = 0;
43 0 : m_map_descriptor = 0;
44 0 : m_is_mapped = false;
45 0 : } // MapFile
46 :
47 : /** Destructor - the file should be unmapped before destruction.
48 : */
49 :
50 0 : OksSystem::MapFile::~MapFile() {
51 0 : if (m_map_descriptor!=0) {
52 0 : close_fd();
53 : } // file descriptor open
54 0 : } // ~MapFile
55 :
56 : /** Opens the file descriptor associated with the memory map.
57 : * \exception OpenFail if the \c open okssystem call fails
58 : */
59 :
60 0 : void OksSystem::MapFile::open_fd() {
61 0 : const int flags = OksSystem::Descriptor::flags(m_map_read,m_map_write);
62 0 : m_map_descriptor = new OksSystem::Descriptor(this, flags,m_map_permission);
63 0 : } // open_fd
64 :
65 :
66 : /** Closes the file descriptor associated with the memory map.
67 : * \exception CloseFail if the \c close okssystem call fails
68 : */
69 :
70 0 : void OksSystem::MapFile::close_fd() {
71 0 : m_map_descriptor->close();
72 0 : delete(m_map_descriptor);
73 0 : m_map_descriptor = 0;
74 0 : } // close_fd
75 :
76 : /** Internal method - does the actual memory mapping.
77 : * \exception MMapFail if the \c mmap operation succeeded
78 : * \exception Precondition if the file descriptor is not valid.
79 : */
80 :
81 0 : void OksSystem::MapFile::map_mem() {
82 0 : ERS_PRECONDITION(m_map_descriptor);
83 0 : int prot = 0;
84 0 : int flags = MAP_FILE | MAP_SHARED;
85 0 : if (m_map_read) {
86 0 : prot|=PROT_READ;
87 : }
88 0 : if (m_map_write) {
89 0 : prot|=PROT_WRITE;
90 : }
91 0 : m_map_address = ::mmap(0,m_map_size,prot,flags,*m_map_descriptor,m_map_offset);
92 0 : if (m_map_address==MAP_FAILED || m_map_address==0) {
93 0 : m_is_mapped = false;
94 0 : std::string message = "on file " + this->full_name();
95 0 : throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "mmap", message.c_str() );
96 0 : } /* map_failed */ else {
97 0 : m_is_mapped = true;
98 : }
99 0 : } // map_mem
100 :
101 : /** Internal method - does the actual memory unmapping.
102 : * \exception MUnmapFail if the \c munmap operation fails.
103 : */
104 :
105 0 : void OksSystem::MapFile::unmap_mem(){
106 0 : ERS_PRECONDITION(m_map_address!=0);
107 0 : const int status = munmap(m_map_address,m_map_size);
108 0 : if (status<0) {
109 0 : m_is_mapped = true;
110 0 : std::string message = "on file " + this->full_name();
111 0 : throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "munmap", message.c_str() );
112 0 : } else {
113 0 : m_is_mapped = false;
114 : }
115 0 : } // unmap_mem
116 :
117 : /** Creates a zero filled file with correct length
118 : */
119 :
120 0 : void OksSystem::MapFile::zero() const {
121 0 : ERS_ASSERT(m_map_write==true);
122 0 : const int flags = OksSystem::Descriptor::flags(false,true);
123 0 : OksSystem::Descriptor fd(this, flags,m_map_permission);
124 0 : const int page_size = ::getpagesize();
125 0 : const int page_num = (m_map_size+m_map_offset) / page_size;
126 0 : void *buffer= calloc(1,page_size);
127 0 : for(int i=0;i<page_num;i++) {
128 0 : fd.write(buffer,page_size);
129 : } // for
130 0 : free(buffer);
131 0 : fd.close();
132 0 : } // zero
133 :
134 :
135 : /** Maps the file into memory.
136 : * This is done first by opening the file descriptor for the file, then doing the actual map.
137 : * \exception OpenFail error while opening the file
138 : * \exception MMapFail error while mapping the file
139 : */
140 :
141 0 : void OksSystem::MapFile::map() {
142 0 : open_fd();
143 0 : map_mem();
144 0 : } // map
145 :
146 : /** Unmaps the file from memory
147 : * This is done first by unmapping the file, then closing the file-descriptor.
148 : * \exception CloseFail error while closing the file.
149 : * \exception MUnmapFail error while unmapping the file.
150 : */
151 :
152 0 : void OksSystem::MapFile::unmap() {
153 0 : unmap_mem();
154 0 : close_fd();
155 0 : } // unmap
156 :
157 0 : bool OksSystem::MapFile::is_loaded() const throw() {
158 0 : return (m_map_address!=0);
159 : } // is_loaded
160 :
161 :
162 : /** Gives the actual address of the map in memory.
163 : * If the file is not yet mapped, this will be 0.
164 : * \return point to the start address of the mapped file in memory.
165 : */
166 :
167 0 : void *OksSystem::MapFile::address() const throw() {
168 0 : return m_map_address;
169 : } // address
170 :
171 : /** Gives the actual size of the map in memory.
172 : * \return the size of the memory region
173 : */
174 :
175 0 : size_t OksSystem::MapFile::memory_size() const throw() {
176 0 : return m_map_size;
177 : } // memory_size
178 :
179 : /** Returns if the file is mapped or not in memory */
180 :
181 0 : bool OksSystem::MapFile::is_mapped() const {
182 0 : return m_is_mapped;
183 : }
184 :
185 0 : OksSystem::Descriptor* OksSystem::MapFile::fd() const throw() {
186 0 : return m_map_descriptor;
187 : }
|