1 /******************************************************************************* 2 3 Copyright: 4 Copyright (c) 2004 Kris Bell. 5 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH. 6 All rights reserved. 7 8 License: 9 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0. 10 See LICENSE_TANGO.txt for details. 11 12 Version: Initial release: March 2004 13 14 Authors: Kris 15 16 *******************************************************************************/ 17 18 module ocean.io.device.FileMap; 19 20 import ocean.io.device.Array; 21 import ocean.io.device.File; 22 import ocean.meta.types.Qualifiers; 23 import ocean.sys.Common; 24 25 import core.sys.posix.sys.mman; 26 27 28 /******************************************************************************* 29 30 *******************************************************************************/ 31 32 class FileMap : Array 33 { 34 private MappedFile file; 35 36 /*********************************************************************** 37 38 Construct a FileMap upon the given path. 39 40 You should use resize() to setup the available 41 working space. 42 43 ***********************************************************************/ 44 45 this (cstring path, File.Style style = File.ReadWriteOpen) 46 { 47 file = new MappedFile (path, style); 48 super (file.map); 49 } 50 51 /*********************************************************************** 52 53 Resize the file and return the remapped content. Usage of 54 map() is not required following this call. 55 56 ***********************************************************************/ 57 58 final ubyte[] resize (long size) 59 { 60 auto ret = file.resize (size); 61 super.assign (ret); 62 return ret; 63 } 64 65 /*********************************************************************** 66 67 Release external resources. 68 69 ***********************************************************************/ 70 71 override void close () 72 { 73 super.close; 74 if (file) 75 file.close; 76 file = null; 77 } 78 } 79 80 81 /******************************************************************************* 82 83 *******************************************************************************/ 84 85 class MappedFile 86 { 87 private File host; 88 89 /*********************************************************************** 90 91 Construct a FileMap upon the given path. 92 93 You should use resize() to setup the available 94 working space. 95 96 ***********************************************************************/ 97 98 this (cstring path, File.Style style = File.ReadWriteOpen) 99 { 100 host = new File (path, style); 101 } 102 103 /*********************************************************************** 104 105 ***********************************************************************/ 106 107 final long length () 108 { 109 return host.length; 110 } 111 112 /*********************************************************************** 113 114 ***********************************************************************/ 115 116 final istring path () 117 { 118 return host.toString; 119 } 120 121 /*********************************************************************** 122 123 Resize the file and return the remapped content. Usage of 124 map() is not required following this call. 125 126 ***********************************************************************/ 127 128 final ubyte[] resize (long size) 129 { 130 host.truncate (size); 131 return map; 132 } 133 134 private void* base; // array pointer 135 private size_t size; // length of file 136 137 /*************************************************************************** 138 139 Return a slice representing file content as a memory-mapped array 140 141 Use this to remap content each time the file size is changed. 142 143 ***************************************************************************/ 144 145 final ubyte[] map () 146 { 147 // be wary of redundant references 148 if (base) 149 reset; 150 151 // can only do 32bit mapping on 32bit platform 152 size = cast (size_t) host.length; 153 154 // Make sure the mapping attributes are consistant with 155 // the File attributes. 156 int flags = MAP_SHARED; 157 int protection = PROT_READ; 158 auto access = host.style.access; 159 if (access & host.Access.Write) 160 protection |= PROT_WRITE; 161 162 base = mmap (null, size, protection, flags, host.fileHandle, 0); 163 if (base is MAP_FAILED) 164 { 165 base = null; 166 host.error; 167 } 168 169 return (cast(ubyte*) base) [0 .. size]; 170 } 171 172 /*************************************************************************** 173 174 Release this mapped buffer without flushing. 175 176 ***************************************************************************/ 177 178 final void close () 179 { 180 reset; 181 if (host) 182 host.close; 183 host = null; 184 } 185 186 /// 187 private void reset () 188 { 189 // NOTE: When a process ends, all mmaps belonging to that process 190 // are automatically unmapped by system (Linux). 191 // On the other hand, this is NOT the case when the related 192 // file descriptor is closed. This function unmaps explicitly. 193 if (base) 194 if (munmap (base, size)) 195 host.error; 196 197 base = null; 198 } 199 200 /*************************************************************************** 201 202 Flush dirty content out to the drive. 203 204 ***************************************************************************/ 205 206 final MappedFile flush () 207 { 208 // MS_ASYNC: delayed flush; equivalent to "add-to-queue" 209 // MS_SYNC: function flushes file immediately; no return until flush complete 210 // MS_INVALIDATE: invalidate all mappings of the same file (shared) 211 212 if (msync (base, size, MS_SYNC | MS_INVALIDATE)) 213 host.error; 214 return this; 215 } 216 } 217 218 /// 219 unittest 220 { 221 void example ( ) 222 { 223 auto file = new MappedFile ("foo.map"); 224 auto heap = file.resize (1_000_000); 225 file.close(); 226 227 auto file1 = new MappedFile ("foo1.map"); 228 auto heap1 = file1.resize (1_000_000); 229 file1.close(); 230 } 231 }