-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBlocksMapDb.java
More file actions
176 lines (165 loc) · 4.59 KB
/
BlocksMapDb.java
File metadata and controls
176 lines (165 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package storage.mapdb;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import model.lightchain.Block;
import model.lightchain.Identifier;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.HTreeMap;
import org.mapdb.Serializer;
import storage.Blocks;
/**
* Implementation of BlocksMapDb interface.
*/
public class BlocksMapDb implements Blocks {
private final DB dbId;
private final DB dbHeight;
private final ReentrantReadWriteLock lock;
private static final String MAP_NAME_ID = "blocks_map_id";
private static final String MAP_NAME_HEIGHT = "blocks_map_height";
private final HTreeMap blocksIdMap;
private final HTreeMap<Integer, Identifier> blocksHeightMap;
/**
* Creates blocks mapdb.
*
* @param filePathId of id,block mapdb.
* @param filePathHeight of height,id mapdb.
*/
@SuppressWarnings("unchecked")
public BlocksMapDb(String filePathId, String filePathHeight) {
// TODO: file paths consolidated.
this.dbId = DBMaker.fileDB(filePathId).make();
this.lock = new ReentrantReadWriteLock();
blocksIdMap = this.dbId.hashMap(MAP_NAME_ID)
.keySerializer(Serializer.BYTE_ARRAY)
.createOrOpen();
this.dbHeight = DBMaker.fileDB(filePathHeight).make();
blocksHeightMap = (HTreeMap<Integer, Identifier>) this.dbHeight.hashMap(MAP_NAME_HEIGHT)
.createOrOpen();
}
/**
* Checks existence of block on the database.
*
* @param blockId Identifier of block.
* @return true if a block with that identifier exists, false otherwise.
*/
@Override
public boolean has(Identifier blockId) {
boolean hasBoolean;
try {
lock.readLock().lock();
hasBoolean = blocksIdMap.containsKey(blockId.getBytes());
} finally {
lock.readLock().unlock();
}
return hasBoolean;
}
/**
* Adds block to the database.
*
* @param block given block to be added.
* @return true if block did not exist on the database,
false if block is already in database.
*/
@Override
public boolean add(Block block) {
boolean addBooleanId;
// TODO: refactor to Long
Integer height = (int) block.getHeight();
try {
lock.writeLock().lock();
// if the block.id() key and the block was absent in IdMap, add it and return true
addBooleanId = blocksIdMap.putIfAbsentBoolean(block.id().getBytes(), block);
if (addBooleanId) {
blocksHeightMap.compute(height, (key, value) ->
(value == null)
? block.id()
: null //TODO: implement else case
);
}
} finally {
lock.writeLock().unlock();
}
return addBooleanId;
}
/**
* Removes block with given identifier.
*
* @param blockId identifier of the block.
* @return true if block exists on database and removed successfully,
false if block does not exist on database.
*/
@Override
public boolean remove(Identifier blockId) {
boolean removeBoolean;
try {
lock.writeLock().lock();
Block block = byId(blockId);
removeBoolean = blocksIdMap.remove(blockId.getBytes(), block);
if (removeBoolean) {
blocksHeightMap.remove((int) block.getHeight(), blockId);
}
} finally {
lock.writeLock().unlock();
}
return removeBoolean;
}
/**
* Returns the block with given identifier.
*
* @param blockId identifier of the block.
* @return the block itself if exists and null otherwise.
*/
@Override
public Block byId(Identifier blockId) {
Block block;
try {
lock.readLock().lock();
block = (Block) blocksIdMap.get(blockId.getBytes());
} finally {
lock.readLock().unlock();
}
return block;
}
/**
* Returns the block with the given height.
*
* @param height height of the block.
* @return the block id itself if exists and null otherwise.
*/
@Override
public Block atHeight(long height) {
Block block = null;
try {
lock.readLock().lock();
// TODO: fix the height for long.
final Identifier blockId = blocksHeightMap.get((int) height);
if (blockId != null) {
block = byId(blockId);
}
} finally {
lock.readLock().unlock();
}
return block;
}
/**
* Returns all blocks stored in database.
*
* @return all stored blocks in database.
*/
@Override
public ArrayList<Block> all() {
ArrayList<Block> allBlocks = new ArrayList<>();
for (Object block : blocksIdMap.values()) {
allBlocks.add((Block) block);
}
return allBlocks;
}
/**
* Close the db.
*/
public void close() {
dbId.close();
dbHeight.close();
}
}