Skip to content

Commit df01469

Browse files
mukul1987nandakumar131
authored andcommitted
HDDS-1401. Static ContainerCache in Datanodes can result in overwrite of container db. Contributed by Mukul Kumar Singh. (#708)
1 parent 32722d2 commit df01469

File tree

7 files changed

+42
-23
lines changed

7 files changed

+42
-23
lines changed

hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,15 @@ public synchronized static ContainerCache getInstance(Configuration conf) {
6969
/**
7070
* Closes a db instance.
7171
*
72-
* @param containerID - ID of the container to be closed.
72+
* @param containerPath - path of the container db to be closed.
7373
* @param db - db instance to close.
7474
*/
75-
private void closeDB(long containerID, MetadataStore db) {
75+
private void closeDB(String containerPath, MetadataStore db) {
7676
if (db != null) {
7777
try {
7878
db.close();
79-
} catch (IOException e) {
80-
LOG.error("Error closing DB. Container: " + containerID, e);
79+
} catch (Exception e) {
80+
LOG.error("Error closing DB. Container: " + containerPath, e);
8181
}
8282
}
8383
}
@@ -93,7 +93,7 @@ public void shutdownCache() {
9393
while (iterator.hasNext()) {
9494
iterator.next();
9595
MetadataStore db = (MetadataStore) iterator.getValue();
96-
closeDB(((Number)iterator.getKey()).longValue(), db);
96+
closeDB((String)iterator.getKey(), db);
9797
}
9898
// reset the cache
9999
cache.clear();
@@ -107,14 +107,18 @@ public void shutdownCache() {
107107
*/
108108
@Override
109109
protected boolean removeLRU(LinkEntry entry) {
110+
MetadataStore db = (MetadataStore) entry.getValue();
111+
String dbFile = (String)entry.getKey();
110112
lock.lock();
111113
try {
112-
MetadataStore db = (MetadataStore) entry.getValue();
113-
closeDB(((Number)entry.getKey()).longValue(), db);
114+
closeDB(dbFile, db);
115+
return true;
116+
} catch (Exception e) {
117+
LOG.error("Eviction for db:{} failed", dbFile, e);
118+
return false;
114119
} finally {
115120
lock.unlock();
116121
}
117-
return true;
118122
}
119123

120124
/**
@@ -133,7 +137,7 @@ public MetadataStore getDB(long containerID, String containerDBType,
133137
"Container ID cannot be negative.");
134138
lock.lock();
135139
try {
136-
MetadataStore db = (MetadataStore) this.get(containerID);
140+
MetadataStore db = (MetadataStore) this.get(containerDBPath);
137141

138142
if (db == null) {
139143
db = MetadataStoreBuilder.newBuilder()
@@ -142,7 +146,7 @@ public MetadataStore getDB(long containerID, String containerDBType,
142146
.setConf(conf)
143147
.setDBType(containerDBType)
144148
.build();
145-
this.put(containerID, db);
149+
this.put(containerDBPath, db);
146150
}
147151
return db;
148152
} catch (Exception e) {
@@ -157,16 +161,14 @@ public MetadataStore getDB(long containerID, String containerDBType,
157161
/**
158162
* Remove a DB handler from cache.
159163
*
160-
* @param containerID - ID of the container.
164+
* @param containerPath - path of the container db file.
161165
*/
162-
public void removeDB(long containerID) {
163-
Preconditions.checkState(containerID >= 0,
164-
"Container ID cannot be negative.");
166+
public void removeDB(String containerPath) {
165167
lock.lock();
166168
try {
167-
MetadataStore db = (MetadataStore)this.get(containerID);
168-
closeDB(containerID, db);
169-
this.remove(containerID);
169+
MetadataStore db = (MetadataStore)this.get(containerPath);
170+
closeDB(containerPath, db);
171+
this.remove(containerPath);
170172
} finally {
171173
lock.unlock();
172174
}

hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/BlockUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public static void removeDB(KeyValueContainerData container, Configuration
9595
Preconditions.checkNotNull(container);
9696
ContainerCache cache = ContainerCache.getInstance(conf);
9797
Preconditions.checkNotNull(cache);
98-
cache.removeDB(container.getContainerID());
98+
cache.removeDB(container.getDbFile().getAbsolutePath());
9999
}
100100

101101
/**

hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/BlockManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public BlockData getBlock(Container container, BlockID blockID)
160160
}
161161
byte[] kData = db.get(Longs.toByteArray(blockID.getLocalID()));
162162
if (kData == null) {
163-
throw new StorageContainerException("Unable to find the block.",
163+
throw new StorageContainerException("Unable to find the block." + blockID,
164164
NO_SUCH_BLOCK);
165165
}
166166
ContainerProtos.BlockData blockData =

hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ public void testContainerImportExport() throws Exception {
195195
for (int i = 0; i < numberOfKeysToWrite; i++) {
196196
metadataStore.put(("test" + i).getBytes(UTF_8), "test".getBytes(UTF_8));
197197
}
198-
metadataStore.close();
198+
BlockUtils.removeDB(keyValueContainerData, conf);
199199

200200
Map<String, String> metadata = new HashMap<>();
201201
metadata.put("key1", "value1");

hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,8 @@ public AllocatedBlock allocateBlock(final long size, ReplicationType type,
189189
// factors are handled by pipeline creator
190190
pipeline = pipelineManager.createPipeline(type, factor);
191191
} catch (IOException e) {
192-
LOG.error("pipeline creation failed type:{} factor:{}", type,
193-
factor, e);
192+
LOG.error("Pipeline creation failed for type:{} factor:{}",
193+
type, factor, e);
194194
break;
195195
}
196196
} else {

hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerPersistence.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ public void testDeleteContainer() throws Exception {
255255
"Container cannot be deleted because it is not empty.");
256256
container2.delete();
257257
Assert.assertTrue(containerSet.getContainerMapCopy()
258-
.containsKey(testContainerID1));
258+
.containsKey(testContainerID2));
259259
}
260260

261261
@Test

hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestCloseContainerByPipeline.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,21 @@
3434
import org.apache.hadoop.ozone.client.OzoneClientFactory;
3535
import org.apache.hadoop.ozone.client.io.OzoneOutputStream;
3636
import org.apache.hadoop.ozone.container.common.impl.ContainerData;
37+
import org.apache.hadoop.ozone.container.common.interfaces.Container;
38+
import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData;
39+
import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils;
3740
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
3841
import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
3942
import org.apache.hadoop.ozone.protocol.commands.CloseContainerCommand;
4043
import org.apache.hadoop.test.GenericTestUtils;
44+
import org.apache.hadoop.utils.MetadataStore;
4145
import org.junit.AfterClass;
4246
import org.junit.Assert;
4347
import org.junit.BeforeClass;
4448
import org.junit.Test;
4549

4650
import java.io.IOException;
51+
import java.util.ArrayList;
4752
import java.util.HashMap;
4853
import java.util.List;
4954
import java.util.concurrent.TimeoutException;
@@ -221,13 +226,25 @@ public void testCloseContainerViaRatis() throws IOException,
221226
List<DatanodeDetails> datanodes = pipeline.getNodes();
222227
Assert.assertEquals(3, datanodes.size());
223228

229+
List<MetadataStore> metadataStores = new ArrayList<>(datanodes.size());
224230
for (DatanodeDetails details : datanodes) {
225231
Assert.assertFalse(isContainerClosed(cluster, containerID, details));
226232
//send the order to close the container
227233
cluster.getStorageContainerManager().getScmNodeManager()
228234
.addDatanodeCommand(details.getUuid(),
229235
new CloseContainerCommand(containerID, pipeline.getId()));
236+
int index = cluster.getHddsDatanodeIndex(details);
237+
Container dnContainer = cluster.getHddsDatanodes().get(index)
238+
.getDatanodeStateMachine().getContainer().getContainerSet()
239+
.getContainer(containerID);
240+
metadataStores.add(BlockUtils.getDB((KeyValueContainerData) dnContainer
241+
.getContainerData(), conf));
230242
}
243+
244+
// There should be as many rocks db as the number of datanodes in pipeline.
245+
Assert.assertEquals(datanodes.size(),
246+
metadataStores.stream().distinct().count());
247+
231248
// Make sure that it is CLOSED
232249
for (DatanodeDetails datanodeDetails : datanodes) {
233250
GenericTestUtils.waitFor(

0 commit comments

Comments
 (0)