This is an automated email from the ASF dual-hosted git repository.
pifta pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new aa68b9abed HDDS-5119. Recon file count by size page has incorrect data
when keys are deleted (#3269)
aa68b9abed is described below
commit aa68b9abedc0b5882a415f2b3b6b8adc367bb98a
Author: Zita Dombi <[email protected]>
AuthorDate: Wed Apr 6 18:34:32 2022 +0200
HDDS-5119. Recon file count by size page has incorrect data when keys are
deleted (#3269)
---
.../hadoop/ozone/recon/tasks/OMDBUpdateEvent.java | 2 +-
.../ozone/recon/tasks/OMDBUpdatesHandler.java | 28 ++-
.../ozone/recon/tasks/TestOMDBUpdatesHandler.java | 252 ++++++++++++++-------
3 files changed, 185 insertions(+), 97 deletions(-)
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/OMDBUpdateEvent.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/OMDBUpdateEvent.java
index 8201f93a33..5ef9bf187c 100644
---
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/OMDBUpdateEvent.java
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/OMDBUpdateEvent.java
@@ -89,7 +89,7 @@ public final class OMDBUpdateEvent<KEY, VALUE> {
@Override
public int hashCode() {
- return Objects.hash(updatedKey, action);
+ return Objects.hash(updatedKey, table, action);
}
/**
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/OMDBUpdatesHandler.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/OMDBUpdatesHandler.java
index 7fa9a32c1a..e478e3be40 100644
---
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/OMDBUpdatesHandler.java
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/OMDBUpdatesHandler.java
@@ -24,6 +24,7 @@ import static
org.apache.hadoop.ozone.recon.tasks.OMDBUpdateEvent.OMDBUpdateActi
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -49,6 +50,8 @@ public class OMDBUpdatesHandler extends WriteBatch.Handler {
private CodecRegistry codecRegistry;
private OMMetadataManager omMetadataManager;
private List<OMDBUpdateEvent> omdbUpdateEvents = new ArrayList<>();
+ private Map<String, OMDBUpdateEvent> omdbLatestUpdateEvents
+ = new HashMap<>();
private OMDBDefinition omdbDefinition;
public OMDBUpdatesHandler(OMMetadataManager metadataManager) {
@@ -105,9 +108,17 @@ public class OMDBUpdatesHandler extends WriteBatch.Handler
{
// Delete existing
// Delete non-existing
Table table = omMetadataManager.getTable(tableName);
- // Recon does not add entries to cache and it is safer to always use
- // getSkipCache in Recon.
- Object oldValue = table.getSkipCache(key);
+
+ OMDBUpdateEvent latestEvent = omdbLatestUpdateEvents.get(key);
+ Object oldValue;
+ if (latestEvent != null) {
+ oldValue = latestEvent.getValue();
+ } else {
+ // Recon does not add entries to cache and it is safer to always use
+ // getSkipCache in Recon.
+ oldValue = table.getSkipCache(key);
+ }
+
if (action == PUT) {
Object value = codecRegistry.asObject(valueBytes, valueType.get());
builder.setValue(value);
@@ -115,7 +126,9 @@ public class OMDBUpdatesHandler extends WriteBatch.Handler {
// as an "UPDATE" event.
if (oldValue != null) {
builder.setOldValue(oldValue);
- builder.setAction(UPDATE);
+ if (latestEvent == null || latestEvent.getAction() != DELETE) {
+ builder.setAction(UPDATE);
+ }
}
} else if (action.equals(DELETE)) {
// When you delete a Key, we add the old value to the event so that
@@ -128,13 +141,8 @@ public class OMDBUpdatesHandler extends WriteBatch.Handler
{
LOG.debug(String.format("Generated OM update Event for table : %s, " +
"action = %s", tableName, action));
}
- if (omdbUpdateEvents.contains(event)) {
- // If the same event is part of this batch, the last one only holds.
- // For example, if there are 2 PUT key1 events, then the first one
- // can be discarded.
- omdbUpdateEvents.remove(event);
- }
omdbUpdateEvents.add(event);
+ omdbLatestUpdateEvents.put(key, event);
} else {
// key type or value type cannot be determined for this table.
// log a warn message and ignore the update.
diff --git
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/tasks/TestOMDBUpdatesHandler.java
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/tasks/TestOMDBUpdatesHandler.java
index 5e80f7e70f..ed03973c98 100644
---
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/tasks/TestOMDBUpdatesHandler.java
+++
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/tasks/TestOMDBUpdatesHandler.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.ozone.recon.tasks;
import static
org.apache.hadoop.ozone.recon.tasks.OMDBUpdateEvent.OMDBUpdateAction.PUT;
import static
org.apache.hadoop.ozone.recon.tasks.OMDBUpdateEvent.OMDBUpdateAction.UPDATE;
+import static
org.apache.hadoop.ozone.recon.tasks.OMDBUpdateEvent.OMDBUpdateAction.DELETE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -35,6 +36,7 @@ import
org.apache.hadoop.hdds.client.StandaloneReplicationConfig;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.server.ServerUtils;
+import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OmMetadataManagerImpl;
import org.apache.hadoop.ozone.om.codec.OMDBDefinition;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
@@ -43,10 +45,13 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.hdds.utils.db.RDBStore;
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.rocksdb.RocksDB;
+import org.rocksdb.RocksDBException;
import org.rocksdb.TransactionLogIterator;
import org.rocksdb.WriteBatch;
@@ -58,6 +63,8 @@ public class TestOMDBUpdatesHandler {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
+ private OMMetadataManager omMetadataManager;
+ private OMMetadataManager reconOmMetadataManager;
private OMDBDefinition omdbDefinition = new OMDBDefinition();
private Random random = new Random();
@@ -71,60 +78,41 @@ public class TestOMDBUpdatesHandler {
return configuration;
}
- @Test
- public void testPut() throws Exception {
+ @Before
+ public void setUp() throws Exception {
OzoneConfiguration configuration = createNewTestPath();
- OmMetadataManagerImpl metaMgr = new OmMetadataManagerImpl(configuration);
+ omMetadataManager = new OmMetadataManagerImpl(configuration);
+
+ OzoneConfiguration reconConfiguration = createNewTestPath();
+ reconOmMetadataManager = new OmMetadataManagerImpl(reconConfiguration);
+ }
+ @Test
+ public void testPut() throws Exception {
// Create 1 volume, 2 keys and write to source OM DB.
- String volumeKey = metaMgr.getVolumeKey("sampleVol");
+ String volumeKey = omMetadataManager.getVolumeKey("sampleVol");
OmVolumeArgs args =
OmVolumeArgs.newBuilder()
.setVolume("sampleVol")
.setAdminName("bilbo")
.setOwnerName("bilbo")
.build();
- metaMgr.getVolumeTable().put(volumeKey, args);
+ omMetadataManager.getVolumeTable().put(volumeKey, args);
OmKeyInfo firstKey = getOmKeyInfo("sampleVol", "bucketOne", "key_one");
- metaMgr.getKeyTable(getBucketLayout())
+ omMetadataManager.getKeyTable(getBucketLayout())
.put("/sampleVol/bucketOne/key_one", firstKey);
OmKeyInfo secondKey = getOmKeyInfo("sampleVol", "bucketOne", "key_two");
- metaMgr.getKeyTable(getBucketLayout())
+ omMetadataManager.getKeyTable(getBucketLayout())
.put("/sampleVol/bucketOne/key_two", secondKey);
// Write the secondKey to the target OM DB.
- OzoneConfiguration conf2 = createNewTestPath();
- OmMetadataManagerImpl reconOmmetaMgr = new OmMetadataManagerImpl(conf2);
- reconOmmetaMgr.getKeyTable(getBucketLayout())
+ reconOmMetadataManager.getKeyTable(getBucketLayout())
.put("/sampleVol/bucketOne/key_two", secondKey);
- RDBStore rdbStore = (RDBStore) metaMgr.getStore();
- RocksDB rocksDB = rdbStore.getDb();
- // Get all updates from source DB. (3 PUTs)
- TransactionLogIterator transactionLogIterator =
- rocksDB.getUpdatesSince(0);
- List<byte[]> writeBatches = new ArrayList<>();
-
- while (transactionLogIterator.isValid()) {
- TransactionLogIterator.BatchResult result =
- transactionLogIterator.getBatch();
- result.writeBatch().markWalTerminationPoint();
- WriteBatch writeBatch = result.writeBatch();
- writeBatches.add(writeBatch.data());
- transactionLogIterator.next();
- }
-
- // OMDBUpdatesHandler has access to target DB. Hence it has only the
- // "secondKey".
- OMDBUpdatesHandler omdbUpdatesHandler =
- new OMDBUpdatesHandler(reconOmmetaMgr);
- for (byte[] data : writeBatches) {
- WriteBatch writeBatch = new WriteBatch(data);
- // Capture the 3 PUT events from source DB.
- writeBatch.iterate(omdbUpdatesHandler);
- }
+ List<byte[]> writeBatches = getBytesFromOmMetaManager(0);
+ OMDBUpdatesHandler omdbUpdatesHandler = captureEvents(writeBatches);
List<OMDBUpdateEvent> events = omdbUpdatesHandler.getEvents();
assertEquals(3, events.size());
@@ -150,63 +138,37 @@ public class TestOMDBUpdatesHandler {
@Test
public void testDelete() throws Exception {
-
- OzoneConfiguration configuration = createNewTestPath();
- OmMetadataManagerImpl metaMgr = new OmMetadataManagerImpl(configuration);
-
- OzoneConfiguration conf2 = createNewTestPath();
- OmMetadataManagerImpl metaMgrCopy = new OmMetadataManagerImpl(conf2);
-
// Write 1 volume, 1 key into source and target OM DBs.
- String volumeKey = metaMgr.getVolumeKey("sampleVol");
- String nonExistVolumeKey = metaMgr.getVolumeKey("nonExistingVolume");
+ String volumeKey = omMetadataManager.getVolumeKey("sampleVol");
+ String nonExistVolumeKey = omMetadataManager
+ .getVolumeKey("nonExistingVolume");
OmVolumeArgs args =
OmVolumeArgs.newBuilder()
.setVolume("sampleVol")
.setAdminName("bilbo")
.setOwnerName("bilbo")
.build();
- metaMgr.getVolumeTable().put(volumeKey, args);
- metaMgrCopy.getVolumeTable().put(volumeKey, args);
+ omMetadataManager.getVolumeTable().put(volumeKey, args);
+ reconOmMetadataManager.getVolumeTable().put(volumeKey, args);
OmKeyInfo omKeyInfo = getOmKeyInfo("sampleVol", "bucketOne", "key_one");
- metaMgr.getKeyTable(getBucketLayout())
+ omMetadataManager.getKeyTable(getBucketLayout())
.put("/sampleVol/bucketOne/key_one", omKeyInfo);
- metaMgrCopy.getKeyTable(getBucketLayout())
+ reconOmMetadataManager.getKeyTable(getBucketLayout())
.put("/sampleVol/bucketOne/key_one", omKeyInfo);
// Delete the volume and key from target DB.
- metaMgr.getKeyTable(getBucketLayout())
+ omMetadataManager.getKeyTable(getBucketLayout())
.delete("/sampleVol/bucketOne/key_one");
- metaMgr.getVolumeTable().delete(volumeKey);
+ omMetadataManager.getVolumeTable().delete(volumeKey);
// Delete a non-existing volume and key
- metaMgr.getKeyTable(getBucketLayout())
+ omMetadataManager.getKeyTable(getBucketLayout())
.delete("/sampleVol/bucketOne/key_two");
- metaMgr.getVolumeTable().delete(metaMgr.getVolumeKey("nonExistingVolume"));
+ omMetadataManager.getVolumeTable()
+ .delete(omMetadataManager.getVolumeKey("nonExistingVolume"));
- RDBStore rdbStore = (RDBStore) metaMgr.getStore();
- RocksDB rocksDB = rdbStore.getDb();
- TransactionLogIterator transactionLogIterator =
- rocksDB.getUpdatesSince(3);
- List<byte[]> writeBatches = new ArrayList<>();
-
- while (transactionLogIterator.isValid()) {
- TransactionLogIterator.BatchResult result =
- transactionLogIterator.getBatch();
- result.writeBatch().markWalTerminationPoint();
- WriteBatch writeBatch = result.writeBatch();
- writeBatches.add(writeBatch.data());
- transactionLogIterator.next();
- }
-
- // OMDBUpdatesHandler has access to target DB. So it has the volume and
- // key.
- OMDBUpdatesHandler omdbUpdatesHandler =
- new OMDBUpdatesHandler(metaMgrCopy);
- for (byte[] data : writeBatches) {
- WriteBatch writeBatch = new WriteBatch(data);
- writeBatch.iterate(omdbUpdatesHandler);
- }
+ List<byte[]> writeBatches = getBytesFromOmMetaManager(3);
+ OMDBUpdatesHandler omdbUpdatesHandler = captureEvents(writeBatches);
List<OMDBUpdateEvent> events = omdbUpdatesHandler.getEvents();
assertEquals(4, events.size());
@@ -238,27 +200,145 @@ public class TestOMDBUpdatesHandler {
}
@Test
- public void testGetKeyType() throws IOException {
- OzoneConfiguration configuration = createNewTestPath();
- OmMetadataManagerImpl metaMgr = new OmMetadataManagerImpl(configuration);
+ public void testOperateOnSameEntry() throws Exception {
+ // Create 1 volume, 1 key and write to source OM DB.
+ String volumeKey = omMetadataManager.getVolumeKey("sampleVol");
+ OmVolumeArgs args =
+ OmVolumeArgs.newBuilder()
+ .setVolume("sampleVol")
+ .setAdminName("bilbo")
+ .setOwnerName("bilbo")
+ .build();
+ omMetadataManager.getVolumeTable().put(volumeKey, args);
+
+ OmKeyInfo key = getOmKeyInfo("sampleVol", "bucketOne", "key");
+ omMetadataManager.getKeyTable(getBucketLayout())
+ .put("/sampleVol/bucketOne/key", key);
+
+ OmKeyInfo keyNewValue = getOmKeyInfo("sampleVol", "bucketOne", "key_new");
+ omMetadataManager.getKeyTable(getBucketLayout())
+ .put("/sampleVol/bucketOne/key", keyNewValue);
+
+ OmKeyInfo keyNewValue2 = getOmKeyInfo("sampleVol", "bucketOne",
"key_new2");
+ omMetadataManager.getKeyTable(getBucketLayout())
+ .put("/sampleVol/bucketOne/key", keyNewValue2);
+
+ omMetadataManager.getKeyTable(getBucketLayout())
+ .delete("/sampleVol/bucketOne/key");
+ omMetadataManager.getKeyTable(getBucketLayout())
+ .delete("/sampleVol/bucketOne/key");
+ omMetadataManager.getKeyTable(getBucketLayout())
+ .put("/sampleVol/bucketOne/key", keyNewValue2);
+
+ List<byte[]> writeBatches = getBytesFromOmMetaManager(0);
+ OMDBUpdatesHandler omdbUpdatesHandler = captureEvents(writeBatches);
+ List<OMDBUpdateEvent> events = omdbUpdatesHandler.getEvents();
+ assertEquals(7, events.size());
+
+ OMDBUpdateEvent volEvent = events.get(0);
+ assertEquals(PUT, volEvent.getAction());
+ assertEquals(volumeKey, volEvent.getKey());
+ assertEquals(args.getVolume(), ((OmVolumeArgs)volEvent.getValue())
+ .getVolume());
+
+ OMDBUpdateEvent keyPutEvent = events.get(1);
+ assertEquals(PUT, keyPutEvent.getAction());
+ assertEquals("/sampleVol/bucketOne/key", keyPutEvent.getKey());
+ assertEquals("key",
+ ((OmKeyInfo)keyPutEvent.getValue()).getKeyName());
+ assertNull(keyPutEvent.getOldValue());
+
+ OMDBUpdateEvent keyUpdateEvent = events.get(2);
+ assertEquals(UPDATE, keyUpdateEvent.getAction());
+ assertEquals("/sampleVol/bucketOne/key", keyUpdateEvent.getKey());
+ assertEquals("key_new",
+ ((OmKeyInfo)keyUpdateEvent.getValue()).getKeyName());
+ assertNotNull(keyUpdateEvent.getOldValue());
+ assertEquals("key",
+ ((OmKeyInfo)keyUpdateEvent.getOldValue()).getKeyName());
+
+ OMDBUpdateEvent keyUpdateEvent2 = events.get(3);
+ assertEquals(UPDATE, keyUpdateEvent2.getAction());
+ assertEquals("/sampleVol/bucketOne/key", keyUpdateEvent2.getKey());
+ assertEquals("key_new2",
+ ((OmKeyInfo)keyUpdateEvent2.getValue()).getKeyName());
+ assertNotNull(keyUpdateEvent2.getOldValue());
+ assertEquals("key_new",
+ ((OmKeyInfo)keyUpdateEvent2.getOldValue()).getKeyName());
+
+ OMDBUpdateEvent keyDeleteEvent = events.get(4);
+ assertEquals(DELETE, keyDeleteEvent.getAction());
+ assertEquals("/sampleVol/bucketOne/key", keyDeleteEvent.getKey());
+ assertEquals("key_new2",
+ ((OmKeyInfo)keyDeleteEvent.getValue()).getKeyName());
+
+ OMDBUpdateEvent keyDeleteEvent2 = events.get(5);
+ assertEquals(DELETE, keyDeleteEvent2.getAction());
+ assertEquals("/sampleVol/bucketOne/key", keyDeleteEvent2.getKey());
+ assertEquals("key_new2",
+ ((OmKeyInfo)keyDeleteEvent2.getValue()).getKeyName());
+
+ OMDBUpdateEvent keyPut2 = events.get(6);
+ assertEquals(PUT, keyPut2.getAction());
+ assertEquals("/sampleVol/bucketOne/key", keyPut2.getKey());
+ assertEquals("key_new2",
+ ((OmKeyInfo)keyPut2.getValue()).getKeyName());
+ assertNotNull(keyPut2.getOldValue());
+ assertEquals("key_new2",
+ ((OmKeyInfo)keyPut2.getOldValue()).getKeyName());
+ }
+
+ @Test
+ public void testGetKeyType() throws IOException {
assertEquals(String.class, omdbDefinition.getKeyType(
- metaMgr.getKeyTable(getBucketLayout()).getName()).get());
+ omMetadataManager.getKeyTable(getBucketLayout()).getName()).get());
assertEquals(OzoneTokenIdentifier.class, omdbDefinition.getKeyType(
- metaMgr.getDelegationTokenTable().getName()).get());
+ omMetadataManager.getDelegationTokenTable().getName()).get());
}
@Test
public void testGetValueType() throws IOException {
- OzoneConfiguration configuration = createNewTestPath();
- OmMetadataManagerImpl metaMgr = new OmMetadataManagerImpl(configuration);
-
assertEquals(OmKeyInfo.class, omdbDefinition.getValueType(
- metaMgr.getKeyTable(getBucketLayout()).getName()).get());
+ omMetadataManager.getKeyTable(getBucketLayout()).getName()).get());
assertEquals(OmVolumeArgs.class, omdbDefinition.getValueType(
- metaMgr.getVolumeTable().getName()).get());
+ omMetadataManager.getVolumeTable().getName()).get());
assertEquals(OmBucketInfo.class, omdbDefinition.getValueType(
- metaMgr.getBucketTable().getName()).get());
+ omMetadataManager.getBucketTable().getName()).get());
+ }
+
+ @NotNull
+ private List<byte[]> getBytesFromOmMetaManager(int getUpdatesSince)
+ throws RocksDBException {
+ RDBStore rdbStore = (RDBStore) omMetadataManager.getStore();
+ RocksDB rocksDB = rdbStore.getDb();
+ // Get all updates from source DB
+ TransactionLogIterator transactionLogIterator =
+ rocksDB.getUpdatesSince(getUpdatesSince);
+ List<byte[]> writeBatches = new ArrayList<>();
+
+ while (transactionLogIterator.isValid()) {
+ TransactionLogIterator.BatchResult result =
+ transactionLogIterator.getBatch();
+ result.writeBatch().markWalTerminationPoint();
+ WriteBatch writeBatch = result.writeBatch();
+ writeBatches.add(writeBatch.data());
+ transactionLogIterator.next();
+ }
+ return writeBatches;
+ }
+
+ @NotNull
+ private OMDBUpdatesHandler captureEvents(List<byte[]> writeBatches)
+ throws RocksDBException {
+ OMDBUpdatesHandler omdbUpdatesHandler =
+ new OMDBUpdatesHandler(reconOmMetadataManager);
+ for (byte[] data : writeBatches) {
+ WriteBatch writeBatch = new WriteBatch(data);
+ // Capture the events from source DB.
+ writeBatch.iterate(omdbUpdatesHandler);
+ }
+ return omdbUpdatesHandler;
}
private OmKeyInfo getOmKeyInfo(String volumeName, String bucketName,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]