Skip to content

Commit 486b399

Browse files
fix(toplingdb): align explicit provider configuration
1 parent 7c7e363 commit 486b399

8 files changed

Lines changed: 187 additions & 65 deletions

File tree

.specs/hugegraph-server/ToplingDB/design.md

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -40,34 +40,39 @@ sequenceDiagram
4040

4141
### RocksDB Startup Logic
4242

43-
Use reflection to detect whether ToplingDB APIs are available. If present, attempt to start the storage engine using ToplingDB; otherwise, fall back to standard RocksDB APIs.
43+
HugeGraph routes the main RocksDB open/close paths through `RocksDBProviderLoader`.
44+
Providers are discovered via Java SPI, but the active provider is selected explicitly by
45+
`rocksdb.provider`. `standard` uses vanilla RocksDB; `topling` requires
46+
`org.rocksdb.SidePluginRepo` to be available at runtime.
4447

4548
```mermaid
4649
sequenceDiagram
4750
autonumber
48-
participant Store as HugeGraph Store
51+
participant Store as HugeGraph Server/PD/Store
4952
participant Config as HugeConfig
50-
participant Sessions as RocksDBStdSessions
51-
participant SPR as SidePluginRepo (Reflection)
53+
participant Loader as RocksDBProviderLoader
54+
participant Provider as Configured Provider
5255
participant Repo as Repo Instance
5356
participant Rocks as RocksDB
5457
55-
Store->>Config: Read OPTION_PATH / OPEN_HTTP
56-
Store->>Sessions: Create Sessions(..., optionPath, openHttp)
57-
alt optionPath provided and SPR available
58-
Sessions->>SPR: Reflectively load/create Repo
59-
Sessions->>Repo: importAutoFile(optionPath)
60-
Sessions->>Repo: open (with JSON descriptor)
61-
opt openHttp is true and instance is GRAPH_STORE
62-
Sessions->>Repo: startHttpServer()
58+
Store->>Config: Read PROVIDER / OPTION_PATH / OPEN_HTTP
59+
Store->>Loader: selectProviderIfNeeded(provider)
60+
Store->>Loader: openRocksDB(..., optionPath, openHttp)
61+
Loader->>Provider: openRocksDB(...)
62+
alt provider is standard
63+
Provider->>Rocks: RocksDB.open(...)
64+
else provider is topling and optionPath valid
65+
Provider->>Repo: Reflectively create SidePluginRepo
66+
Provider->>Repo: importAutoFile(optionPath)
67+
Provider->>Repo: openDB(JSON descriptor)
68+
opt Server openHttp is true and instance is GRAPH_STORE
69+
Provider->>Repo: startHttpServer()
6370
end
64-
Sessions->>Rocks: Get RocksDB instance (with CF handles)
65-
Sessions-->>Store: Return OpenedRocksDB(repo, handles)
66-
else optionPath not provided or SPR unavailable
67-
Sessions->>Rocks: Standard open()
68-
Sessions-->>Store: Return OpenedRocksDB(null, handles)
71+
else provider is topling but optionPath pre-validation fails
72+
Provider->>Rocks: RocksDB.open(...)
6973
end
70-
note over Store,Sessions: On shutdown, if repo exists, call repo.closeAllDB()
74+
Loader-->>Store: Return RocksDB instance
75+
note over Store,Loader: On shutdown, close through the active provider; Topling closes Repo when present.
7176
```
7277

7378
## Involved Modules
@@ -168,19 +173,30 @@ Both `init-hugegraph.sh` and `start-hugegraph.sh` now invoke `preload-topling.sh
168173

169174
### HugeGraph Configuration Options for RocksDB
170175

171-
Two new configuration options were added to `hugegraph.properties`: `option_path` for the YAML file and `open_http` to enable the Web Server.
176+
Three RocksDB provider options were added: `provider` selects standard RocksDB or ToplingDB,
177+
`option_path` points to the YAML file, and `open_http` enables the Web Server.
172178

173179
```properties
174180
# rocksdb backend config
175181
#rocksdb.data_path=/path/to/disk
176182
#rocksdb.wal_path=/path/to/disk
177-
#rocksdb.option_path=./conf/graphs/rocksdb_plus.yaml
183+
#rocksdb.provider=topling
184+
#rocksdb.option_path=./conf/graphs/rocksdb_server.yaml
178185
#rocksdb.open_http=true
179186
```
180187

181188
Java-side parsing and default values:
182189

183190
```java
191+
public static final ConfigOption<String> PROVIDER =
192+
new ConfigOption<>(
193+
"rocksdb.provider",
194+
"The RocksDB engine provider. 'standard' for vanilla RocksDB, "
195+
+ "'topling' for ToplingDB (requires addon installation).",
196+
allowValues("standard", "topling"),
197+
"standard"
198+
);
199+
184200
public static final ConfigOption<String> OPTION_PATH =
185201
new ConfigOption<>(
186202
"rocksdb.option_path",
@@ -200,29 +216,30 @@ public static final ConfigOption<Boolean> OPEN_HTTP =
200216

201217
### ToplingDB Startup Logic
202218

203-
When `option_path` is configured and the JAR contains ToplingDB APIs, HugeGraph will load the YAML file and start ToplingDB. Otherwise, it falls back to standard RocksDB.
219+
When `rocksdb.provider=topling`, `option_path` is configured, pre-validation passes, and the JAR
220+
contains ToplingDB APIs, HugeGraph will load the YAML file and start ToplingDB. If
221+
`rocksdb.provider=standard`, HugeGraph uses standard RocksDB.
204222

205-
To keep port configuration simple, the Web Server is only enabled for the `GRAPH_STORE` instance.
223+
For HugeGraph Server, the Web Server is only enabled for the `GRAPH_STORE` instance. PD and
224+
Store pass their component-level HTTP flag to the provider.
206225

207226
```mermaid
208227
flowchart LR
209-
A[Start Initialization] --> B{Is optionPath provided?}
210-
211-
B -- No --> Z[Use standard RocksDB to open DB] --> O[Finish standard init]
212-
213-
B -- Yes --> C{Is SidePluginRepo class available?}
214-
C -- No --> Z
228+
A[Start Initialization] --> P{rocksdb.provider}
229+
P -- standard --> Z[Use StandardRocksDBProvider] --> O[Finish standard init]
230+
P -- topling --> S{Is SidePluginRepo available?}
231+
S -- No --> F[Fail startup]
232+
S -- Yes --> B{Is optionPath provided and valid?}
215233
216-
C -- Yes --> D[Set useTopling = true] --> E["Load SidePluginRepo class and call importAutoFile(optionPath)"]
234+
B -- No --> Z
235+
B -- Yes --> E["ToplingRocksDBProvider calls importAutoFile(optionPath)"]
217236
218-
E --> K{Is openHttp true?}
237+
E --> K{Should this component start HTTP?}
219238
K -- No --> M[Finish Topling init]
220-
K -- Yes --> L{Is dbName GRAPH_STORE?}
221-
L -- No --> M
222-
L -- Yes --> N["startHttpServer()"] --> M
239+
K -- Yes --> N["startHttpServer()"] --> M
223240
```
224241

225242
## Design Decisions and Rationale
226243

227-
1. **Why is the Web Server only started for GRAPH_STORE?**
244+
1. **Why does HugeGraph Server only start the Web Server for GRAPH_STORE?**
228245
- All graph data is stored in GRAPH_STORE, and performance tuning and observability are primarily focused on this instance.

.specs/hugegraph-server/ToplingDB/task.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ When using an IDE such as IntelliJ IDEA, you need to configure the following env
1212

1313
```shell
1414
LD_LIBRARY_PATH=/path/to/your/library:$LD_LIBRARY_PATH
15-
LD_PRELOAD=libjemalloc.so:librocksdbjni-linux64.so
15+
LD_PRELOAD=/path/to/libjemalloc.so:/path/to/your/library/librocksdbjni-linux64.so
1616
```
1717

1818
When running from the terminal, simply use `init-store.sh` and `start-hugegraph.sh`, as `preload-topling.sh` is already embedded in these scripts.
@@ -25,9 +25,10 @@ When running from the terminal, simply use `init-store.sh` and `start-hugegraph.
2525

2626
## 2. Compatibility with ToplingDB and Standard RocksDB
2727

28-
- [x] **2.1 Modify openRocksDB logic in RocksDBStdSession**
29-
- Use reflection to detect whether the current JAR contains ToplingDB APIs; if so, start the storage engine using ToplingDB
30-
- If not available, fall back to the standard RocksDB API for engine startup
28+
- [x] **2.1 Add a RocksDB provider SPI and route main open/close paths through it**
29+
- Use `RocksDBProviderLoader` to discover standard RocksDB and ToplingDB providers
30+
- Select the active provider explicitly with `rocksdb.provider`
31+
- Use reflection in `ToplingRocksDBProvider` to detect whether the current JAR contains `org.rocksdb.SidePluginRepo`
3132

3233
## 3. Add Configuration Options for ToplingDB in HugeGraph
3334

@@ -40,7 +41,12 @@ When running from the terminal, simply use `init-store.sh` and `start-hugegraph.
4041
- Type: boolean, used to specify whether to enable the ToplingDB Web Server
4142
- Allow users to configure Web Server activation via `rocksdb.open_http` in `hugegraph.properties`
4243
- The Web Server port is defined in the YAML file specified by `option_path`, under `http.listening_ports`
43-
- For simplicity, the Web Server is only enabled for the `GRAPH_STORE` instance that stores graph data
44+
- For HugeGraph Server, the Web Server is only enabled for the `GRAPH_STORE` instance that stores graph data
45+
46+
- [x] **3.3 Add `rocksdb.provider` configuration**
47+
- Type: string, valid values: `standard` and `topling`
48+
- Default: `standard`
49+
- Prevent ToplingDB from being enabled implicitly just because a ToplingDB-capable JAR is on the classpath
4450

4551
## 4. End-to-End Performance Testing
4652

docs/toplingdb/toplingdb-troubleshooting.md

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
## Issues
44

5-
### Issue 1: Startup Failure Due to YAML Format Error
5+
### Issue 1: YAML Configuration Error
66

77
Sample log output:
88

99
```java
10-
2025-10-15 01:55:50 [db-open-1] [INFO] o.a.h.b.s.r.RocksDBStdSessions - SidePluginRepo found. Will attempt to open multi CFs RocksDB using Topling plugin.
11-
21:1: (891B):ERROR:
10+
2025-10-15 01:55:50 [db-open-1] [INFO] o.a.h.r.p.ToplingRocksDBProvider - SidePluginRepo found. Will attempt to open default CF RocksDB using Topling.
11+
21:1: (891B):ERROR:
1212
sideplugin/rockside/3rdparty/rapidyaml/src/c4/yml/parse.cpp:3310: ERROR parsing yml: parse error: incorrect indentation?
1313
```
1414

@@ -18,19 +18,49 @@ sideplugin/rockside/3rdparty/rapidyaml/src/c4/yml/parse.cpp:3310: ERROR parsing
1818
2. Validate YAML syntax:
1919

2020
```bash
21-
python -c "import yaml; yaml.safe_load(open('conf/graphs/rocksdb_plus.yaml'))"
21+
python -c "import yaml; yaml.safe_load(open('conf/graphs/rocksdb_server.yaml'))"
2222
```
2323

2424
3. Review the specific error message in the logs for further clues.
2525

26+
HugeGraph performs basic path and YAML validation before enabling ToplingDB. If this
27+
pre-validation fails, HugeGraph falls back to standard RocksDB behavior inside the ToplingDB
28+
provider. If the file passes basic YAML validation but `SidePluginRepo.importAutoFile()` or
29+
`openDB()` fails, startup fails with the corresponding ToplingDB error and the YAML file should
30+
be fixed.
31+
2632
---
2733

28-
### Issue 2: Web Server Port Conflict
34+
### Issue 2: ToplingDB Provider Not Available
35+
36+
When `rocksdb.provider=topling` is configured but the runtime `rocksdbjni` JAR does not contain
37+
`org.rocksdb.SidePluginRepo`, HugeGraph fails provider activation instead of silently switching
38+
to the standard provider.
39+
40+
**Solution**:
41+
42+
1. If you want standard RocksDB, set:
43+
44+
```properties
45+
rocksdb.provider=standard
46+
```
47+
48+
2. If you want ToplingDB, confirm that Maven or the deployment addon provides a ToplingDB-capable
49+
`rocksdbjni` artifact.
50+
3. Inspect the runtime JAR:
51+
52+
```bash
53+
jar tf lib/rocksdbjni-*.jar | grep org/rocksdb/SidePluginRepo.class
54+
```
55+
56+
---
57+
58+
### Issue 3: Web Server Port Conflict
2959

3060
Sample log output:
3161

3262
```java
33-
2025-10-15 01:57:34 [db-open-1] [INFO] o.a.h.b.s.r.RocksDBStdSessions - SidePluginRepo found. Will attempt to open multi CFs RocksDB using Topling plugin.
63+
2025-10-15 01:57:34 [db-open-1] [INFO] o.a.h.r.p.ToplingRocksDBProvider - SidePluginRepo found. Will attempt to open default CF RocksDB using Topling.
3464
2025-10-15 01:57:34 [db-open-1] [ERROR] o.a.h.b.s.r.RocksDBStore - Failed to open RocksDB 'rocksdb-data/data/g'
3565
org.rocksdb.RocksDBException: rocksdb::Status rocksdb::SidePluginRepo::StartHttpServer(): null context when constructing CivetServer. Possible problem binding to port.
3666
at org.rocksdb.SidePluginRepo.startHttpServer(Native Method) ~[rocksdbjni-8.10.2-20250804.074027-4.jar:?]
@@ -49,7 +79,7 @@ org.rocksdb.RocksDBException: rocksdb::Status rocksdb::SidePluginRepo::StartHttp
4979

5080
---
5181

52-
### Issue 3: Database Initialization Failure
82+
### Issue 4: Database Initialization Failure
5383

5484
This error indicates the database lock file cannot be acquired, possibly due to insufficient write permissions or another process holding the lock:
5585

@@ -64,7 +94,8 @@ Caused by: org.rocksdb.RocksDBException: While lock file: rocksdb-data/data/m/LO
6494
1. Confirm the configuration file path is correct:
6595

6696
```properties
67-
rocksdb.option_path=./conf/graphs/rocksdb_plus.yaml
97+
rocksdb.provider=topling
98+
rocksdb.option_path=./conf/graphs/rocksdb_server.yaml
6899
```
69100

70101
2. Check permissions on the data directory to ensure the running user has read/write access.
@@ -76,6 +107,23 @@ Caused by: org.rocksdb.RocksDBException: While lock file: rocksdb-data/data/m/LO
76107

77108
---
78109

110+
### Issue 5: Ubuntu 24.04+ libaio Compatibility
111+
112+
Some ToplingDB native libraries may expect the legacy `libaio.so.1` name, while Ubuntu 24.04+
113+
ships the time64 library as `libaio.so.1t64`. The preload script currently creates a
114+
compatibility symlink when running on Ubuntu 24.04+ and `libaio.so.1` is missing.
115+
116+
If startup fails with a missing `libaio.so.1` error, install the system package first:
117+
118+
```bash
119+
sudo apt-get install libaio1t64
120+
```
121+
122+
Then retry startup. If your environment does not allow scripts to use `sudo`, create the
123+
compatibility symlink manually or ask the system administrator to provide it.
124+
125+
---
126+
79127
## Log Analysis
80128

81129
### Enable Debug Logging

0 commit comments

Comments
 (0)