raw
cryostat_genesis.kv     1 ------------------------------------------------------------------------------
cryostat_genesis.kv 2 ------------------------------------------------------------------------------
cryostat_genesis.kv 3 -- This file is part of 'Cryostat', an Ada library for persistent storage. --
cryostat_genesis.kv 4 -- --
cryostat_genesis.kv 5 -- (C) 2020 Stanislav Datskovskiy ( www.loper-os.org ) --
cryostat_genesis.kv 6 -- http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html --
cryostat_genesis.kv 7 -- --
cryostat_genesis.kv 8 -- You do not have, nor can you ever acquire the right to use, copy or --
cryostat_genesis.kv 9 -- distribute this software ; Should you use this software for any purpose, --
cryostat_genesis.kv 10 -- or copy and distribute it to anyone or in any manner, you are breaking --
cryostat_genesis.kv 11 -- the laws of whatever soi-disant jurisdiction, and you promise to --
cryostat_genesis.kv 12 -- continue doing so for the indefinite future. In any case, please --
cryostat_genesis.kv 13 -- always : read and understand any software ; verify any PGP signatures --
cryostat_genesis.kv 14 -- that you use - for any purpose. --
cryostat_genesis.kv 15 ------------------------------------------------------------------------------
cryostat_genesis.kv 16 ------------------------------------------------------------------------------
cryostat_genesis.kv 17
cryostat_genesis.kv 18 with System; use System;
cryostat_genesis.kv 19
cryostat_genesis.kv 20
cryostat_genesis.kv 21 package body PMaps is
cryostat_genesis.kv 22
cryostat_genesis.kv 23 -- Open a backing file at Path, with given params, for use with Initialize
cryostat_genesis.kv 24 function OpenMapFile(Path : in String;
cryostat_genesis.kv 25 Writable : in Boolean := False;
cryostat_genesis.kv 26 Create : in Boolean := False) return FD is
cryostat_genesis.kv 27
cryostat_genesis.kv 28 -- Buffer for converting the civilized Path string to a C-style string :
cryostat_genesis.kv 29 CPath : String(1 .. Path'Length + 1) := (others => Character'Val(0));
cryostat_genesis.kv 30
cryostat_genesis.kv 31 -- Unix FD handle for the backing file, obtained by Open()
cryostat_genesis.kv 32 FileFD : FD;
cryostat_genesis.kv 33
cryostat_genesis.kv 34 -- Flags provided to Open() -- default 'read only'
cryostat_genesis.kv 35 COpenFlag : O_Flags := O_RDONLY;
cryostat_genesis.kv 36
cryostat_genesis.kv 37 begin
cryostat_genesis.kv 38
cryostat_genesis.kv 39 -- Convert civilized string to the barbaric type expected by Open() :
cryostat_genesis.kv 40 CPath(Path'Range) := Path;
cryostat_genesis.kv 41
cryostat_genesis.kv 42 -- Set the writability flag for Open() if Writable is enabled :
cryostat_genesis.kv 43 if Writable then
cryostat_genesis.kv 44 COpenFlag := O_RDWR;
cryostat_genesis.kv 45 end if;
cryostat_genesis.kv 46
cryostat_genesis.kv 47 -- If file does not exist, and Create is enabled, it will be created :
cryostat_genesis.kv 48 if Create then
cryostat_genesis.kv 49 COpenFlag := COpenFlag or O_CREAT;
cryostat_genesis.kv 50 end if;
cryostat_genesis.kv 51
cryostat_genesis.kv 52 -- Open the file :
cryostat_genesis.kv 53 FileFD := Open(CPath'Address, COpenFlag);
cryostat_genesis.kv 54
cryostat_genesis.kv 55 -- If Open() failed, eggog :
cryostat_genesis.kv 56 if FileFD = FD_EGGOG then
cryostat_genesis.kv 57 raise PMapFailedOpen with "PMap: Failed to Open backing file";
cryostat_genesis.kv 58 end if;
cryostat_genesis.kv 59
cryostat_genesis.kv 60 -- Return the FD of the backing file :
cryostat_genesis.kv 61 return FileFD;
cryostat_genesis.kv 62
cryostat_genesis.kv 63 end OpenMapFile;
cryostat_genesis.kv 64
cryostat_genesis.kv 65
cryostat_genesis.kv 66 -- Initialize a new map
cryostat_genesis.kv 67 procedure Initialize(Map : in out PMap) is
cryostat_genesis.kv 68
cryostat_genesis.kv 69 -- Prot flags to be given to MMap()
cryostat_genesis.kv 70 MProtFlag : MM_Prot := PROT_READ;
cryostat_genesis.kv 71
cryostat_genesis.kv 72 -- Result code returned by FTruncate()
cryostat_genesis.kv 73 CErr : Unix_Int;
cryostat_genesis.kv 74
cryostat_genesis.kv 75 begin
cryostat_genesis.kv 76
cryostat_genesis.kv 77 -- Check that we have not already Open'd:
cryostat_genesis.kv 78 if Map.Status /= Stop then
cryostat_genesis.kv 79 Map.Status := Eggog;
cryostat_genesis.kv 80 raise PMapFailedOpen with "PMap: already Opened backing file";
cryostat_genesis.kv 81 end if;
cryostat_genesis.kv 82
cryostat_genesis.kv 83 -- If Write is enabled, set the appropriate flag for MMap() :
cryostat_genesis.kv 84 if Map.MapWritable then
cryostat_genesis.kv 85 MProtFlag := PROT_READ or PROT_WRITE;
cryostat_genesis.kv 86 end if;
cryostat_genesis.kv 87
cryostat_genesis.kv 88 -- If creating, pad the backing file to the payload size :
cryostat_genesis.kv 89 if Map.MapCreate then
cryostat_genesis.kv 90 CErr := FTruncate(Map.FileFD, Map.MapLength);
cryostat_genesis.kv 91 if CErr /= 0 then
cryostat_genesis.kv 92 Map.Status := Eggog;
cryostat_genesis.kv 93 raise PMapFailedOpen with "PMap: Failed to FTruncate backing file";
cryostat_genesis.kv 94 end if;
cryostat_genesis.kv 95 end if;
cryostat_genesis.kv 96
cryostat_genesis.kv 97 -- Ask the OS to set up the map itself:
cryostat_genesis.kv 98 Map.Address := MMap(Length => Map.MapLength,
cryostat_genesis.kv 99 Off_T => Map.MapOffset,
cryostat_genesis.kv 100 Prot => MProtFlag,
cryostat_genesis.kv 101 Flags => MAP_SHARED,
cryostat_genesis.kv 102 Handle => Map.FileFD);
cryostat_genesis.kv 103
cryostat_genesis.kv 104 -- Test for failure of MMap() call :
cryostat_genesis.kv 105 if Map.Address = MAP_FAILED then
cryostat_genesis.kv 106 Map.Status := Eggog;
cryostat_genesis.kv 107 raise PMapFailedMMap with "PMap: MAP_FAILED";
cryostat_genesis.kv 108 end if;
cryostat_genesis.kv 109
cryostat_genesis.kv 110 if Map.Address = NullPtr then
cryostat_genesis.kv 111 Map.Status := Eggog;
cryostat_genesis.kv 112 raise PMapFailedAddr with "PMap: Map Address is Null";
cryostat_genesis.kv 113 end if;
cryostat_genesis.kv 114
cryostat_genesis.kv 115 -- If no failure detected, mark the map as usable :
cryostat_genesis.kv 116 Map.Status := Run;
cryostat_genesis.kv 117
cryostat_genesis.kv 118 end Initialize;
cryostat_genesis.kv 119
cryostat_genesis.kv 120
cryostat_genesis.kv 121 -- Test whether a map is operating
cryostat_genesis.kv 122 function IsReady(Map : in PMap) return Boolean is
cryostat_genesis.kv 123 begin
cryostat_genesis.kv 124
cryostat_genesis.kv 125 return Map.Status = Run;
cryostat_genesis.kv 126
cryostat_genesis.kv 127 end IsReady;
cryostat_genesis.kv 128
cryostat_genesis.kv 129
cryostat_genesis.kv 130 -- Retrieve the memory address where the map payload resides
cryostat_genesis.kv 131 function GetAddress(Map : in PMap) return MapAddress is
cryostat_genesis.kv 132 begin
cryostat_genesis.kv 133
cryostat_genesis.kv 134 -- Ensure that the map is active :
cryostat_genesis.kv 135 if not IsReady(Map) then
cryostat_genesis.kv 136 raise PMapNotRunning with "PMap: GetAddress on inactive Map";
cryostat_genesis.kv 137 end if;
cryostat_genesis.kv 138
cryostat_genesis.kv 139 -- Return the address :
cryostat_genesis.kv 140 return Map.Address;
cryostat_genesis.kv 141
cryostat_genesis.kv 142 end GetAddress;
cryostat_genesis.kv 143
cryostat_genesis.kv 144
cryostat_genesis.kv 145 -- Zeroize the map, if it is writable
cryostat_genesis.kv 146 procedure Zap(Map : in out PMap) is
cryostat_genesis.kv 147
cryostat_genesis.kv 148 -- Represent the map's payload as a byte array across full length :
cryostat_genesis.kv 149 RawArray : array(1 .. Map.MapLength) of Byte;
cryostat_genesis.kv 150 for RawArray'Address use Map.Address;
cryostat_genesis.kv 151
cryostat_genesis.kv 152 begin
cryostat_genesis.kv 153
cryostat_genesis.kv 154 -- If map is inactive, do nothing :
cryostat_genesis.kv 155 if not IsReady(Map) then
cryostat_genesis.kv 156 return;
cryostat_genesis.kv 157 end if;
cryostat_genesis.kv 158
cryostat_genesis.kv 159 -- If tried to zap a read-only map, eggog :
cryostat_genesis.kv 160 if Map.MapWritable = False then
cryostat_genesis.kv 161 raise PMapNotWritable with "PMap: Tried to Zap a Read-Only Map";
cryostat_genesis.kv 162 end if;
cryostat_genesis.kv 163
cryostat_genesis.kv 164 -- Zeroize the payload of the map :
cryostat_genesis.kv 165 RawArray := (others => 0);
cryostat_genesis.kv 166
cryostat_genesis.kv 167 end Zap;
cryostat_genesis.kv 168
cryostat_genesis.kv 169
cryostat_genesis.kv 170 -- Sync the map to disk
cryostat_genesis.kv 171 procedure Sync(Map : in out PMap) is
cryostat_genesis.kv 172
cryostat_genesis.kv 173 -- Result code returned by MSync() and Close()
cryostat_genesis.kv 174 CErr : Unix_Int := 0;
cryostat_genesis.kv 175
cryostat_genesis.kv 176 begin
cryostat_genesis.kv 177
cryostat_genesis.kv 178 -- If map is inactive, do nothing :
cryostat_genesis.kv 179 if not IsReady(Map) then
cryostat_genesis.kv 180 return;
cryostat_genesis.kv 181 end if;
cryostat_genesis.kv 182
cryostat_genesis.kv 183 -- If map is writable, sync it to disk :
cryostat_genesis.kv 184 if Map.MapWritable then
cryostat_genesis.kv 185 CErr := MSync(Map.Address, Map.MapLength, MS_SYNC);
cryostat_genesis.kv 186 end if;
cryostat_genesis.kv 187
cryostat_genesis.kv 188 -- If eggog during MSync() :
cryostat_genesis.kv 189 if CErr /= 0 then
cryostat_genesis.kv 190 Map.Status := Eggog;
cryostat_genesis.kv 191 CErr := Close(Map.FileFD);
cryostat_genesis.kv 192 raise PMapFailedSync with "PMap: Failed to Sync";
cryostat_genesis.kv 193 end if;
cryostat_genesis.kv 194
cryostat_genesis.kv 195 end Sync;
cryostat_genesis.kv 196
cryostat_genesis.kv 197
cryostat_genesis.kv 198 -- Close map and mark it unusable
cryostat_genesis.kv 199 procedure Stop(Map : in out PMap) is
cryostat_genesis.kv 200
cryostat_genesis.kv 201 -- Result code returned by MUnmap() and Close()
cryostat_genesis.kv 202 CErr : Unix_Int;
cryostat_genesis.kv 203
cryostat_genesis.kv 204 begin
cryostat_genesis.kv 205
cryostat_genesis.kv 206 -- If map is already inactive, do nothing :
cryostat_genesis.kv 207 if not IsReady(Map) then
cryostat_genesis.kv 208 return;
cryostat_genesis.kv 209 end if;
cryostat_genesis.kv 210
cryostat_genesis.kv 211 -- Sync all changes to disk, if map was writable :
cryostat_genesis.kv 212 Sync(Map);
cryostat_genesis.kv 213
cryostat_genesis.kv 214 -- Mark map as inactive :
cryostat_genesis.kv 215 Map.Status := Stop;
cryostat_genesis.kv 216
cryostat_genesis.kv 217 -- Unmap the map :
cryostat_genesis.kv 218 CErr := MUnmap(Map.Address, Map.MapLength);
cryostat_genesis.kv 219 if CErr /= 0 then
cryostat_genesis.kv 220 Map.Status := Eggog;
cryostat_genesis.kv 221 raise PMapFailedUnmap with "PMap: Failed to Unmap";
cryostat_genesis.kv 222 end if;
cryostat_genesis.kv 223
cryostat_genesis.kv 224 -- Lastly, close out the FD :
cryostat_genesis.kv 225 CErr := Close(Map.FileFD);
cryostat_genesis.kv 226 if CErr /= 0 then
cryostat_genesis.kv 227 Map.Status := Eggog;
cryostat_genesis.kv 228 raise PMapFailedClose with "PMap: Failed to Close backing file";
cryostat_genesis.kv 229 end if;
cryostat_genesis.kv 230
cryostat_genesis.kv 231 end Stop;
cryostat_genesis.kv 232
cryostat_genesis.kv 233
cryostat_genesis.kv 234 -- Sync and close a given map, if fell out of scope
cryostat_genesis.kv 235 procedure Finalize(Map : in out PMap) is
cryostat_genesis.kv 236 begin
cryostat_genesis.kv 237
cryostat_genesis.kv 238 -- Close the map :
cryostat_genesis.kv 239 Stop(Map);
cryostat_genesis.kv 240
cryostat_genesis.kv 241 end Finalize;
cryostat_genesis.kv 242
cryostat_genesis.kv 243 end PMaps;