Coverage Summary for Class: MapDBBlocksIndex (co.rsk.db)
Class |
Class, %
|
Method, %
|
Line, %
|
MapDBBlocksIndex |
0%
(0/1)
|
0%
(0/10)
|
0%
(0/41)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2019 RSK Labs Ltd.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package co.rsk.db;
20
21 import org.ethereum.db.IndexedBlockStore;
22 import org.ethereum.util.ByteUtil;
23 import org.mapdb.DB;
24 import org.mapdb.Serializer;
25
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Map;
29
30 import static org.ethereum.db.IndexedBlockStore.BLOCK_INFO_SERIALIZER;
31
32 /**
33 * MapDBBlocksIndex is a thread safe implementation of BlocksIndex with mapDB providing the underlying functionality.
34 */
35 public class MapDBBlocksIndex implements BlocksIndex {
36
37 private static final String MAX_BLOCK_NUMBER_KEY = "max_block";
38
39 private final Map<Long, List<IndexedBlockStore.BlockInfo>> index;
40 private final Map<String, byte[]> metadata;
41
42 private final DB indexDB;
43
44 public MapDBBlocksIndex(DB indexDB) {
45
46 this.indexDB = indexDB;
47
48 index = indexDB.hashMapCreate("index")
49 .keySerializer(Serializer.LONG)
50 .valueSerializer(BLOCK_INFO_SERIALIZER)
51 .counterEnable()
52 .makeOrGet();
53
54 metadata = indexDB.hashMapCreate("metadata")
55 .keySerializer(Serializer.STRING)
56 .valueSerializer(Serializer.BYTE_ARRAY)
57 .makeOrGet();
58
59 // Max block number initialization assumes an index without gap
60 if (!metadata.containsKey(MAX_BLOCK_NUMBER_KEY)) {
61 long maxBlockNumber = (long) index.size() - 1;
62 metadata.put(MAX_BLOCK_NUMBER_KEY, ByteUtil.longToBytes(maxBlockNumber));
63 }
64 }
65
66 @Override
67 public boolean isEmpty() {
68 return index.isEmpty();
69 }
70
71 @Override
72 public long getMaxNumber() {
73 if (index.isEmpty()) {
74 throw new IllegalStateException("Index is empty");
75 }
76
77 return ByteUtil.byteArrayToLong(metadata.get(MAX_BLOCK_NUMBER_KEY));
78 }
79
80 @Override
81 public long getMinNumber() {
82 if (index.isEmpty()) {
83 throw new IllegalStateException("Index is empty");
84 }
85
86 return getMaxNumber() - index.size() + 1;
87 }
88
89 @Override
90 public boolean contains(long blockNumber) {
91 return index.containsKey(blockNumber);
92 }
93
94 @Override
95 public List<IndexedBlockStore.BlockInfo> getBlocksByNumber(long blockNumber) {
96 return index.getOrDefault(blockNumber, new ArrayList<>());
97 }
98
99 @Override
100 public void putBlocks(long blockNumber, List<IndexedBlockStore.BlockInfo> blocks) {
101 if (blocks == null || blocks.isEmpty()) {
102 throw new IllegalArgumentException("Block list cannot be empty nor null.");
103 }
104
105 long maxNumber = -1;
106 if (index.size() > 0) {
107 maxNumber = getMaxNumber();
108 }
109 if (blockNumber > maxNumber) {
110 metadata.put(MAX_BLOCK_NUMBER_KEY, ByteUtil.longToBytes(blockNumber));
111 }
112
113 index.put(blockNumber, blocks);
114 }
115
116 @Override
117 public List<IndexedBlockStore.BlockInfo> removeLast() {
118 long lastBlockNumber = -1;
119 if (index.size() > 0) {
120 lastBlockNumber = getMaxNumber();
121 }
122
123 List<IndexedBlockStore.BlockInfo> result = index.remove(lastBlockNumber);
124
125 if (result == null) {
126 result = new ArrayList<>();
127 }
128
129 metadata.put(MAX_BLOCK_NUMBER_KEY, ByteUtil.longToBytes(lastBlockNumber - 1));
130
131 return result;
132 }
133
134 @Override
135 public void flush() {
136 indexDB.commit();
137 }
138
139 @Override
140 public void close() {
141 indexDB.close();
142 }
143 }