Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ public class OMDBUpdatesHandler extends ManagedWriteBatch.Handler {
private Map<Integer, String> tablesNames;
private OMMetadataManager omMetadataManager;
private List<OMDBUpdateEvent> omdbUpdateEvents = new ArrayList<>();
private Map<Object, OMDBUpdateEvent> omdbLatestUpdateEvents
= new HashMap<>();
private Map<String, Map<Object, OMDBUpdateEvent>> omdbLatestUpdateEvents = new HashMap<>();
private OMDBDefinition omdbDefinition;
private OmUpdateEventValidator omUpdateEventValidator;

Expand Down Expand Up @@ -112,6 +111,10 @@ private void processEvent(int cfIndex, byte[] keyBytes, byte[]
final Object key = cf.getKeyCodec().fromPersistedFormat(keyBytes);
builder.setKey(key);

// Initialize table-specific event map if it does not exist
omdbLatestUpdateEvents.putIfAbsent(tableName, new HashMap<>());
Map<Object, OMDBUpdateEvent> tableEventsMap = omdbLatestUpdateEvents.get(tableName);

// Handle the event based on its type:
// - PUT with a new key: Insert the new value.
// - PUT with an existing key: Update the existing value.
Expand All @@ -120,7 +123,7 @@ private void processEvent(int cfIndex, byte[] keyBytes, byte[]
// necessary.
Table table = omMetadataManager.getTable(tableName);

OMDBUpdateEvent latestEvent = omdbLatestUpdateEvents.get(key);
OMDBUpdateEvent latestEvent = tableEventsMap.get(key);
Object oldValue;
if (latestEvent != null) {
oldValue = latestEvent.getValue();
Expand Down Expand Up @@ -184,7 +187,7 @@ private void processEvent(int cfIndex, byte[] keyBytes, byte[]
"action = %s", tableName, action));
}
omdbUpdateEvents.add(event);
omdbLatestUpdateEvents.put(key, event);
tableEventsMap.put(key, event);
} else {
// Log and ignore events if key or value types are undetermined.
if (LOG.isWarnEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
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.RepeatedOmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OmDirectoryInfo;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
Expand Down Expand Up @@ -286,6 +288,71 @@ public void testOperateOnSameEntry() throws Exception {
((OmKeyInfo)keyPut2.getOldValue()).getKeyName());
}

/**
* Test to verify that events with duplicate keys in different tables
* (FileTable and DirectoryTable) are handled correctly without causing
* ClassCastException or event conflicts.
*
* This test simulates creating a file, deleting the file, and then creating
* a directory with the same name under the same parent ID in different tables.
* It ensures that the events are correctly processed and stored in the
* `omdbLatestUpdateEvents` map without causing any type mismatches or
* exceptions.
*
* @throws Exception if any error occurs during the test execution.
*/
@Test
public void testEventsHavingDuplicateRocksDBKey() throws Exception {
// Step 1: Create a file with the name "sameName" in the fileTable
OmKeyInfo fileKeyInfo = getOmKeyInfo("sampleVol", "bucketOne", "sameName");
omMetadataManager.getFileTable().put("/sampleVol/bucketOne/parentId/sameName", fileKeyInfo);

// Step 2: Delete the file by adding its information to the deletedTable
RepeatedOmKeyInfo repeatedKeyInfo = new RepeatedOmKeyInfo(fileKeyInfo);
omMetadataManager.getDeletedTable().put("/sampleVol/bucketOne/parentId/sameName", repeatedKeyInfo);

// Step 3: Create a directory with the same name "sameName" in the directoryTable
OmDirectoryInfo dirInfo = OmDirectoryInfo.newBuilder()
.setName("sameName")
.setParentObjectID(fileKeyInfo.getParentObjectID())
.setObjectID(fileKeyInfo.getObjectID())
.setCreationTime(System.currentTimeMillis())
.setModificationTime(System.currentTimeMillis())
.build();
omMetadataManager.getDirectoryTable().put("/sampleVol/bucketOne/parentId/sameName", dirInfo);

// Capture the events from the OM Metadata Manager
List<byte[]> writeBatches = getBytesFromOmMetaManager(0);
OMDBUpdatesHandler omdbUpdatesHandler = captureEvents(writeBatches);

// Retrieve the captured events and assert the correct number of events
List<OMDBUpdateEvent> events = omdbUpdatesHandler.getEvents();
// Verify no events were discarded
assertEquals(3, events.size());

// Validate the file creation event
OMDBUpdateEvent filePutEvent = events.get(0);
assertEquals(PUT, filePutEvent.getAction());
assertEquals("/sampleVol/bucketOne/parentId/sameName", filePutEvent.getKey());
assertEquals("sameName", ((OmKeyInfo) filePutEvent.getValue()).getKeyName());
assertNull(filePutEvent.getOldValue());

// Validate the file deletion event
OMDBUpdateEvent fileDeleteEvent = events.get(1);
assertEquals(PUT, fileDeleteEvent.getAction());
assertEquals("/sampleVol/bucketOne/parentId/sameName", fileDeleteEvent.getKey());
assertEquals("sameName",
((RepeatedOmKeyInfo) fileDeleteEvent.getValue()).getOmKeyInfoList().get(0).getKeyName());

// Validate the directory creation event
OMDBUpdateEvent dirPutEvent = events.get(2);
assertEquals(PUT, dirPutEvent.getAction());
assertEquals("/sampleVol/bucketOne/parentId/sameName", dirPutEvent.getKey());
assertEquals("sameName", ((OmDirectoryInfo) dirPutEvent.getValue()).getName());
// There will be no old value as the key was not present in the directoryTable before
assertNull(dirPutEvent.getOldValue());
}

@Test
public void testGetKeyType() throws IOException {
final String keyTable = omMetadataManager
Expand Down