Skip to content

Commit 7f682af

Browse files
committed
Cache site id -> ordinal mapping during tx
Signed-off-by: Somtochi Onyekwere <[email protected]>
1 parent 1862686 commit 7f682af

File tree

6 files changed

+105
-7
lines changed

6 files changed

+105
-7
lines changed

core/rs/core/src/c.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ pub struct crsql_ExtData {
7373
pub pSelectClockTablesStmt: *mut sqlite::stmt,
7474
pub mergeEqualValues: ::core::ffi::c_int,
7575
pub timestamp: ::core::ffi::c_ulonglong,
76+
pub ordinalMap: *mut ::core::ffi::c_void,
7677
}
7778

7879
#[repr(C)]
@@ -268,7 +269,7 @@ fn bindgen_test_layout_crsql_ExtData() {
268269
let ptr = UNINIT.as_ptr();
269270
assert_eq!(
270271
::core::mem::size_of::<crsql_ExtData>(),
271-
160usize,
272+
168usize,
272273
concat!("Size of: ", stringify!(crsql_ExtData))
273274
);
274275
assert_eq!(
@@ -498,4 +499,14 @@ fn bindgen_test_layout_crsql_ExtData() {
498499
stringify!(timestamp)
499500
)
500501
);
502+
assert_eq!(
503+
unsafe { ::core::ptr::addr_of!((*ptr).ordinalMap) as usize - ptr as usize },
504+
160usize,
505+
concat!(
506+
"Offset of field: ",
507+
stringify!(crsql_ExtData),
508+
"::",
509+
stringify!(ordinalMap)
510+
)
511+
);
501512
}

core/rs/core/src/commit.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use alloc::{boxed::Box, collections::BTreeMap, vec::Vec};
12
use core::{
23
ffi::{c_int, c_void},
4+
mem,
35
ptr::null,
46
};
57

@@ -31,4 +33,9 @@ pub unsafe fn commit_or_rollback_reset(ext_data: *mut crsql_ExtData) {
3133
(*ext_data).seq = 0;
3234
(*ext_data).timestamp = 0;
3335
(*ext_data).updatedTableInfosThisTx = 0;
36+
37+
let mut ordinals: mem::ManuallyDrop<Box<BTreeMap<Vec<u8>, i64>>> = mem::ManuallyDrop::new(
38+
Box::from_raw((*ext_data).ordinalMap as *mut BTreeMap<Vec<u8>, i64>),
39+
);
40+
ordinals.clear();
3441
}

core/rs/core/src/db_version.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ pub extern "C" fn crsql_init_last_db_versions_map(ext_data: *mut crsql_ExtData)
187187
unsafe { (*ext_data).lastDbVersions = Box::into_raw(Box::new(map)) as *mut c_void }
188188
}
189189

190+
#[no_mangle]
191+
pub extern "C" fn crsql_init_ordinal_map(ext_data: *mut crsql_ExtData) {
192+
let map: BTreeMap<Vec<u8>, i64> = BTreeMap::new();
193+
unsafe { (*ext_data).ordinalMap = Box::into_raw(Box::new(map)) as *mut c_void }
194+
}
195+
190196
#[no_mangle]
191197
pub extern "C" fn crsql_drop_last_db_versions_map(ext_data: *mut crsql_ExtData) {
192198
unsafe {
@@ -196,6 +202,15 @@ pub extern "C" fn crsql_drop_last_db_versions_map(ext_data: *mut crsql_ExtData)
196202
}
197203
}
198204

205+
#[no_mangle]
206+
pub extern "C" fn crsql_drop_ordinal_map(ext_data: *mut crsql_ExtData) {
207+
unsafe {
208+
drop(Box::from_raw(
209+
(*ext_data).ordinalMap as *mut BTreeMap<Vec<u8>, i64>,
210+
));
211+
}
212+
}
213+
199214
pub fn insert_db_version(
200215
ext_data: *mut crsql_ExtData,
201216
insert_site_id: &[u8],
@@ -258,6 +273,15 @@ pub unsafe fn get_or_set_site_ordinal(
258273
ext_data: *mut crsql_ExtData,
259274
site_id: &[u8],
260275
) -> Result<i64, ResultCode> {
276+
// check the cache first
277+
let mut ordinals: mem::ManuallyDrop<Box<BTreeMap<Vec<u8>, i64>>> = mem::ManuallyDrop::new(
278+
Box::from_raw((*ext_data).ordinalMap as *mut BTreeMap<Vec<u8>, i64>),
279+
);
280+
281+
if let Some(ordinal) = ordinals.get(site_id) {
282+
return Ok(*ordinal);
283+
}
284+
261285
let bind_result =
262286
(*ext_data)
263287
.pSelectSiteIdOrdinalStmt
@@ -268,11 +292,11 @@ pub unsafe fn get_or_set_site_ordinal(
268292
return Err(rc);
269293
}
270294

271-
match (*ext_data).pSelectSiteIdOrdinalStmt.step() {
295+
let ordinal = match (*ext_data).pSelectSiteIdOrdinalStmt.step() {
272296
Ok(ResultCode::ROW) => {
273297
let ordinal = (*ext_data).pSelectSiteIdOrdinalStmt.column_int64(0);
274298
reset_cached_stmt((*ext_data).pSelectSiteIdOrdinalStmt)?;
275-
Ok(ordinal)
299+
ordinal
276300
}
277301
Ok(_) => {
278302
reset_cached_stmt((*ext_data).pSelectSiteIdOrdinalStmt)?;
@@ -296,7 +320,7 @@ pub unsafe fn get_or_set_site_ordinal(
296320
Ok(_) => {
297321
let ordinal = (*ext_data).pSetSiteIdOrdinalStmt.column_int64(0);
298322
reset_cached_stmt((*ext_data).pSetSiteIdOrdinalStmt)?;
299-
Ok(ordinal)
323+
ordinal
300324
}
301325
Err(rc) => {
302326
reset_cached_stmt((*ext_data).pSetSiteIdOrdinalStmt)?;
@@ -308,5 +332,7 @@ pub unsafe fn get_or_set_site_ordinal(
308332
reset_cached_stmt((*ext_data).pSetSiteIdOrdinalStmt)?;
309333
return Err(rc);
310334
}
311-
}
335+
};
336+
ordinals.insert(site_id.to_vec(), ordinal);
337+
Ok(ordinal)
312338
}

core/rs/integration_check/src/t/test_db_version.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extern crate alloc;
2-
use alloc::{ffi::CString, string::String};
3-
use core::ffi::c_char;
2+
use alloc::{boxed::Box, collections::BTreeMap, ffi::CString, format, string::String, vec::Vec};
3+
use core::{ffi::c_char, mem};
44
use crsql_bundle::test_exports;
55
use sqlite::{Connection, ResultCode};
66
use sqlite_nostd as sqlite;
@@ -10,6 +10,11 @@ fn make_site() -> *mut c_char {
1010
inner_ptr
1111
}
1212

13+
fn convert_to_bytes(id: *mut c_char) -> Vec<u8> {
14+
let site_id_string = unsafe { CString::from_raw(id) };
15+
site_id_string.into_bytes()
16+
}
17+
1318
fn get_site_id(db: *mut sqlite::sqlite3) -> *mut c_char {
1419
let stmt = db
1520
.prepare_v2("SELECT crsql_site_id();")
@@ -112,8 +117,49 @@ fn test_next_db_version() -> Result<(), String> {
112117
Ok(())
113118
}
114119

120+
fn test_get_or_set_site_ordinal() -> Result<(), ResultCode> {
121+
let c = crate::opendb().expect("db opened");
122+
let db = &c.db;
123+
let raw_db = db.db;
124+
let ext_data = unsafe { test_exports::c::crsql_newExtData(raw_db, get_site_id(raw_db)) };
125+
126+
let site_id = convert_to_bytes(get_site_id(raw_db));
127+
let ordinal = unsafe { test_exports::db_version::get_or_set_site_ordinal(ext_data, &site_id)? };
128+
assert_eq!(0, ordinal);
129+
130+
let mut ordinals = unsafe {
131+
mem::ManuallyDrop::new(Box::from_raw(
132+
(*ext_data).ordinalMap as *mut BTreeMap<Vec<u8>, i64>,
133+
))
134+
};
135+
136+
assert_eq!(0, *(ordinals.get(&site_id).unwrap()));
137+
138+
// update ordinal in db but it should remain the same on the map
139+
let update_stmt =
140+
raw_db.prepare_v2("UPDATE crsql_site_id SET ordinal = 8 WHERE site_id = ?")?;
141+
update_stmt.bind_blob(1, &site_id, sqlite::Destructor::STATIC)?;
142+
update_stmt.step()?;
143+
144+
let ordinal = unsafe { test_exports::db_version::get_or_set_site_ordinal(ext_data, &site_id)? };
145+
assert_eq!(0, ordinal);
146+
147+
// clear ordinals and call func again, we should get update
148+
ordinals.clear();
149+
let ordinal = unsafe { test_exports::db_version::get_or_set_site_ordinal(ext_data, &site_id)? };
150+
assert_eq!(8, ordinal);
151+
152+
unsafe {
153+
test_exports::c::crsql_freeExtData(ext_data);
154+
};
155+
Ok(())
156+
}
157+
115158
pub fn run_suite() -> Result<(), String> {
116159
test_fetch_db_version_from_storage()?;
117160
test_next_db_version()?;
161+
if let Err(rc) = test_get_or_set_site_ordinal() {
162+
return Err(format!("test_get_or_set_site_ordinal failed: {:?}", rc));
163+
}
118164
Ok(())
119165
}

core/src/ext-data.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
void crsql_clear_stmt_cache(crsql_ExtData *pExtData);
99
void crsql_init_table_info_vec(crsql_ExtData *pExtData);
10+
void crsql_init_ordinal_map(crsql_ExtData *pExtData);
11+
void crsql_drop_ordinal_map(crsql_ExtData *pExtData);
1012
void crsql_drop_table_info_vec(crsql_ExtData *pExtData);
1113
void crsql_init_last_db_versions_map(crsql_ExtData *pExtData);
1214
void crsql_drop_last_db_versions_map(crsql_ExtData *pExtData);
@@ -74,10 +76,12 @@ crsql_ExtData *crsql_newExtData(sqlite3 *db, unsigned char *siteIdBuffer) {
7476
-1, SQLITE_PREPARE_PERSISTENT, &(pExtData->pDbVersionStmt), 0);
7577
pExtData->tableInfos = 0;
7678
pExtData->lastDbVersions = 0;
79+
pExtData->ordinalMap = 0;
7780
pExtData->rowsImpacted = 0;
7881
pExtData->updatedTableInfosThisTx = 0;
7982
crsql_init_table_info_vec(pExtData);
8083
crsql_init_last_db_versions_map(pExtData);
84+
crsql_init_ordinal_map(pExtData);
8185

8286
sqlite3_stmt *pStmt;
8387

@@ -147,6 +151,7 @@ void crsql_freeExtData(crsql_ExtData *pExtData) {
147151
crsql_clear_stmt_cache(pExtData);
148152
crsql_drop_table_info_vec(pExtData);
149153
crsql_drop_last_db_versions_map(pExtData);
154+
crsql_drop_ordinal_map(pExtData);
150155
sqlite3_free(pExtData);
151156
}
152157

core/src/ext-data.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct crsql_ExtData {
4848

4949
int mergeEqualValues;
5050
unsigned long long timestamp;
51+
void *ordinalMap;
5152
};
5253

5354
crsql_ExtData *crsql_newExtData(sqlite3 *db, unsigned char *siteIdBuffer);
@@ -57,5 +58,7 @@ int crsql_fetchPragmaSchemaVersion(sqlite3 *db, crsql_ExtData *pExtData,
5758
int crsql_fetchPragmaDataVersion(sqlite3 *db, crsql_ExtData *pExtData);
5859
int crsql_recreate_db_version_stmt(sqlite3 *db, crsql_ExtData *pExtData);
5960
void crsql_finalize(crsql_ExtData *pExtData);
61+
void crsql_init_ordinal_map(crsql_ExtData *pExtData);
62+
void crsql_drop_ordinal_map(crsql_ExtData *pExtData);
6063

6164
#endif

0 commit comments

Comments
 (0)