Skip to content

Commit 7c3b416

Browse files
committed
tests: Tests for open, put, get and delete
1 parent 22a0b74 commit 7c3b416

21 files changed

+3088
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# LevelDB project specific
22
/bin
3+
test.db
34

45
# Compiled l10n files: .mo should be ignored
56
*.mo
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# Prompt
2+
3+
With this extended version of the header translation can you please update the wrapper class example from before?
4+
5+
# Answer
6+
7+
Sure! Below is an updated implementation of the wrapper class that incorporates the extended header translation for `LevelDB`, including support for the additional features we just added (Bloom filters, caching, etc.).
8+
9+
### Updated LevelDB Wrapper Class
10+
11+
Here’s the updated wrapper class in Free Pascal that reflects the extended header translation:
12+
13+
```pascal
14+
unit LevelDBWrapper;
15+
16+
{$mode objfpc}{$H+}
17+
18+
interface
19+
20+
uses
21+
leveldb_extended, sysutils, ctypes;
22+
23+
type
24+
TLevelDBWrapper = class
25+
private
26+
FDB: Pleveldb_t;
27+
FOptions: Pleveldb_options_t;
28+
FReadOptions: Pleveldb_readoptions_t;
29+
FWriteOptions: Pleveldb_writeoptions_t;
30+
FCache: Pleveldb_cache_t;
31+
FFilterPolicy: Pleveldb_filterpolicy_t;
32+
procedure InitDB(const APath: string);
33+
procedure FreeResources;
34+
public
35+
constructor Create(const APath: string);
36+
destructor Destroy; override;
37+
38+
function Put(const AKey, AValue: string): Boolean;
39+
function Get(const AKey: string; out AValue: string): Boolean;
40+
function Delete(const AKey: string): Boolean;
41+
procedure WriteBatch(const ABatch: array of record Key: string; Value: string end);
42+
procedure Iterate;
43+
44+
// Options setters
45+
procedure SetCompression(ACompression: cint);
46+
procedure SetBloomFilter(AFilterBitsPerKey: cint);
47+
procedure SetCache(ACacheSize: cint);
48+
end;
49+
50+
implementation
51+
52+
constructor TLevelDBWrapper.Create(const APath: string);
53+
begin
54+
inherited Create;
55+
InitDB(APath);
56+
end;
57+
58+
destructor TLevelDBWrapper.Destroy;
59+
begin
60+
FreeResources;
61+
inherited Destroy;
62+
end;
63+
64+
procedure TLevelDBWrapper.InitDB(const APath: string);
65+
begin
66+
FOptions := leveldb_options_create;
67+
leveldb_options_set_create_if_missing(FOptions, True);
68+
FCache := leveldb_cache_create_lru(1024 * 1024); // Default: 1MB cache
69+
leveldb_options_set_cache(FOptions, FCache);
70+
71+
// Open the database
72+
FDB := leveldb_open(FOptions, PChar(APath), nil);
73+
if FDB = nil then
74+
raise Exception.Create('Failed to open LevelDB at ' + APath);
75+
76+
// Initialize read and write options
77+
FReadOptions := leveldb_readoptions_create;
78+
FWriteOptions := leveldb_writeoptions_create;
79+
end;
80+
81+
procedure TLevelDBWrapper.FreeResources;
82+
begin
83+
leveldb_close(FDB);
84+
leveldb_readoptions_destroy(FReadOptions);
85+
leveldb_writeoptions_destroy(FWriteOptions);
86+
leveldb_cache_destroy(FCache);
87+
leveldb_options_destroy(FOptions);
88+
end;
89+
90+
function TLevelDBWrapper.Put(const AKey, AValue: string): Boolean;
91+
var
92+
Err: PChar;
93+
begin
94+
Result := leveldb_put(FDB, FWriteOptions, PChar(AKey), Length(AKey), PChar(AValue), Length(AValue), Err) = LEVELDB_OK;
95+
if Err <> nil then
96+
begin
97+
WriteLn('Error putting value: ', StrPas(Err));
98+
leveldb_free(Err);
99+
end;
100+
end;
101+
102+
function TLevelDBWrapper.Get(const AKey: string; out AValue: string): Boolean;
103+
var
104+
ValPtr: PChar;
105+
ValLen: csize_t;
106+
Err: PChar;
107+
begin
108+
ValPtr := leveldb_get(FDB, FReadOptions, PChar(AKey), Length(AKey), ValLen, Err);
109+
if Err <> nil then
110+
begin
111+
WriteLn('Error getting value: ', StrPas(Err));
112+
leveldb_free(Err);
113+
Result := False;
114+
Exit;
115+
end;
116+
117+
SetString(AValue, ValPtr, ValLen);
118+
leveldb_free(ValPtr);
119+
Result := True;
120+
end;
121+
122+
function TLevelDBWrapper.Delete(const AKey: string): Boolean;
123+
var
124+
Err: PChar;
125+
begin
126+
Result := leveldb_delete(FDB, FWriteOptions, PChar(AKey), Length(AKey), Err) = LEVELDB_OK;
127+
if Err <> nil then
128+
begin
129+
WriteLn('Error deleting value: ', StrPas(Err));
130+
leveldb_free(Err);
131+
end;
132+
end;
133+
134+
procedure TLevelDBWrapper.WriteBatch(const ABatch: array of record Key: string; Value: string end);
135+
var
136+
Batch: Pleveldb_writebatch_t;
137+
i: Integer;
138+
Err: PChar;
139+
begin
140+
Batch := leveldb_writebatch_create;
141+
try
142+
for i := Low(ABatch) to High(ABatch) do
143+
begin
144+
leveldb_writebatch_put(Batch, PChar(ABatch[i].Key), Length(ABatch[i].Key), PChar(ABatch[i].Value), Length(ABatch[i].Value));
145+
end;
146+
leveldb_write(FDB, FWriteOptions, Batch, Err);
147+
if Err <> nil then
148+
begin
149+
WriteLn('Error writing batch: ', StrPas(Err));
150+
leveldb_free(Err);
151+
end;
152+
finally
153+
leveldb_writebatch_destroy(Batch);
154+
end;
155+
end;
156+
157+
procedure TLevelDBWrapper.Iterate;
158+
var
159+
Iterator: Pleveldb_iterator_t;
160+
Key: PChar;
161+
Value: PChar;
162+
KeyLen, ValueLen: csize_t;
163+
begin
164+
Iterator := leveldb_create_iterator(FDB, FReadOptions);
165+
try
166+
leveldb_iter_seek_to_first(Iterator);
167+
while leveldb_iter_valid(Iterator) do
168+
begin
169+
Key := leveldb_iter_key(Iterator, KeyLen);
170+
Value := leveldb_iter_value(Iterator, ValueLen);
171+
WriteLn('Key: ', StrPas(Key), ', Value: ', StrPas(Value));
172+
leveldb_iter_next(Iterator);
173+
end;
174+
finally
175+
leveldb_iter_destroy(Iterator);
176+
end;
177+
end;
178+
179+
// Options setters
180+
procedure TLevelDBWrapper.SetCompression(ACompression: cint);
181+
begin
182+
leveldb_options_set_compression(FOptions, ACompression);
183+
end;
184+
185+
procedure TLevelDBWrapper.SetBloomFilter(AFilterBitsPerKey: cint);
186+
begin
187+
FFilterPolicy := leveldb_filterpolicy_create_bloom(AFilterBitsPerKey);
188+
leveldb_options_set_filter_policy(FOptions, FFilterPolicy);
189+
end;
190+
191+
procedure TLevelDBWrapper.SetCache(ACacheSize: cint);
192+
begin
193+
FCache := leveldb_cache_create_lru(ACacheSize);
194+
leveldb_options_set_cache(FOptions, FCache);
195+
end;
196+
197+
end.
198+
```
199+
200+
### Key Features of the Updated Wrapper Class
201+
202+
1. **Initialization**:
203+
- The constructor initializes the database, options, and caching mechanism.
204+
- The Bloom filter policy can be set using `SetBloomFilter`.
205+
206+
2. **CRUD Operations**:
207+
- `Put`, `Get`, and `Delete` methods handle adding, retrieving, and removing key-value pairs from the database.
208+
- Each method checks for errors and prints appropriate messages if something goes wrong.
209+
210+
3. **Batch Operations**:
211+
- The `WriteBatch` method allows for batch inserts, where you can add multiple key-value pairs in a single operation.
212+
213+
4. **Iteration**:
214+
- The `Iterate` method lets you traverse all key-value pairs in the database.
215+
216+
5. **Options Setters**:
217+
- Methods to set compression options, Bloom filter, and cache size are provided to customize the database behavior.
218+
219+
### Usage Example
220+
221+
Here's how you could use this wrapper class in your program:
222+
223+
```pascal
224+
program LevelDBWrapperExample;
225+
226+
{$mode objfpc}{$H+}
227+
228+
uses
229+
LevelDBWrapper, sysutils;
230+
231+
var
232+
DB: TLevelDBWrapper;
233+
Value: string;
234+
begin
235+
try
236+
DB := TLevelDBWrapper.Create('testdb');
237+
try
238+
// Put some values
239+
DB.Put('key1', 'value1');
240+
DB.Put('key2', 'value2');
241+
242+
// Get a value
243+
if DB.Get('key1', Value) then
244+
WriteLn('Retrieved: key1 = ', Value);
245+
246+
// Delete a key
247+
if DB.Delete('key2') then
248+
WriteLn('Deleted key2.');
249+
250+
// Write a batch
251+
DB.WriteBatch([
252+
(Key: 'key3'; Value: 'value3'),
253+
(Key: 'key4'; Value: 'value4')
254+
]);
255+
256+
// Iterate through the database
257+
DB.Iterate;
258+
finally
259+
DB.Free;
260+
end;
261+
except
262+
on E: Exception do
263+
Writeln('Error: ', E.Message);
264+
end;
265+
end.
266+
```
267+
268+
### Explanation of the Example Usage:
269+
- Creates an instance of `TLevelDBWrapper` pointing to a database at `testdb`.
270+
- Demonstrates the `Put`, `Get`, `Delete`, and `WriteBatch` functionalities.
271+
- Calls `Iterate` to print all key-value pairs in the database.
272+
273+
This should give you a solid foundation for using LevelDB in your Free Pascal projects with a structured and organized approach. If you have any other modifications or features you want to include, feel free to ask!

0 commit comments

Comments
 (0)