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