cartel_sqlite/runtime/raw/
mod.rs1mod vfs;
2
3use crate::{
4 catalogs, conn,
5 runtime::{self, Error, heap},
6 sys,
7};
8use o3::alloc;
9use std::{mem, ptr};
10
11#[repr(C, align(64))]
12struct Unit {
13 bytes: [mem::MaybeUninit<u8>; Span::ALIGNMENT],
14}
15
16pub(crate) struct Memory {
17 _memory: alloc::array::Block<mem::MaybeUninit<Unit>, usize>,
18}
19
20pub(crate) struct Span {
21 base: ptr::NonNull<u8>,
22 bytes: usize,
23}
24
25#[must_use]
31pub struct Permit(pub(super) ());
32
33struct Setup(Permit);
35
36impl Permit {
37 pub unsafe fn exclusive() -> Self {
41 Self(())
42 }
43
44 pub(super) fn initialize(self) -> Result<Self, Error> {
45 if unsafe {
46 libsqlite3_sys::sqlite3_compileoption_used(c"ENABLE_MEMORY_MANAGEMENT".as_ptr())
47 } != 0
48 {
49 return Err(Error::GlobalCache);
50 }
51 if unsafe {
52 libsqlite3_sys::sqlite3_compileoption_used(c"DISABLE_PAGECACHE_OVERFLOW_STATS".as_ptr())
53 } == 0
54 {
55 return Err(Error::CacheStats);
56 }
57 if unsafe { libsqlite3_sys::sqlite3_compileoption_used(c"ENABLE_STMTVTAB".as_ptr()) } != 0 {
58 return Err(Error::StatementVtab);
59 }
60 if unsafe { libsqlite3_sys::sqlite3_compileoption_used(c"OMIT_WSD".as_ptr()) } != 0 {
61 return Err(Error::WritableStatic);
62 }
63 if unsafe { libsqlite3_sys::sqlite3_compileoption_used(c"ENABLE_SQLLOG".as_ptr()) } != 0 {
64 return Err(Error::StatementLog);
65 }
66 Setup(self).initialize()
67 }
68}
69
70impl Setup {
71 fn initialize(self) -> Result<Permit, Error> {
72 use heap::raw;
73 use vfs::Vfs;
74
75 let code =
76 unsafe { libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MULTITHREAD) };
77 if code != libsqlite3_sys::SQLITE_OK {
78 return Err(Error::Threading(sys::Code::new(code)));
79 }
80 unsafe {
84 libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_URI, 0);
85 libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MEMSTATUS, 0);
86 libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_LOOKASIDE, 0, 0);
88 libsqlite3_sys::sqlite3_config(
89 libsqlite3_sys::SQLITE_CONFIG_PAGECACHE,
90 ptr::null_mut::<std::ffi::c_void>(),
91 0,
92 20,
93 );
94 }
95 let cache = libsqlite3_sys::sqlite3_pcache_methods2 {
96 iVersion: 1,
97 pArg: ptr::null_mut(),
98 xInit: None,
99 xShutdown: None,
100 xCreate: None,
101 xCachesize: None,
102 xPagecount: None,
103 xFetch: None,
104 xUnpin: None,
105 xRekey: None,
106 xTruncate: None,
107 xDestroy: None,
108 xShrink: None,
109 };
110 unsafe {
113 libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_PCACHE2, &raw const cache);
114 }
115 let hooks = raw::methods();
116 unsafe {
119 libsqlite3_sys::sqlite3_config(libsqlite3_sys::SQLITE_CONFIG_MALLOC, &raw const hooks);
120 }
121 raw::foreign(|| {
122 let code = unsafe { libsqlite3_sys::sqlite3_initialize() };
123 let result = if code == libsqlite3_sys::SQLITE_OK {
124 unsafe { Vfs::install() }
125 } else {
126 Err(Error::Initialization(sys::Code::new(code)))
127 };
128 if result.is_err() {
129 unsafe { libsqlite3_sys::sqlite3_shutdown() };
132 }
133 result
134 })?;
135 Ok(self.0)
136 }
137}
138
139impl Memory {
140 pub(in crate::runtime) fn new<I: catalogs::Catalog>(
141 layout: &runtime::Layout<'_, I>,
142 ) -> Result<(Self, heap::raw::Span, Span, Span, Span, Span), runtime::Error> {
143 let (sqlite, collect_bytes, statement_bytes, lookaside_bytes) = layout.dimensions();
145 let phase = conn::raw::Vacant::<'_, '_, I>::LAYOUT;
146 let prefix = phase.size().next_multiple_of(Span::ALIGNMENT);
147 let collect = prefix + heap::layout::Layout::PREFIX_BYTES + sqlite.bytes();
148 let stmts = collect + collect_bytes.next_multiple_of(Span::ALIGNMENT);
149 let aside = stmts + statement_bytes;
150 let bytes = aside + lookaside_bytes.next_multiple_of(Span::ALIGNMENT);
151 let units = bytes / Span::ALIGNMENT;
152 let mut memory =
153 alloc::array::Block::try_new(units, ()).map_err(runtime::Error::Allocation)?;
154 let base = unsafe { ptr::NonNull::new_unchecked(memory.as_mut_ptr().cast()) };
156 let start = Span::new(base, prefix, collect - prefix).base();
157 let collect = Span::new(base, collect, collect_bytes);
158 let stmts = Span::new(base, stmts, aside - stmts);
159 let aside = Span::new(base, aside, bytes - aside);
160 let phase = Span::new(base, 0, phase.size());
161 let sqlite = unsafe { heap::raw::Span::new(start, sqlite) };
163 Ok((
164 Self { _memory: memory },
165 sqlite,
166 collect,
167 stmts,
168 aside,
169 phase,
170 ))
171 }
172}
173
174impl Span {
175 pub(crate) const ALIGNMENT: usize = 64;
176
177 fn new(base: ptr::NonNull<u8>, start: usize, bytes: usize) -> Self {
178 let base = unsafe { ptr::NonNull::new_unchecked(base.as_ptr().add(start)) };
180 Self { base, bytes }
181 }
182
183 pub(crate) const fn into_parts(self) -> (ptr::NonNull<u8>, usize) {
184 (self.base, self.bytes)
185 }
186
187 pub(crate) const fn as_mut_ptr(&mut self) -> *mut u8 {
188 self.base.as_ptr()
189 }
190
191 pub(crate) const fn len(&self) -> usize {
192 self.bytes
193 }
194
195 pub(crate) const fn base(&self) -> ptr::NonNull<u8> {
196 self.base
197 }
198}
199
200const _: () = {
201 assert!(mem::size_of::<Unit>() == Span::ALIGNMENT);
202 assert!(mem::align_of::<Unit>() == Span::ALIGNMENT);
203};