Skip to content

Commit 93327e6

Browse files
committed
Preliminary buffer-cache implementation
1 parent c24a834 commit 93327e6

File tree

18 files changed

+1009
-68
lines changed

18 files changed

+1009
-68
lines changed

cloudata-keyvalue/src/main/java/com/cloudata/keyvalue/KeyValueStore.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99

1010
import com.cloudata.btree.Btree;
1111
import com.cloudata.btree.BtreeQuery;
12+
import com.cloudata.btree.Database;
1213
import com.cloudata.btree.Keyspace;
13-
import com.cloudata.btree.MmapPageStore;
14-
import com.cloudata.btree.PageStore;
1514
import com.cloudata.btree.ReadOnlyTransaction;
1615
import com.cloudata.btree.WriteTransaction;
1716
import com.cloudata.keyvalue.operation.KeyValueOperation;
@@ -26,14 +25,14 @@ public class KeyValueStore {
2625

2726
public KeyValueStore(File dir, boolean uniqueKeys) throws IOException {
2827
File data = new File(dir, "data");
29-
PageStore pageStore = MmapPageStore.build(data, uniqueKeys);
28+
Database db = Database.build(data);
3029

3130
log.warn("Building new btree @{}", dir);
3231

33-
this.btree = new Btree(pageStore, uniqueKeys);
32+
this.btree = new Btree(db, uniqueKeys);
3433
}
3534

36-
public void doAction(KeyValueOperation operation) {
35+
public void doAction(KeyValueOperation operation) throws IOException {
3736
if (operation.isReadOnly()) {
3837
try (ReadOnlyTransaction txn = btree.beginReadOnly()) {
3938
txn.doAction(btree, operation);
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package com.cloudata.btree;
2+
3+
import io.netty.buffer.ByteBuf;
4+
5+
import java.io.Closeable;
6+
import java.io.EOFException;
7+
import java.io.File;
8+
import java.io.IOException;
9+
import java.nio.ByteBuffer;
10+
import java.nio.channels.AsynchronousFileChannel;
11+
import java.nio.channels.CompletionHandler;
12+
import java.nio.file.Path;
13+
import java.nio.file.Paths;
14+
import java.nio.file.StandardOpenOption;
15+
16+
import org.slf4j.Logger;
17+
import org.slf4j.LoggerFactory;
18+
19+
import com.google.common.util.concurrent.FutureCallback;
20+
import com.google.common.util.concurrent.Futures;
21+
import com.google.common.util.concurrent.ListenableFuture;
22+
import com.google.common.util.concurrent.SettableFuture;
23+
24+
public class BackingFile implements Closeable {
25+
private static final Logger log = LoggerFactory.getLogger(BackingFile.class);
26+
27+
final File file;
28+
29+
final AsynchronousFileChannel fileChannel;
30+
31+
public BackingFile(File file) throws IOException {
32+
this.file = file;
33+
34+
Path path = Paths.get(file.getAbsolutePath());
35+
36+
log.warn("We want to disable the read cache (probably?)");
37+
this.fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.READ);
38+
}
39+
40+
public ListenableFuture<ByteBuffer> read(ByteBuffer buffer, long position) {
41+
final SettableFuture<ByteBuffer> future = SettableFuture.create();
42+
43+
read(buffer, buffer.position(), position, future);
44+
45+
return future;
46+
}
47+
48+
/**
49+
* Read into a ByteBuf. Adds reference for duration of read, and releases it unless future is set.
50+
*/
51+
public ListenableFuture<ByteBuf> read(final ByteBuf buf, final long position) {
52+
final SettableFuture<ByteBuf> ret = SettableFuture.create();
53+
54+
ByteBuffer nioBuffer = buf.nioBuffer();
55+
56+
assert nioBuffer.remaining() == buf.writableBytes();
57+
58+
ListenableFuture<ByteBuffer> future = read(buf.nioBuffer(), position);
59+
60+
buf.retain();
61+
62+
Futures.addCallback(future, new FutureCallback<ByteBuffer>() {
63+
@Override
64+
public void onSuccess(ByteBuffer result) {
65+
assert buf.readableBytes() == result.remaining();
66+
67+
// Caller releases
68+
ret.set(buf);
69+
}
70+
71+
@Override
72+
public void onFailure(Throwable t) {
73+
buf.release();
74+
75+
ret.setException(t);
76+
}
77+
});
78+
79+
return ret;
80+
}
81+
82+
private void read(ByteBuffer dest, final int destStart, final long filePosition,
83+
final SettableFuture<ByteBuffer> future) {
84+
try {
85+
fileChannel.read(dest, filePosition, dest, new CompletionHandler<Integer, ByteBuffer>() {
86+
@Override
87+
public void completed(Integer n, ByteBuffer dest) {
88+
if (n == -1) {
89+
future.setException(new EOFException());
90+
return;
91+
}
92+
93+
if (dest.remaining() > 0) {
94+
long newPosition = filePosition + n;
95+
96+
read(dest, destStart, newPosition, future);
97+
return;
98+
}
99+
100+
dest.position(destStart);
101+
future.set(dest);
102+
}
103+
104+
@Override
105+
public void failed(Throwable exc, ByteBuffer attachment) {
106+
future.setException(exc);
107+
}
108+
});
109+
} catch (Exception e) {
110+
future.setException(e);
111+
}
112+
}
113+
114+
public void sync() throws IOException {
115+
boolean metadata = false;
116+
fileChannel.force(metadata);
117+
}
118+
119+
public ListenableFuture<Void> write(ByteBuffer src, final long position) {
120+
final SettableFuture<Void> future = SettableFuture.create();
121+
write(src, position, future);
122+
return future;
123+
}
124+
125+
public ListenableFuture<Void> write(final ByteBuf buf, final long position) {
126+
ListenableFuture<Void> future = write(buf.nioBuffer(), position);
127+
128+
buf.retain();
129+
130+
Futures.addCallback(future, new FutureCallback<Void>() {
131+
@Override
132+
public void onSuccess(Void result) {
133+
buf.release();
134+
}
135+
136+
@Override
137+
public void onFailure(Throwable t) {
138+
buf.release();
139+
}
140+
});
141+
142+
return future;
143+
}
144+
145+
private void write(ByteBuffer src, final long position, final SettableFuture<Void> future) {
146+
try {
147+
fileChannel.write(src, position, src, new CompletionHandler<Integer, ByteBuffer>() {
148+
@Override
149+
public void completed(Integer wrote, ByteBuffer src) {
150+
if (wrote < 0) {
151+
future.setException(new IOException());
152+
return;
153+
}
154+
155+
if (src.remaining() > 0) {
156+
long newPosition = position + wrote;
157+
158+
write(src, newPosition, future);
159+
return;
160+
}
161+
162+
future.set(null);
163+
}
164+
165+
@Override
166+
public void failed(Throwable exc, ByteBuffer attachment) {
167+
future.setException(exc);
168+
}
169+
});
170+
} catch (Exception e) {
171+
future.setException(e);
172+
}
173+
}
174+
175+
public long size() {
176+
return file.length();
177+
}
178+
179+
@Override
180+
public void close() throws IOException {
181+
fileChannel.close();
182+
}
183+
184+
}

cloudata-server-shared/src/main/java/com/cloudata/btree/Btree.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,8 @@ public boolean isUniqueKeys() {
3434
return uniqueKeys;
3535
}
3636

37+
public Database getDb() {
38+
return db;
39+
}
40+
3741
}

0 commit comments

Comments
 (0)