Skip to content

Commit c789942

Browse files
committed
HDDS-15155. Add ozone debug ldb drop_column_family subcommand
Generated-by: GPT-5.5
1 parent e215b48 commit c789942

5 files changed

Lines changed: 547 additions & 0 deletions

File tree

hadoop-hdds/docs/content/tools/debug/Ldb.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Commands:
3535
list_column_families, ls list all column families in db.
3636
value-schema Schema of value in metadataTable
3737
checkpoint Create checkpoint for specified db
38+
drop_column_family Drop a column family from the DB.
3839
```
3940

4041
### list_column_families command
@@ -60,6 +61,17 @@ revokedCerts
6061
move
6162
```
6263

64+
### drop_column_family command
65+
66+
`drop_column_family` command drops a column family from the db provided. The service that owns the DB should be stopped
67+
before running this command. The command prompts for confirmation by default; use `-y` or `--yes` to skip the prompt.
68+
69+
```bash
70+
$ ozone debug ldb --db=/path/to/om.db drop_column_family --cf=deletedTable
71+
WARNING: Dropping a column family mutates RocksDB and can be unsafe if the DB is already open by an Ozone process. Ensure the service that owns this DB is stopped before running this command. Do you want to continue (y/N)? y
72+
Dropped column family deletedTable
73+
```
74+
6375
### scan command
6476
6577
`scan` command parses a particular column family of a rocksdb provided and prints the records.
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.hadoop.ozone.debug.ldb;
19+
20+
import static org.apache.hadoop.hdds.utils.db.DBStoreBuilder.DEFAULT_COLUMN_FAMILY_NAME;
21+
22+
import java.io.IOException;
23+
import java.io.InputStreamReader;
24+
import java.nio.charset.StandardCharsets;
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
import java.util.Scanner;
28+
import java.util.concurrent.Callable;
29+
import org.apache.hadoop.hdds.cli.AbstractSubcommand;
30+
import org.apache.hadoop.hdds.utils.IOUtils;
31+
import org.apache.hadoop.hdds.utils.db.RocksDatabase;
32+
import org.apache.hadoop.hdds.utils.db.managed.ManagedConfigOptions;
33+
import org.apache.hadoop.hdds.utils.db.managed.ManagedDBOptions;
34+
import org.apache.hadoop.hdds.utils.db.managed.ManagedRocksDB;
35+
import org.apache.hadoop.ozone.debug.RocksDBUtils;
36+
import org.rocksdb.ColumnFamilyDescriptor;
37+
import org.rocksdb.ColumnFamilyHandle;
38+
import org.rocksdb.RocksDBException;
39+
import picocli.CommandLine;
40+
41+
/**
42+
* Drop a column family from a RocksDB.
43+
*/
44+
@CommandLine.Command(
45+
name = "drop_column_family",
46+
aliases = "drop-column-family",
47+
description = "Drop a column family from the DB.")
48+
public class DropColumnFamily extends AbstractSubcommand
49+
implements Callable<Void> {
50+
51+
private static final String WARNING_TO_STOP_SERVICE =
52+
"WARNING: Dropping a column family mutates RocksDB and can be unsafe " +
53+
"if the DB is already open by an Ozone process. Ensure the service " +
54+
"that owns this DB is stopped before running this command. " +
55+
"Do you want to continue (y/N)? ";
56+
57+
@CommandLine.ParentCommand
58+
private RDBParser parent;
59+
60+
@CommandLine.Option(names = {"--column_family", "--column-family", "--cf"},
61+
required = true,
62+
description = "Column family name")
63+
private String columnFamilyName;
64+
65+
@CommandLine.Option(names = {"-y", "--yes"},
66+
description = "Continue without interactive user confirmation")
67+
private boolean yes;
68+
69+
@Override
70+
public Void call() throws Exception {
71+
if (isDefaultColumnFamily(columnFamilyName)) {
72+
throw new IllegalArgumentException(
73+
"Default column family cannot be dropped.");
74+
}
75+
if (!columnFamilyExists()) {
76+
throw new IllegalArgumentException(columnFamilyName
77+
+ " is not a column family in DB for the given path.");
78+
}
79+
80+
confirm();
81+
82+
ManagedConfigOptions configOptions = new ManagedConfigOptions();
83+
ManagedDBOptions dbOptions = new ManagedDBOptions();
84+
List<ColumnFamilyHandle> cfHandleList = new ArrayList<>();
85+
List<ColumnFamilyDescriptor> cfDescList = new ArrayList<>();
86+
87+
try (ManagedRocksDB db = ManagedRocksDB.openWithLatestOptions(
88+
configOptions, dbOptions, parent.getDbPath(), cfDescList,
89+
cfHandleList)) {
90+
ColumnFamilyHandle columnFamilyHandle =
91+
RocksDBUtils.getColumnFamilyHandle(columnFamilyName, cfHandleList);
92+
if (columnFamilyHandle == null) {
93+
throw new IllegalArgumentException(columnFamilyName
94+
+ " is not a column family in DB for the given path.");
95+
}
96+
97+
db.get().dropColumnFamily(columnFamilyHandle);
98+
out().println("Dropped column family " + columnFamilyName);
99+
} catch (RocksDBException exception) {
100+
String errorMessage = "Failed to drop column family " + columnFamilyName
101+
+ " from RocksDB for the given path: " + parent.getDbPath();
102+
throw new IOException(errorMessage, exception);
103+
} finally {
104+
IOUtils.closeQuietly(cfHandleList);
105+
closeDescriptors(cfDescList);
106+
IOUtils.closeQuietly(configOptions, dbOptions);
107+
}
108+
109+
return null;
110+
}
111+
112+
private static boolean isDefaultColumnFamily(String name) {
113+
return DEFAULT_COLUMN_FAMILY_NAME.equals(name);
114+
}
115+
116+
private void confirm() {
117+
if (yes) {
118+
return;
119+
}
120+
121+
err().print(WARNING_TO_STOP_SERVICE);
122+
err().flush();
123+
Scanner scanner = new Scanner(new InputStreamReader(
124+
System.in, StandardCharsets.UTF_8));
125+
String confirmation = scanner.hasNextLine()
126+
? scanner.nextLine().trim() : "";
127+
if (!"y".equalsIgnoreCase(confirmation)) {
128+
throw new IllegalStateException("Aborting command.");
129+
}
130+
}
131+
132+
private boolean columnFamilyExists() throws RocksDBException {
133+
for (byte[] columnFamily : RocksDatabase.listColumnFamiliesEmptyOptions(
134+
parent.getDbPath())) {
135+
if (columnFamilyName.equals(new String(columnFamily,
136+
StandardCharsets.UTF_8))) {
137+
return true;
138+
}
139+
}
140+
return false;
141+
}
142+
143+
private static void closeDescriptors(
144+
List<ColumnFamilyDescriptor> descriptors) {
145+
descriptors.forEach(descriptor -> descriptor.getOptions().close());
146+
}
147+
}

hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/ldb/RDBParser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
ListTables.class,
3232
ValueSchema.class,
3333
Checkpoint.class,
34+
DropColumnFamily.class,
3435
},
3536
description = "Parse rocksdb file content")
3637
@MetaInfServices(DebugSubcommand.class)

0 commit comments

Comments
 (0)