Updated copyright
[sixth-data.git] / src / main / java / eu / svjatoslav / sixth / data / store / file / MetaData.java
1 /*
2  * Sixth Data. Copyright ©2012-2019, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 3 of the GNU Lesser General Public License
6  * or later as published by the Free Software Foundation.
7  */
8
9 package eu.svjatoslav.sixth.data.store.file;
10
11 import java.io.IOException;
12
13 public class MetaData {
14
15     public static final int FILE_LOCATION_ENTRY_ALLOCATION_TABLE_START = 4 * 6;
16     private static final int FORMAT_VERSION = 1;
17     private static final int FILE_LOCATION_VERSION = 4 * 0;
18     private static final int FILE_LOCATION_ENTRIES_TABLE_SIZE = 4 * 1;
19     private static final int FILE_LOCATION_USED_ENTRIES_COUNT = 4 * 2;
20     private static final int FILE_LOCATION_CURRENT_ENTRY = 4 * 3;
21     private static final int FILE_LOCATION_CURRENT_LOCATION = 4 * 4; // LONG!!
22     private final FileDataStore dataStore;
23     private int entriesTableSize;
24     private int currentEntry;
25     private int usedEntriesCount;
26     private long currentLocation;
27
28     public MetaData(final FileDataStore dataStore) {
29         this.dataStore = dataStore;
30     }
31
32     /**
33      * @return address of the start of the allocated space
34      */
35     public synchronized long allocateStorageSpace(final int amountOfBytes) {
36         final long locationStart = currentLocation;
37         currentLocation += amountOfBytes;
38         return locationStart;
39     }
40
41     public void decreaseUsedEntriesCount() {
42         usedEntriesCount--;
43     }
44
45     public synchronized void ensureMinimumCurrentLocation(
46             final long minimumLocation) {
47
48         if (currentLocation < minimumLocation)
49             currentLocation = minimumLocation;
50     }
51
52     public boolean entriesTableNeedsIncreasing() {
53         final int reserveSize = (entriesTableSize / 10) + 1;
54
55         return usedEntriesCount >= (entriesTableSize - reserveSize);
56
57     }
58
59     public long getEntriesStorageAreaStart() {
60         return FILE_LOCATION_ENTRY_ALLOCATION_TABLE_START
61                 + (EntryRecord.ENTRY_RECORD_LENGTH * entriesTableSize);
62     }
63
64     public long getEntriesStorageAreaStart(
65             final int hypotheticalEntriesTableSize) {
66         return FILE_LOCATION_ENTRY_ALLOCATION_TABLE_START
67                 + (EntryRecord.ENTRY_RECORD_LENGTH * hypotheticalEntriesTableSize);
68     }
69
70     /**
71      * @return amount of entries in the entries table
72      */
73     public int getEntriesTableSize() {
74         return entriesTableSize;
75     }
76
77     public void setEntriesTableSize(final int newSize) {
78         entriesTableSize = newSize;
79     }
80
81     public int getNewEntryId() {
82         currentEntry++;
83
84         if (currentEntry >= getEntriesTableSize())
85             currentEntry = 0;
86
87         return currentEntry;
88     }
89
90     public void increaseUsedEntriesCount() {
91         usedEntriesCount++;
92     }
93
94     public void initializeNewFile() throws IOException {
95         entriesTableSize = 16;
96         usedEntriesCount = 0;
97         currentEntry = entriesTableSize - 1;
98         currentLocation = getEntriesStorageAreaStart();
99
100         writeFileHeader();
101     }
102
103     public void readFileHeader() throws IOException {
104
105         final int fileVersion = dataStore.readInt(FILE_LOCATION_VERSION);
106         if (fileVersion != FORMAT_VERSION)
107             throw new RuntimeException("File version is " + fileVersion
108                     + " but version " + FORMAT_VERSION + " is required.");
109
110         entriesTableSize = dataStore.readInt(FILE_LOCATION_ENTRIES_TABLE_SIZE);
111
112         usedEntriesCount = dataStore.readInt(FILE_LOCATION_USED_ENTRIES_COUNT);
113
114         currentEntry = dataStore.readInt(FILE_LOCATION_CURRENT_ENTRY);
115
116         currentLocation = dataStore.readLong(FILE_LOCATION_CURRENT_LOCATION);
117     }
118
119     public void setCurrentLocation(final long currentLocation) {
120         this.currentLocation = currentLocation;
121     }
122
123     public void writeFileHeader() throws IOException {
124         dataStore.writeInt(FILE_LOCATION_VERSION, FORMAT_VERSION);
125         dataStore.writeInt(FILE_LOCATION_ENTRIES_TABLE_SIZE,
126                 getEntriesTableSize());
127         dataStore.writeInt(FILE_LOCATION_USED_ENTRIES_COUNT, usedEntriesCount);
128         dataStore.writeInt(FILE_LOCATION_CURRENT_ENTRY, currentEntry);
129         dataStore.writeLong(FILE_LOCATION_CURRENT_LOCATION, currentLocation);
130     }
131
132 }