Skip to content

Commit 543f059

Browse files
committed
Get Readers, Writers and Handles ref-counted in C API to compile and pass tests
1 parent 6888985 commit 543f059

File tree

12 files changed

+251
-151
lines changed

12 files changed

+251
-151
lines changed

go/cpossum/c-possum.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func (me Stat) Size() int64 {
5858
return int64(me.size)
5959
}
6060

61-
type Handle = C.Handle
61+
type Handle = C.PossumHandle
6262

6363
func NewHandle(dir string) *Handle {
6464
cDir := C.CString(dir)

go/cpossum/possum.h

+22-22
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,7 @@ typedef enum {
1616
/**
1717
* Manages uncommitted writes
1818
*/
19-
typedef struct BatchWriter BatchWriter;
20-
21-
/**
22-
* Provides access to a storage directory. Manages manifest access, file cloning, file writers,
23-
* configuration, value eviction etc.
24-
*/
25-
typedef struct Handle Handle;
19+
typedef struct BatchWriter_PossumHandle BatchWriter_PossumHandle;
2620

2721
typedef struct PossumReader PossumReader;
2822

@@ -31,9 +25,15 @@ typedef struct PossumReader PossumReader;
3125
*/
3226
typedef struct PossumValue PossumValue;
3327

28+
typedef struct Rc_RwLock_Handle Rc_RwLock_Handle;
29+
3430
typedef struct ValueWriter ValueWriter;
3531

36-
typedef BatchWriter PossumWriter;
32+
typedef Rc_RwLock_Handle PossumHandleRc;
33+
34+
typedef PossumHandleRc PossumHandle;
35+
36+
typedef BatchWriter_PossumHandle PossumWriter;
3737

3838
typedef ValueWriter PossumValueWriter;
3939

@@ -66,13 +66,13 @@ typedef struct {
6666
bool disable_hole_punching;
6767
} PossumLimits;
6868

69-
Handle *possum_new(const char *path);
69+
PossumHandle *possum_new(const char *path);
7070

7171
PossumError possum_start_new_value(PossumWriter *writer, PossumValueWriter **value);
7272

7373
RawFileHandle possum_value_writer_fd(PossumValueWriter *value);
7474

75-
PossumError possum_writer_rename(BatchWriter *writer, const PossumValue *value, PossumBuf new_key);
75+
PossumError possum_writer_rename(PossumWriter *writer, const PossumValue *value, PossumBuf new_key);
7676

7777
PossumError possum_reader_add(PossumReader *reader, PossumBuf key, const PossumValue **value);
7878

@@ -99,35 +99,35 @@ PossumError possum_writer_commit(PossumWriter *writer);
9999

100100
PossumError possum_writer_stage(PossumWriter *writer, PossumBuf key, PossumValueWriter *value);
101101

102-
void possum_drop(Handle *handle);
102+
void possum_drop(PossumHandle *handle);
103103

104-
PossumError possum_set_instance_limits(Handle *handle, const PossumLimits *limits);
104+
PossumError possum_set_instance_limits(PossumHandle *handle, const PossumLimits *limits);
105105

106-
PossumError possum_cleanup_snapshots(const Handle *handle);
106+
PossumError possum_cleanup_snapshots(const PossumHandle *handle);
107107

108-
size_t possum_single_write_buf(Handle *handle, PossumBuf key, PossumBuf value);
108+
size_t possum_single_write_buf(PossumHandle *handle, PossumBuf key, PossumBuf value);
109109

110-
PossumWriter *possum_new_writer(Handle *handle);
110+
PossumWriter *possum_new_writer(PossumHandle *handle);
111111

112-
bool possum_single_stat(const Handle *handle, PossumBuf key, PossumStat *out_stat);
112+
bool possum_single_stat(const PossumHandle *handle, PossumBuf key, PossumStat *out_stat);
113113

114-
PossumError possum_list_items(const Handle *handle,
114+
PossumError possum_list_items(const PossumHandle *handle,
115115
PossumBuf prefix,
116116
PossumItem **out_list,
117117
size_t *out_list_len);
118118

119-
PossumError possum_single_read_at(const Handle *handle,
119+
PossumError possum_single_read_at(const PossumHandle *handle,
120120
PossumBuf key,
121121
PossumBuf *buf,
122122
uint64_t offset);
123123

124124
/**
125125
* stat is filled if non-null and a delete occurs. NoSuchKey is returned if the key does not exist.
126126
*/
127-
PossumError possum_single_delete(const Handle *handle, PossumBuf key, PossumStat *stat);
127+
PossumError possum_single_delete(const PossumHandle *handle, PossumBuf key, PossumStat *stat);
128128

129-
PossumError possum_reader_new(const Handle *handle, PossumReader **reader);
129+
PossumError possum_reader_new(const PossumHandle *handle, PossumReader **reader);
130130

131-
PossumError possum_handle_move_prefix(Handle *handle, PossumBuf from, PossumBuf to);
131+
PossumError possum_handle_move_prefix(PossumHandle *handle, PossumBuf from, PossumBuf to);
132132

133-
PossumError possum_handle_delete_prefix(Handle *handle, PossumBuf prefix);
133+
PossumError possum_handle_delete_prefix(PossumHandle *handle, PossumBuf prefix);

src/c_api/ext_fns/handle.rs

+63-27
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,56 @@
11
use libc::size_t;
22
use positioned_io::ReadAt;
3+
use rusqlite::TransactionBehavior;
34

45
use super::*;
56
use crate::c_api::PossumError::NoError;
6-
use crate::Handle;
77

8-
// This drops the Handle Box. Instead, if this is hard to use correctly from C, it could drop a
9-
// top-level reference count for the box. i.e. If this one goes, there's no way to work with the
10-
// Handle, and when all other outstanding operations on the Handle complete, it will drop the Handle
11-
// for real.
8+
// This drops the PossumHandle Box. Instead, if this is hard to use correctly from C, it could drop
9+
// a top-level reference count for the box. i.e. If this one goes, there's no way to work with the
10+
// PossumHandle, and when all other outstanding operations on the PossumHandle complete, it will
11+
// drop the PossumHandle for real.
1212
#[no_mangle]
13-
pub extern "C" fn possum_drop(handle: *mut Handle) {
13+
pub extern "C" fn possum_drop(handle: *mut PossumHandle) {
1414
drop(unsafe { Box::from_raw(handle) })
1515
}
1616

1717
#[no_mangle]
1818
pub extern "C" fn possum_set_instance_limits(
19-
handle: *mut Handle,
19+
handle: *mut PossumHandle,
2020
limits: *const PossumLimits,
2121
) -> PossumError {
2222
let handle = unsafe { &mut *handle };
2323
let limits = unsafe { limits.read() };
2424
with_residual(|| {
2525
handle
26+
.write()
27+
.unwrap()
2628
.set_instance_limits(limits.into())
2729
.map_err(Into::into)
2830
})
2931
}
3032

3133
#[no_mangle]
32-
pub extern "C" fn possum_cleanup_snapshots(handle: *const Handle) -> PossumError {
33-
let handle = unsafe { &*handle };
34-
with_residual(|| handle.cleanup_snapshots())
34+
pub extern "C" fn possum_cleanup_snapshots(handle: *const PossumHandle) -> PossumError {
35+
let handle = unwrap_possum_handle(handle);
36+
with_residual(|| handle.read().unwrap().cleanup_snapshots())
3537
}
3638

3739
#[no_mangle]
3840
pub extern "C" fn possum_single_write_buf(
39-
handle: *mut Handle,
41+
handle: *mut PossumHandle,
4042
key: PossumBuf,
4143
value: PossumBuf,
4244
) -> size_t {
4345
let key_vec = key.as_ref().to_vec();
4446
let value_slice = value.as_ref();
4547
const ERR_SENTINEL: usize = usize::MAX;
4648
let handle = unsafe { &*handle };
47-
match handle.single_write_from(key_vec, value_slice) {
49+
match handle
50+
.read()
51+
.unwrap()
52+
.single_write_from(key_vec, value_slice)
53+
{
4854
Err(_) => ERR_SENTINEL,
4955
Ok((n, _)) => {
5056
let n = n.try_into().unwrap();
@@ -55,18 +61,21 @@ pub extern "C" fn possum_single_write_buf(
5561
}
5662

5763
#[no_mangle]
58-
pub extern "C" fn possum_new_writer(handle: *mut Handle) -> *mut PossumWriter {
59-
let handle = unsafe { handle.as_ref() }.unwrap();
60-
Box::into_raw(Box::new(handle.new_writer().unwrap()))
64+
pub extern "C" fn possum_new_writer(handle: *mut PossumHandle) -> *mut PossumWriter {
65+
let handle = unwrap_possum_handle(handle);
66+
let writer = BatchWriter::new(handle.clone());
67+
Box::into_raw(Box::new(writer))
6168
}
6269

6370
#[no_mangle]
6471
pub extern "C" fn possum_single_stat(
65-
handle: *const Handle,
72+
handle: *const PossumHandle,
6673
key: PossumBuf,
6774
out_stat: *mut PossumStat,
6875
) -> bool {
6976
match unsafe { handle.as_ref() }
77+
.unwrap()
78+
.read()
7079
.unwrap()
7180
.read_single(key.as_ref())
7281
.unwrap()
@@ -82,12 +91,14 @@ pub extern "C" fn possum_single_stat(
8291

8392
#[no_mangle]
8493
pub extern "C" fn possum_list_items(
85-
handle: *const Handle,
94+
handle: *const PossumHandle,
8695
prefix: PossumBuf,
8796
out_list: *mut *mut PossumItem,
8897
out_list_len: *mut size_t,
8998
) -> PossumError {
9099
let items = match unsafe { handle.as_ref() }
100+
.unwrap()
101+
.read()
91102
.unwrap()
92103
.list_items(prefix.as_ref())
93104
{
@@ -100,13 +111,18 @@ pub extern "C" fn possum_list_items(
100111

101112
#[no_mangle]
102113
pub extern "C" fn possum_single_read_at(
103-
handle: *const Handle,
114+
handle: *const PossumHandle,
104115
key: PossumBuf,
105116
buf: *mut PossumBuf,
106117
offset: u64,
107118
) -> PossumError {
108119
let rust_key = key.as_ref();
109-
let value = match unsafe { handle.as_ref() }.unwrap().read_single(rust_key) {
120+
let value = match unsafe { handle.as_ref() }
121+
.unwrap()
122+
.read()
123+
.unwrap()
124+
.read_single(rust_key)
125+
{
110126
Ok(Some(value)) => value,
111127
Ok(None) => return PossumError::NoSuchKey,
112128
Err(err) => return err.into(),
@@ -124,13 +140,13 @@ pub extern "C" fn possum_single_read_at(
124140
/// stat is filled if non-null and a delete occurs. NoSuchKey is returned if the key does not exist.
125141
#[no_mangle]
126142
pub extern "C" fn possum_single_delete(
127-
handle: *const Handle,
143+
handle: *const PossumHandle,
128144
key: PossumBuf,
129145
stat: *mut PossumStat,
130146
) -> PossumError {
131147
with_residual(|| {
132148
let handle = unsafe { &*handle };
133-
let value = match handle.single_delete(key.as_ref()) {
149+
let value = match handle.read().unwrap().single_delete(key.as_ref()) {
134150
Ok(None) => return Err(crate::Error::NoSuchKey),
135151
Err(err) => return Err(err),
136152
Ok(Some(value)) => value,
@@ -144,15 +160,27 @@ pub extern "C" fn possum_single_delete(
144160

145161
#[no_mangle]
146162
pub extern "C" fn possum_reader_new(
147-
handle: *const Handle,
163+
handle: *const PossumHandle,
148164
reader: *mut *mut PossumReader,
149165
) -> PossumError {
150-
let handle = unsafe { handle.as_ref() }.unwrap();
166+
let handle = unwrap_possum_handle(handle).clone();
151167
let reader = unsafe { reader.as_mut() }.unwrap();
152-
let rust_reader = match handle.read() {
168+
let owned_tx_res = handle.start_transaction(
169+
// This is copied from Handle::start_writable_transaction_with_behaviour and Handle::read
170+
// until I make proper abstractions.
171+
|conn, handle| {
172+
let rtx = conn.transaction_with_behavior(TransactionBehavior::Deferred)?;
173+
Ok(Transaction::new(rtx, handle))
174+
},
175+
);
176+
let owned_tx = match owned_tx_res {
153177
Ok(ok) => ok,
154178
Err(err) => return err.into(),
155179
};
180+
let rust_reader = Reader {
181+
owned_tx,
182+
reads: Default::default(),
183+
};
156184
*reader = Box::into_raw(Box::new(PossumReader {
157185
rust_reader: Some(rust_reader),
158186
values: Default::default(),
@@ -162,23 +190,31 @@ pub extern "C" fn possum_reader_new(
162190

163191
#[no_mangle]
164192
pub extern "C" fn possum_handle_move_prefix(
165-
handle: *mut Handle,
193+
handle: *mut PossumHandle,
166194
from: PossumBuf,
167195
to: PossumBuf,
168196
) -> PossumError {
169197
let handle = unsafe { &mut *handle };
170198
with_residual(|| {
171199
handle
200+
.read()
201+
.unwrap()
172202
.move_prefix(from.as_ref(), to.as_ref())
173203
.map_err(Into::into)
174204
})
175205
}
176206

177207
#[no_mangle]
178208
pub extern "C" fn possum_handle_delete_prefix(
179-
handle: *mut Handle,
209+
handle: *mut PossumHandle,
180210
prefix: PossumBuf,
181211
) -> PossumError {
182212
let handle = unsafe { &mut *handle };
183-
with_residual(|| handle.delete_prefix(prefix.as_ref()).map_err(Into::into))
213+
with_residual(|| {
214+
handle
215+
.read()
216+
.unwrap()
217+
.delete_prefix(prefix.as_ref())
218+
.map_err(Into::into)
219+
})
184220
}

src/c_api/ext_fns/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ mod handle;
33
use std::ffi::{c_char, CStr};
44
use std::path::PathBuf;
55
use std::ptr::null_mut;
6+
use std::rc::Rc;
7+
use std::sync::RwLock;
68

79
use libc::size_t;
810
use positioned_io::ReadAt;
@@ -13,7 +15,7 @@ use crate::c_api::PossumError::{NoError, NoSuchKey};
1315
use crate::Handle;
1416

1517
#[no_mangle]
16-
pub extern "C" fn possum_new(path: *const c_char) -> *mut Handle {
18+
pub extern "C" fn possum_new(path: *const c_char) -> *mut PossumHandle {
1719
if let Err(err) = env_logger::try_init() {
1820
warn!("error initing env_logger: {}", err);
1921
}
@@ -33,7 +35,7 @@ pub extern "C" fn possum_new(path: *const c_char) -> *mut Handle {
3335
return null_mut();
3436
}
3537
};
36-
Box::into_raw(Box::new(handle))
38+
Box::into_raw(Box::new(Rc::new(RwLock::new(handle))))
3739
}
3840

3941
#[no_mangle]
@@ -78,7 +80,8 @@ pub extern "C" fn possum_reader_add(
7880
value: *mut *const PossumValue,
7981
) -> PossumError {
8082
let reader = unsafe { reader.as_mut() }.unwrap();
81-
let rust_value = match reader.rust_reader.as_mut().unwrap().add(key.as_ref()) {
83+
let mut_rust_reader = reader.rust_reader.as_mut().unwrap();
84+
let rust_value = match mut_rust_reader.add(key.as_ref()) {
8285
Ok(None) => return NoSuchKey,
8386
Ok(Some(value)) => value,
8487
Err(err) => return err.into(),

src/c_api/mod.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ use std::ffi::c_char;
99
use std::mem::size_of;
1010
use std::pin::Pin;
1111
use std::ptr::copy_nonoverlapping;
12+
use std::rc::Rc;
1213
use std::slice;
14+
use std::sync::RwLockReadGuard;
1315

1416
use libc::{calloc, malloc, size_t};
1517

@@ -32,10 +34,15 @@ impl PossumBuf {
3234
struct PossumReader {
3335
// Removed when converted to a snapshot. Specific to the C API so as to not need to expose
3436
// Snapshot, and to convert Values automatically when a snapshot starts.
35-
rust_reader: Option<Reader<OwnedTx<'static>>>,
37+
rust_reader: Option<Reader<PossumReaderOwnedTransaction<'static>>>,
3638
values: Vec<Pin<Box<PossumValue>>>,
3739
}
3840

41+
pub(crate) type PossumReaderOwnedTransaction<'a> = <PossumHandleRc as StartTransaction<
42+
'a,
43+
Transaction<'a, Rc<RwLockReadGuard<'a, Handle>>>,
44+
>>::Owned;
45+
3946
use crate::c_api::PossumError::{AnyhowError, IoError, SqliteError};
4047

4148
impl<V> From<V> for PossumStat
@@ -142,6 +149,10 @@ fn with_residual(f: impl FnOnce() -> PubResult<()>) -> PossumError {
142149
}
143150
}
144151

152+
fn unwrap_possum_handle<'a>(handle: *const PossumHandle) -> &'a PossumHandle {
153+
unsafe { handle.as_ref() }.unwrap()
154+
}
155+
145156
impl From<PossumLimits> for handle::Limits {
146157
fn from(from: PossumLimits) -> Self {
147158
handle::Limits {

0 commit comments

Comments
 (0)