Skip to content

Commit 2b7b8e0

Browse files
committed
Refactor ObjectStorageAdmin
1 parent 6fba352 commit 2b7b8e0

File tree

2 files changed

+104
-172
lines changed

2 files changed

+104
-172
lines changed

core/src/main/java/com/scalar/db/storage/objectstorage/ObjectStorageAdmin.java

Lines changed: 100 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,20 @@ public void close() {
7878
public void createNamespace(String namespace, Map<String, String> options)
7979
throws ExecutionException {
8080
try {
81-
insertNamespaceMetadata(namespace);
81+
// Insert the namespace metadata
82+
Map<String, String> readVersionMap = new HashMap<>();
83+
Map<String, ObjectStorageNamespaceMetadata> metadataTable =
84+
getNamespaceMetadataTable(readVersionMap);
85+
assert !metadataTable.containsKey(namespace);
86+
if (metadataTable.isEmpty()) {
87+
Map<String, ObjectStorageNamespaceMetadata> newMetadataTable =
88+
Collections.singletonMap(namespace, new ObjectStorageNamespaceMetadata(namespace));
89+
insertMetadataTable(NAMESPACE_METADATA_TABLE, newMetadataTable);
90+
} else {
91+
metadataTable.put(namespace, new ObjectStorageNamespaceMetadata(namespace));
92+
updateMetadataTable(
93+
NAMESPACE_METADATA_TABLE, metadataTable, readVersionMap.get(NAMESPACE_METADATA_TABLE));
94+
}
8295
} catch (Exception e) {
8396
throw new ExecutionException(
8497
String.format("Failed to create the namespace %s", namespace), e);
@@ -90,7 +103,20 @@ public void createTable(
90103
String namespace, String table, TableMetadata metadata, Map<String, String> options)
91104
throws ExecutionException {
92105
try {
93-
insertTableMetadata(namespace, table, metadata);
106+
// Insert the table metadata
107+
String tableMetadataKey = getTableMetadataKey(namespace, table);
108+
Map<String, String> readVersionMap = new HashMap<>();
109+
Map<String, ObjectStorageTableMetadata> metadataTable = getTableMetadataTable(readVersionMap);
110+
assert !metadataTable.containsKey(tableMetadataKey);
111+
if (metadataTable.isEmpty()) {
112+
Map<String, ObjectStorageTableMetadata> newMetadataTable =
113+
Collections.singletonMap(tableMetadataKey, new ObjectStorageTableMetadata(metadata));
114+
insertMetadataTable(TABLE_METADATA_TABLE, newMetadataTable);
115+
} else {
116+
metadataTable.put(tableMetadataKey, new ObjectStorageTableMetadata(metadata));
117+
updateMetadataTable(
118+
TABLE_METADATA_TABLE, metadataTable, readVersionMap.get(TABLE_METADATA_TABLE));
119+
}
94120
} catch (Exception e) {
95121
throw new ExecutionException(
96122
String.format(
@@ -103,7 +129,18 @@ public void createTable(
103129
public void dropTable(String namespace, String table) throws ExecutionException {
104130
try {
105131
deleteTableData(namespace, table);
106-
deleteTableMetadata(namespace, table);
132+
// Delete the table metadata
133+
String tableMetadataKey = getTableMetadataKey(namespace, table);
134+
Map<String, String> readVersionMap = new HashMap<>();
135+
Map<String, ObjectStorageTableMetadata> metadataTable = getTableMetadataTable(readVersionMap);
136+
assert metadataTable.containsKey(tableMetadataKey);
137+
metadataTable.remove(tableMetadataKey);
138+
String readVersion = readVersionMap.get(TABLE_METADATA_TABLE);
139+
if (metadataTable.isEmpty()) {
140+
deleteMetadataTable(TABLE_METADATA_TABLE, readVersion);
141+
} else {
142+
updateMetadataTable(TABLE_METADATA_TABLE, metadataTable, readVersion);
143+
}
107144
} catch (Exception e) {
108145
throw new ExecutionException(
109146
String.format(
@@ -130,7 +167,18 @@ public void dropIndex(String namespace, String table, String columnName)
130167
@Override
131168
public void dropNamespace(String namespace) throws ExecutionException {
132169
try {
133-
deleteNamespaceMetadata(namespace);
170+
// Delete the namespace metadata
171+
Map<String, String> readVersionMap = new HashMap<>();
172+
Map<String, ObjectStorageNamespaceMetadata> metadataTable =
173+
getNamespaceMetadataTable(readVersionMap);
174+
assert metadataTable.containsKey(namespace);
175+
metadataTable.remove(namespace);
176+
String readVersion = readVersionMap.get(NAMESPACE_METADATA_TABLE);
177+
if (metadataTable.isEmpty()) {
178+
deleteMetadataTable(NAMESPACE_METADATA_TABLE, readVersion);
179+
} else {
180+
updateMetadataTable(NAMESPACE_METADATA_TABLE, metadataTable, readVersion);
181+
}
134182
} catch (Exception e) {
135183
throw new ExecutionException(String.format("Failed to drop the namespace %s", namespace), e);
136184
}
@@ -201,7 +249,19 @@ public boolean namespaceExists(String namespace) throws ExecutionException {
201249
public void repairNamespace(String namespace, Map<String, String> options)
202250
throws ExecutionException {
203251
try {
204-
upsertNamespaceMetadata(namespace);
252+
// Upsert the namespace metadata
253+
Map<String, String> readVersionMap = new HashMap<>();
254+
Map<String, ObjectStorageNamespaceMetadata> metadataTable =
255+
getNamespaceMetadataTable(readVersionMap);
256+
if (metadataTable.isEmpty()) {
257+
insertMetadataTable(
258+
NAMESPACE_METADATA_TABLE,
259+
Collections.singletonMap(namespace, new ObjectStorageNamespaceMetadata(namespace)));
260+
} else {
261+
metadataTable.put(namespace, new ObjectStorageNamespaceMetadata(namespace));
262+
updateMetadataTable(
263+
NAMESPACE_METADATA_TABLE, metadataTable, readVersionMap.get(NAMESPACE_METADATA_TABLE));
264+
}
205265
} catch (Exception e) {
206266
throw new ExecutionException(
207267
String.format("Failed to repair the namespace %s", namespace), e);
@@ -224,7 +284,19 @@ public void repairTable(
224284
String namespace, String table, TableMetadata metadata, Map<String, String> options)
225285
throws ExecutionException {
226286
try {
227-
upsertTableMetadata(namespace, table, metadata);
287+
// Upsert the table metadata
288+
String tableMetadataKey = getTableMetadataKey(namespace, table);
289+
Map<String, String> readVersionMap = new HashMap<>();
290+
Map<String, ObjectStorageTableMetadata> metadataTable = getTableMetadataTable(readVersionMap);
291+
if (metadataTable.isEmpty()) {
292+
insertMetadataTable(
293+
TABLE_METADATA_TABLE,
294+
Collections.singletonMap(tableMetadataKey, new ObjectStorageTableMetadata(metadata)));
295+
} else {
296+
metadataTable.put(tableMetadataKey, new ObjectStorageTableMetadata(metadata));
297+
updateMetadataTable(
298+
TABLE_METADATA_TABLE, metadataTable, readVersionMap.get(TABLE_METADATA_TABLE));
299+
}
228300
} catch (Exception e) {
229301
throw new ExecutionException(
230302
String.format(
@@ -238,10 +310,16 @@ public void addNewColumnToTable(
238310
String namespace, String table, String columnName, DataType columnType)
239311
throws ExecutionException {
240312
try {
241-
TableMetadata currentTableMetadata = getTableMetadata(namespace, table);
313+
// Update the table metadata
314+
String tableMetadataKey = getTableMetadataKey(namespace, table);
315+
Map<String, String> readVersionMap = new HashMap<>();
316+
Map<String, ObjectStorageTableMetadata> metadataTable = getTableMetadataTable(readVersionMap);
317+
TableMetadata currentTableMetadata = metadataTable.get(tableMetadataKey).toTableMetadata();
242318
TableMetadata updatedTableMetadata =
243319
TableMetadata.newBuilder(currentTableMetadata).addColumn(columnName, columnType).build();
244-
upsertTableMetadata(namespace, table, updatedTableMetadata);
320+
metadataTable.put(tableMetadataKey, new ObjectStorageTableMetadata(updatedTableMetadata));
321+
updateMetadataTable(
322+
TABLE_METADATA_TABLE, metadataTable, readVersionMap.get(TABLE_METADATA_TABLE));
245323
} catch (Exception e) {
246324
throw new ExecutionException(
247325
String.format(
@@ -293,151 +371,31 @@ public Set<String> getNamespaceNames() throws ExecutionException {
293371
@Override
294372
public void upgrade(Map<String, String> options) throws ExecutionException {
295373
try {
296-
Map<String, ObjectStorageTableMetadata> metadataTable = getTableMetadataTable();
374+
// Get all namespace names from the table metadata table
375+
Map<String, ObjectStorageTableMetadata> tableMetadataTable = getTableMetadataTable();
297376
List<String> namespaceNames =
298-
metadataTable.keySet().stream()
377+
tableMetadataTable.keySet().stream()
299378
.map(ObjectStorageAdmin::getNamespaceNameFromTableMetadataKey)
300379
.distinct()
301380
.collect(Collectors.toList());
302-
for (String namespaceName : namespaceNames) {
303-
upsertNamespaceMetadata(namespaceName);
304-
}
305-
} catch (Exception e) {
306-
throw new ExecutionException("Failed to upgrade", e);
307-
}
308-
}
309-
310-
private void insertNamespaceMetadata(String namespace) throws ExecutionException {
311-
try {
381+
// Upsert the namespace metadata table
312382
Map<String, String> readVersionMap = new HashMap<>();
313-
Map<String, ObjectStorageNamespaceMetadata> metadataTable =
383+
Map<String, ObjectStorageNamespaceMetadata> namespaceMetadataTable =
314384
getNamespaceMetadataTable(readVersionMap);
315-
if (metadataTable.containsKey(namespace)) {
316-
throw new ExecutionException(
317-
String.format("The namespace metadata already exists: %s", namespace));
318-
}
319-
if (metadataTable.isEmpty()) {
320-
insertMetadataTable(
321-
NAMESPACE_METADATA_TABLE,
322-
Collections.singletonMap(namespace, new ObjectStorageNamespaceMetadata(namespace)));
323-
} else {
324-
metadataTable.put(namespace, new ObjectStorageNamespaceMetadata(namespace));
325-
updateMetadataTable(
326-
NAMESPACE_METADATA_TABLE, metadataTable, readVersionMap.get(NAMESPACE_METADATA_TABLE));
327-
}
328-
} catch (Exception e) {
329-
throw new ExecutionException(
330-
String.format("Failed to insert the namespace metadata: %s", namespace), e);
331-
}
332-
}
333-
334-
private void insertTableMetadata(String namespace, String table, TableMetadata metadata)
335-
throws ExecutionException {
336-
String tableMetadataKey = getTableMetadataKey(namespace, table);
337-
try {
338-
Map<String, String> readVersionMap = new HashMap<>();
339-
Map<String, ObjectStorageTableMetadata> metadataTable = getTableMetadataTable(readVersionMap);
340-
if (metadataTable.containsKey(tableMetadataKey)) {
341-
throw new ExecutionException(
342-
String.format("The table metadata already exists: %s", tableMetadataKey));
343-
}
344-
if (metadataTable.isEmpty()) {
345-
insertMetadataTable(
346-
TABLE_METADATA_TABLE,
347-
Collections.singletonMap(tableMetadataKey, new ObjectStorageTableMetadata(metadata)));
385+
Map<String, ObjectStorageNamespaceMetadata> newNamespaceMetadataTable =
386+
namespaceNames.stream()
387+
.collect(
388+
Collectors.toMap(namespace -> namespace, ObjectStorageNamespaceMetadata::new));
389+
if (namespaceMetadataTable.isEmpty()) {
390+
insertMetadataTable(NAMESPACE_METADATA_TABLE, newNamespaceMetadataTable);
348391
} else {
349-
metadataTable.put(tableMetadataKey, new ObjectStorageTableMetadata(metadata));
350392
updateMetadataTable(
351-
TABLE_METADATA_TABLE, metadataTable, readVersionMap.get(TABLE_METADATA_TABLE));
352-
}
353-
} catch (Exception e) {
354-
throw new ExecutionException(
355-
String.format("Failed to insert the table metadata: %s", tableMetadataKey), e);
356-
}
357-
}
358-
359-
private void upsertNamespaceMetadata(String namespace) throws ExecutionException {
360-
try {
361-
Map<String, String> readVersionMap = new HashMap<>();
362-
Map<String, ObjectStorageNamespaceMetadata> metadataTable =
363-
getNamespaceMetadataTable(readVersionMap);
364-
if (metadataTable.isEmpty()) {
365-
insertMetadataTable(
366393
NAMESPACE_METADATA_TABLE,
367-
Collections.singletonMap(namespace, new ObjectStorageNamespaceMetadata(namespace)));
368-
} else {
369-
metadataTable.put(namespace, new ObjectStorageNamespaceMetadata(namespace));
370-
updateMetadataTable(
371-
NAMESPACE_METADATA_TABLE, metadataTable, readVersionMap.get(NAMESPACE_METADATA_TABLE));
394+
newNamespaceMetadataTable,
395+
readVersionMap.get(NAMESPACE_METADATA_TABLE));
372396
}
373397
} catch (Exception e) {
374-
throw new ExecutionException(
375-
String.format("Failed to upsert the namespace metadata: %s", namespace), e);
376-
}
377-
}
378-
379-
private void upsertTableMetadata(String namespace, String table, TableMetadata metadata)
380-
throws ExecutionException {
381-
String tableMetadataKey = getTableMetadataKey(namespace, table);
382-
try {
383-
Map<String, String> readVersionMap = new HashMap<>();
384-
Map<String, ObjectStorageTableMetadata> metadataTable = getTableMetadataTable(readVersionMap);
385-
if (metadataTable.isEmpty()) {
386-
insertMetadataTable(
387-
TABLE_METADATA_TABLE,
388-
Collections.singletonMap(tableMetadataKey, new ObjectStorageTableMetadata(metadata)));
389-
} else {
390-
metadataTable.put(tableMetadataKey, new ObjectStorageTableMetadata(metadata));
391-
updateMetadataTable(
392-
TABLE_METADATA_TABLE, metadataTable, readVersionMap.get(TABLE_METADATA_TABLE));
393-
}
394-
} catch (Exception e) {
395-
throw new ExecutionException(
396-
String.format("Failed to upsert the table metadata: %s", tableMetadataKey), e);
397-
}
398-
}
399-
400-
private void deleteNamespaceMetadata(String namespace) throws ExecutionException {
401-
try {
402-
Map<String, String> readVersionMap = new HashMap<>();
403-
Map<String, ObjectStorageNamespaceMetadata> metadataTable =
404-
getNamespaceMetadataTable(readVersionMap);
405-
if (metadataTable.isEmpty() || !metadataTable.containsKey(namespace)) {
406-
throw new ExecutionException(
407-
String.format("The namespace metadata does not exist: %s", namespace));
408-
}
409-
metadataTable.remove(namespace);
410-
String readVersion = readVersionMap.get(NAMESPACE_METADATA_TABLE);
411-
if (metadataTable.isEmpty()) {
412-
deleteMetadataTable(NAMESPACE_METADATA_TABLE, readVersion);
413-
} else {
414-
updateMetadataTable(NAMESPACE_METADATA_TABLE, metadataTable, readVersion);
415-
}
416-
} catch (Exception e) {
417-
throw new ExecutionException(
418-
String.format("Failed to delete the namespace metadata: %s", namespace), e);
419-
}
420-
}
421-
422-
private void deleteTableMetadata(String namespace, String table) throws ExecutionException {
423-
String tableMetadataKey = getTableMetadataKey(namespace, table);
424-
try {
425-
Map<String, String> readVersionMap = new HashMap<>();
426-
Map<String, ObjectStorageTableMetadata> metadataTable = getTableMetadataTable(readVersionMap);
427-
if (metadataTable.isEmpty() || !metadataTable.containsKey(tableMetadataKey)) {
428-
throw new ExecutionException(
429-
String.format("The table metadata does not exist: %s", tableMetadataKey));
430-
}
431-
metadataTable.remove(tableMetadataKey);
432-
String readVersion = readVersionMap.get(TABLE_METADATA_TABLE);
433-
if (metadataTable.isEmpty()) {
434-
deleteMetadataTable(TABLE_METADATA_TABLE, readVersion);
435-
} else {
436-
updateMetadataTable(TABLE_METADATA_TABLE, metadataTable, readVersion);
437-
}
438-
} catch (Exception e) {
439-
throw new ExecutionException(
440-
String.format("Failed to delete the table metadata: %s", tableMetadataKey), e);
398+
throw new ExecutionException("Failed to upgrade", e);
441399
}
442400
}
443401

core/src/test/java/com/scalar/db/storage/objectstorage/ObjectStorageAdminTest.java

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -614,11 +614,6 @@ public void upgrade_WithExistingTables_ShouldUpsertNamespaces() throws Exception
614614
String tableMetadataKey2 = "ns1" + ObjectStorageUtils.CONCATENATED_KEY_DELIMITER + "tbl2";
615615
String tableMetadataKey3 = "ns2" + ObjectStorageUtils.CONCATENATED_KEY_DELIMITER + "tbl3";
616616

617-
Map<String, ObjectStorageNamespaceMetadata> namespaceMetadataMap = new HashMap<>();
618-
String serializedNamespaceMetadata = Serializer.serialize(namespaceMetadataMap);
619-
ObjectStorageWrapperResponse namespaceMetadataResponse =
620-
new ObjectStorageWrapperResponse(serializedNamespaceMetadata, "version2");
621-
622617
String tableMetadataObjectKey =
623618
ObjectStorageUtils.getObjectKey(
624619
METADATA_NAMESPACE, ObjectStorageAdmin.TABLE_METADATA_TABLE);
@@ -636,41 +631,20 @@ public void upgrade_WithExistingTables_ShouldUpsertNamespaces() throws Exception
636631
new ObjectStorageWrapperResponse(serializedTableMetadata, "version1");
637632
when(wrapper.get(tableMetadataObjectKey)).thenReturn(Optional.of(tableMetadataResponse));
638633

639-
// First call returns empty namespace metadata, second call returns metadata with ns1
640-
Map<String, ObjectStorageNamespaceMetadata> namespaceMetadataMapAfterInsert = new HashMap<>();
641-
namespaceMetadataMapAfterInsert.put("ns1", new ObjectStorageNamespaceMetadata("ns1"));
642-
String serializedNamespaceMetadataAfterInsert =
643-
Serializer.serialize(namespaceMetadataMapAfterInsert);
644-
ObjectStorageWrapperResponse namespaceMetadataResponseAfterInsert =
645-
new ObjectStorageWrapperResponse(serializedNamespaceMetadataAfterInsert, "version3");
646-
when(wrapper.get(namespaceMetadataObjectKey))
647-
.thenReturn(Optional.of(namespaceMetadataResponse))
648-
.thenReturn(Optional.of(namespaceMetadataResponseAfterInsert));
634+
// Mock non-existing namespace metadata
635+
when(wrapper.get(namespaceMetadataObjectKey)).thenReturn(Optional.empty());
649636

650637
// Act
651638
admin.upgrade(Collections.emptyMap());
652639

653640
// Assert
654-
// First namespace should trigger insert when metadata table is empty
641+
verify(wrapper).get(tableMetadataObjectKey);
655642
verify(wrapper).insert(objectKeyCaptor.capture(), payloadCaptor.capture());
656643

657644
Map<String, ObjectStorageNamespaceMetadata> insertedMetadata =
658645
Serializer.deserialize(
659646
payloadCaptor.getValue(),
660647
new TypeReference<Map<String, ObjectStorageNamespaceMetadata>>() {});
661-
assertThat(insertedMetadata).containsKey("ns1");
662-
663-
// Second namespace should trigger update (when metadata table is not empty)
664-
verify(wrapper)
665-
.update(
666-
eq(namespaceMetadataObjectKey),
667-
payloadCaptor.capture(),
668-
eq(namespaceMetadataResponseAfterInsert.getVersion()));
669-
670-
Map<String, ObjectStorageNamespaceMetadata> updatedMetadata =
671-
Serializer.deserialize(
672-
payloadCaptor.getValue(),
673-
new TypeReference<Map<String, ObjectStorageNamespaceMetadata>>() {});
674-
assertThat(updatedMetadata).containsKeys("ns1", "ns2");
648+
assertThat(insertedMetadata).containsKeys("ns1", "ns2");
675649
}
676650
}

0 commit comments

Comments
 (0)