1use std::{
2 fmt::{Debug, Display},
3 time::Instant,
4};
5
6use clap::Parser;
7use miette::{IntoDiagnostic, Result};
8use naming::GetFlags;
9use tracing::Level;
10use twizzler::{
11 Invariant,
12 alloc::{
13 arena::{ArenaAllocator, ArenaObject},
14 invbox::InvBox,
15 },
16 collections::vec::{VecObject, VecObjectAlloc},
17 marker::Invariant,
18 object::{MapFlags, ObjID, Object, ObjectBuilder, RawObject},
19};
20use twizzler_abi::syscall::sys_object_ctrl;
21use twizzler_rt_abi::{error::TwzError, object::ObjectHandle};
22
23#[allow(dead_code)]
24#[derive(Invariant)]
25struct Foo {
26 data: InvBox<u32, ArenaAllocator>,
27 local_data: u32,
28}
29
30impl Debug for Foo {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 f.debug_struct("Foo")
33 .field("local_data", &self.local_data)
34 .field("data (ptr)", &self.data.global())
35 .field("data (val)", &*self.data.resolve())
36 .finish()
37 }
38}
39
40impl Display for Foo {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(
43 f,
44 "Foo ({:p}): local {}, ptr: {:x} :: ",
45 self,
46 &self.local_data,
47 &self.data.as_ptr().raw(),
48 )?;
49 write!(f, "{}", &*self.data.resolve())
50 }
51}
52
53fn create_arena() -> Result<ArenaObject> {
54 let obj = ObjectBuilder::default().persist(true);
55 ArenaObject::new(obj).into_diagnostic()
56}
57
58fn open_arena(id: ObjID) -> Result<ArenaObject> {
59 ArenaObject::from_objid(id).into_diagnostic()
60}
61
62fn create_vector_object<T: Debug + Invariant>() -> Result<VecObject<T, VecObjectAlloc>> {
63 let obj = ObjectBuilder::default().persist(true);
64 VecObject::<T, VecObjectAlloc>::new(obj).into_diagnostic()
65}
66
67fn open_vector_object<T: Debug + Invariant>(id: ObjID) -> Result<VecObject<T, VecObjectAlloc>> {
68 Ok(VecObject::from(
69 Object::map(id, MapFlags::PERSIST | MapFlags::READ | MapFlags::WRITE).into_diagnostic()?,
70 ))
71}
72
73#[derive(clap::Parser, Clone, Copy, Debug)]
74struct Cli {
75 sub: SubCommand,
76 #[clap(default_value = "u32")]
77 ty: VecTy,
78}
79
80#[derive(clap::ValueEnum, clap::Parser, Clone, Copy, Debug)]
81enum VecTy {
82 U32,
83 Foo,
84}
85
86#[derive(clap::ValueEnum, clap::Subcommand, Clone, Copy, Debug)]
87enum SubCommand {
88 New,
89 Push,
90 Append,
91 Read,
92 Hw,
93 Rdb,
94 Preload,
95 Big,
96}
97
98fn open_or_create_arena() -> Result<ArenaObject> {
99 let mut nh = naming::dynamic_naming_factory().unwrap();
100 let name = format!("/data/ptest-arena");
101 let vo = if let Ok(node) = nh.get(&name, GetFlags::empty()) {
102 println!("reopened-arena: {:?}", node.id);
103 open_arena(node.id)
104 } else {
105 let vo = create_arena()?;
106 println!("new-arena: {:?}", vo.object().id());
107 let _ = nh.remove(&name);
108 nh.put(&name, vo.object().id()).into_diagnostic()?;
109 Ok(vo)
110 };
111 vo
112}
113fn open_or_create_vector_object<T: Debug + Invariant>(
114 name: &str,
115) -> Result<VecObject<T, VecObjectAlloc>> {
116 let mut nh = naming::dynamic_naming_factory().unwrap();
117 let name = format!("/data/ptest-obj-{}", name);
118 let vo = if let Ok(node) = nh.get(&name, GetFlags::empty()) {
119 println!("reopened: {:?}", node.id);
120 open_vector_object::<T>(node.id)
121 } else {
122 let vo = create_vector_object::<T>()?;
123 println!("new: {:?}", vo.object().id());
124 let _ = nh.remove(&name);
125 nh.put(&name, vo.object().id()).into_diagnostic()?;
126 Ok(vo)
127 };
128 vo
129}
130
131impl Foo {
132 fn new_in(
133 place: impl AsRef<ObjectHandle>,
134 val: u32,
135 alloc: ArenaAllocator,
136 ) -> Result<Self, TwzError> {
137 Ok(Self {
138 data: InvBox::new_in(place, val, alloc)?,
139 local_data: val,
140 })
141 }
142}
143
144fn do_push_foo(mut vo: VecObject<Foo, VecObjectAlloc>, arena: ArenaObject) {
145 let val = vo.len() as u32;
146 vo.push_ctor(|r| {
147 let foo = Foo::new_in(&r, val, arena.allocator())?;
148 Ok(r.write(foo))
149 })
150 .unwrap();
151}
152
153fn do_append_foo(mut vo: VecObject<Foo, VecObjectAlloc>, arena: ArenaObject) {
154 for i in 0..8 {
155 tracing::info!("PUSH {}", i);
156 vo.push_ctor(|r| {
157 let foo = Foo::new_in(&r, i, arena.allocator())?;
158 Ok(r.write(foo))
159 })
160 .unwrap();
161 tracing::info!("DONE: {}", i);
162 }
163}
164
165fn do_push(vo: VecObject<u32, VecObjectAlloc>) {
166 let mut vo = vo;
167 vo.push(vo.len() as u32).unwrap();
168}
169
170fn do_append(vo: VecObject<u32, VecObjectAlloc>) {
171 let mut vo = vo;
172 for i in 0..100 {
173 vo.push(i).unwrap();
174 }
175}
176
177fn do_read<T: Debug + Invariant + Display>(vo: VecObject<T, VecObjectAlloc>) {
178 for i in vo.iter().enumerate() {
179 println!("entry {}: {}", i.0, i.1);
180 }
181}
182
183#[link(name = "c")]
184unsafe extern "C" {}
185fn main() {
186 tracing::subscriber::set_global_default(
187 tracing_subscriber::FmtSubscriber::builder()
188 .with_max_level(Level::INFO)
189 .finish(),
190 )
191 .unwrap();
192 let cli = Cli::parse();
193 println!("==> {:?}", cli);
194
195 let f = sgtest::bar(sgtest::Foo { x: 42 });
196 println!("==> foo: {:?}", f);
197
198 let mut nh = naming::dynamic_naming_factory().unwrap();
199 match cli.sub {
200 SubCommand::Hw => {
201 let top = hwlocality::topology::Topology::new().unwrap();
202 println!("{:#?}", top);
203 let cpus = top.complete_cpuset();
204 println!("==> {:?}", cpus);
205 }
206 SubCommand::New => match cli.ty {
207 VecTy::U32 => {
208 let _ = nh.remove("/data/ptest-obj-u32");
209 let vo = create_vector_object::<u32>().unwrap();
210 println!("new: {:?}", vo.object().id());
211 nh.put("/data/ptest-obj-u32", vo.object().id()).unwrap();
212 }
213 VecTy::Foo => {
214 let _ = nh.remove("/data/ptest-obj-foo");
215 let _ = nh.remove("/data/ptest-arena");
216 let vo = create_vector_object::<u32>().unwrap();
217 println!("new: {:?}", vo.object().id());
218 nh.put("/data/ptest-obj-foo", vo.object().id()).unwrap();
219
220 let vo = create_arena().unwrap();
221 println!("new arena: {:?}", vo.object().id());
222 nh.put("/data/ptest-arena", vo.object().id()).unwrap();
223 }
224 },
225 SubCommand::Push => match cli.ty {
226 VecTy::U32 => {
227 let vo = open_or_create_vector_object::<u32>("u32").unwrap();
228 let start = std::time::Instant::now();
229 do_push(vo);
230 let end = std::time::Instant::now();
231 println!("done!: {:?}", end - start);
232 }
233 VecTy::Foo => {
234 let vo = open_or_create_vector_object::<Foo>("foo").unwrap();
235 let arena = open_or_create_arena().unwrap();
236 let start = std::time::Instant::now();
237 do_push_foo(vo, arena);
238 let end = std::time::Instant::now();
239 println!("done!: {:?}", end - start);
240 }
241 },
242 SubCommand::Append => {
243 let vo = open_or_create_vector_object::<u32>("u32").unwrap();
244 let start = std::time::Instant::now();
245 match cli.ty {
246 VecTy::U32 => do_append(vo),
247 VecTy::Foo => {
248 let vo = open_or_create_vector_object::<Foo>("foo").unwrap();
249 let arena = open_or_create_arena().unwrap();
250 do_append_foo(vo, arena)
251 }
252 }
253 let end = std::time::Instant::now();
254 println!("done!: {:?}", end - start);
255 }
256 SubCommand::Read => match cli.ty {
257 VecTy::U32 => {
258 let vo = open_or_create_vector_object::<u32>("u32").unwrap();
259 let start = std::time::Instant::now();
260 do_read(vo);
261 let end = std::time::Instant::now();
262 println!("done!: {:?}", end - start);
263 }
264 VecTy::Foo => {
265 let vo = open_or_create_vector_object::<Foo>("foo").unwrap();
266 let start = std::time::Instant::now();
267 do_read(vo);
268 let end = std::time::Instant::now();
269 println!("done!: {:?}", end - start);
270 }
271 },
272 SubCommand::Preload => {
273 let start = std::time::Instant::now();
274 let id = nh.get("/ext/rst", GetFlags::empty()).unwrap().id;
275 sys_object_ctrl(id, twizzler_abi::syscall::ObjectControlCmd::Preload).unwrap();
276 let end = std::time::Instant::now();
277 println!("done!: {:?}", end - start);
278 }
279 SubCommand::Big => {
280 const LEN: usize = 1024 * 1024 * 100;
281
282 if let Ok(n) = nh.get("/data/big", GetFlags::empty()) {
284 let obj = Object::<u8>::map(n.id, MapFlags::READ).unwrap();
285 let obj = unsafe { obj.cast::<[u8; LEN]>() };
286 let base = obj.base_ptr::<u8>();
287 let slice = unsafe { core::slice::from_raw_parts(base, LEN) };
288 let sum = slice.iter().fold(0u32, |acc, x| acc + *x as u32);
289 println!("SUM for {} IS: {}", obj.id(), sum);
290 let mut b = 0u16;
291 for (i, s) in slice.iter().enumerate() {
292 b += 1;
293 if *s != (b - 1) as u8 {
294 println!("wrong at {}: expect: {}, got: {}", i, (b - 1) as u8, *s);
295 }
296 }
297 return;
298 }
299
300 let obj = ObjectBuilder::default().persist(true).build(0u8).unwrap();
301 let obj = unsafe { obj.cast::<[u8; LEN]>() };
302 let mut obj = unsafe { obj.as_mut().unwrap() };
303 println!("filling...");
304 let start = Instant::now();
305 let mut base = obj.base_mut();
306 let mut b = 0u16;
307 base.fill_with(|| {
308 b += 1;
309 (b - 1) as u8
310 });
311
312 let sum = base.iter().fold(0u32, |acc, x| acc + *x as u32);
313 println!("SUM WAS: {} for {}", sum, obj.id());
314 println!("{}ms. syncing...", start.elapsed().as_millis());
315 let start = Instant::now();
316 obj.sync().unwrap();
317 println!("=> {}ms", start.elapsed().as_millis());
318 let _ = nh.remove("/data/big");
319 nh.put("/data/big", obj.id()).unwrap();
320
321 }
332 SubCommand::Rdb => {
333 println!("in progress");
334 } }
349
350 }