Skip to content

Commit fd4da7e

Browse files
Replace storage database with rocksdb (#455)
* Add rocksdb demo * Fix version * Switch to amulet-rocksdb * Update python versions * Remove legacy fallback code * Reformat * Remove beta from leveldb requirement * Improve workflows Add cmake install and refactor
1 parent a2fa0fd commit fd4da7e

8 files changed

Lines changed: 48 additions & 88 deletions

File tree

.github/workflows/python-build.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@ jobs:
1212
runs-on: ${{ matrix.os }}
1313
strategy:
1414
matrix:
15-
python-version: ['3.10', '3.11']
15+
python-version: ['3.11', '3.12']
1616
os: [macos-latest, windows-latest]
17+
1718
steps:
18-
- uses: actions/checkout@v3
19-
- name: Set up Python ${{ matrix.python-version }}
20-
uses: actions/setup-python@v4
19+
- name: Clone
20+
uses: actions/checkout@v4
21+
22+
- name: Set up Python
23+
uses: actions/setup-python@v5
2124
with:
2225
python-version: ${{ matrix.python-version }}
26+
2327
- name: Install dependencies
2428
run: |
2529
python -m pip install --upgrade pip
@@ -32,6 +36,7 @@ jobs:
3236
run: |
3337
python -m build
3438
twine upload dist/* --skip-existing
39+
3540
- name: Build Docs
3641
shell: bash
3742
env:

.github/workflows/python-stylecheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
runs-on: ubuntu-latest
1818
strategy:
1919
matrix:
20-
python-version: ['3.10']
20+
python-version: ['3.11']
2121

2222
steps:
2323
- uses: actions/checkout@v3

.github/workflows/python-unittests.yml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,28 @@ jobs:
1616
unittests:
1717
runs-on: ${{ matrix.os }}
1818
strategy:
19+
fail-fast: false
1920
matrix:
20-
python-version: ['3.10', '3.11']
21+
python-version: ['3.11', '3.12']
2122
os: [windows-latest, macos-latest, ubuntu-latest]
23+
2224
steps:
23-
- uses: actions/checkout@v3
24-
- name: Set up Python ${{ matrix.python-version }}
25-
uses: actions/setup-python@v4
25+
- name: Clone
26+
uses: actions/checkout@v4
27+
28+
- name: Set up Python
29+
uses: actions/setup-python@v5
2630
with:
2731
python-version: ${{ matrix.python-version }}
32+
33+
- name: Setup cmake
34+
if: matrix.os == 'ubuntu-latest'
35+
uses: jwlawson/actions-setup-cmake@v2
36+
2837
- name: Install dependencies
2938
run: |
3039
python -m pip install --upgrade pip
3140
pip install -e .
41+
3242
- name: Test with unittest
3343
run: python -m unittest discover -v -s tests

.readthedocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: 2
33
build:
44
os: ubuntu-22.04
55
tools:
6-
python: '3.10'
6+
python: '3.11'
77

88
python:
99
install:

amulet/api/level/base_level/base_level.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
)
2727
from amulet.api.chunk.status import StatusFormats
2828
from amulet.api.cache import TempDir
29-
from leveldb import LevelDB
29+
from rocksdb import RocksDB, Options, WriteOptions, CompressionType
3030
from amulet.utils.generator import generator_unpacker
3131
from amulet.utils.world_utils import block_coords_to_chunk_coords
3232
from .chunk_manager import ChunkManager
@@ -72,9 +72,21 @@ def __init__(self, path: str, format_wrapper: api_wrapper.FormatWrapper):
7272
self._history_manager = MetaHistoryManager()
7373

7474
self._temp_dir = TempDir()
75-
self._history_db = LevelDB(
76-
os.path.join(self._temp_dir, "history_db"), create_if_missing=True
75+
76+
options = Options()
77+
options.create_if_missing = True
78+
options.compression_type = CompressionType.ZstdCompression
79+
80+
write_options = WriteOptions()
81+
write_options.sync = False
82+
write_options.disable_wal = True
83+
84+
self._history_db = RocksDB(
85+
os.path.join(self._temp_dir, "history_db"),
86+
options=options,
87+
write_options=write_options,
7788
)
89+
7890
self._chunks: ChunkManager = ChunkManager(self, self._history_db)
7991
self._players = PlayerManager(self)
8092

@@ -522,7 +534,7 @@ def close(self):
522534
Use changed method to check if there are any changes that should be saved before closing.
523535
"""
524536
self.level_wrapper.close()
525-
self._history_db.close(compact=False)
537+
self._history_db.close()
526538

527539
def unload(self, safe_area: Optional[Tuple[Dimension, int, int, int, int]] = None):
528540
"""

amulet/api/level/base_level/chunk_manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from amulet.api.errors import ChunkDoesNotExist, ChunkLoadError
1111
from amulet.api.history.history_manager import DatabaseHistoryManager
1212
from amulet.api import level as api_level
13-
from leveldb import LevelDB
13+
from rocksdb import RocksDB
1414

1515

1616
class ChunkDBEntry(DBRevisionManager):
@@ -19,7 +19,7 @@ class ChunkDBEntry(DBRevisionManager):
1919
def __init__(
2020
self,
2121
world: api_level.BaseLevel,
22-
history_db: LevelDB,
22+
history_db: RocksDB,
2323
prefix: str,
2424
initial_state: EntryType,
2525
):
@@ -66,7 +66,7 @@ class ChunkManager(DatabaseHistoryManager):
6666
DoesNotExistError = ChunkDoesNotExist
6767
LoadError = ChunkLoadError
6868

69-
def __init__(self, level: api_level.BaseLevel, history_db: LevelDB):
69+
def __init__(self, level: api_level.BaseLevel, history_db: RocksDB):
7070
"""
7171
Construct a :class:`ChunkManager` instance.
7272

amulet/level/formats/anvil_world/_sector_manager.py

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,75 +2,7 @@
22

33
from typing import NamedTuple, List
44
import threading
5-
import sys
6-
7-
if sys.version_info >= (3, 10):
8-
# bisect only supports key as of 3.10
9-
from bisect import bisect_left, bisect_right
10-
11-
else:
12-
13-
def bisect_left(a, x, lo=0, hi=None, *, key=None):
14-
"""Return the index where to insert item x in list a, assuming a is sorted.
15-
The return value i is such that all e in a[:i] have e < x, and all e in
16-
a[i:] have e >= x. So if x already appears in the list, a.insert(i, x) will
17-
insert just before the leftmost x already there.
18-
Optional args lo (default 0) and hi (default len(a)) bound the
19-
slice of a to be searched.
20-
"""
21-
22-
if lo < 0:
23-
raise ValueError("lo must be non-negative")
24-
if hi is None:
25-
hi = len(a)
26-
# Note, the comparison uses "<" to match the
27-
# __lt__() logic in list.sort() and in heapq.
28-
if key is None:
29-
while lo < hi:
30-
mid = (lo + hi) // 2
31-
if a[mid] < x:
32-
lo = mid + 1
33-
else:
34-
hi = mid
35-
else:
36-
while lo < hi:
37-
mid = (lo + hi) // 2
38-
if key(a[mid]) < x:
39-
lo = mid + 1
40-
else:
41-
hi = mid
42-
return lo
43-
44-
def bisect_right(a, x, lo=0, hi=None, *, key=None):
45-
"""Return the index where to insert item x in list a, assuming a is sorted.
46-
The return value i is such that all e in a[:i] have e <= x, and all e in
47-
a[i:] have e > x. So if x already appears in the list, a.insert(i, x) will
48-
insert just after the rightmost x already there.
49-
Optional args lo (default 0) and hi (default len(a)) bound the
50-
slice of a to be searched.
51-
"""
52-
53-
if lo < 0:
54-
raise ValueError("lo must be non-negative")
55-
if hi is None:
56-
hi = len(a)
57-
# Note, the comparison uses "<" to match the
58-
# __lt__() logic in list.sort() and in heapq.
59-
if key is None:
60-
while lo < hi:
61-
mid = (lo + hi) // 2
62-
if x < a[mid]:
63-
hi = mid
64-
else:
65-
lo = mid + 1
66-
else:
67-
while lo < hi:
68-
mid = (lo + hi) // 2
69-
if x < key(a[mid]):
70-
hi = mid
71-
else:
72-
lo = mid + 1
73-
return lo
5+
from bisect import bisect_left, bisect_right
746

757

768
class NoValidSector(Exception):

setup.cfg

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@ platforms = any
1414
1515
[options]
1616
include_package_data = True
17-
python_requires = >=3.9
17+
python_requires = >=3.11
1818
install_requires =
1919
numpy~=1.17
2020
amulet-nbt~=2.0
2121
pymctranslate~=1.2
2222
portalocker~=2.4
23-
amulet-leveldb~=1.0b0
23+
amulet-leveldb~=1.0
2424
platformdirs~=3.1
2525
lz4~=4.3
26+
amulet-rocksdb~=1.0
2627
2728
packages = find:
2829

0 commit comments

Comments
 (0)