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