use std::thread;
use std::fs::{copy, remove_file};
use std::path::Path;
use std::time::Duration;
use pi_async_rt::rt::{AsyncRuntime,
multi_thread::MultiTaskRuntimeBuilder,
startup_global_time_loop};
use pi_store::devices::{BlockDevice, BlockLocation, DeviceStatus, simple_device::{Binary, SimpleDevice}};
use pi_blocks_allocator::device::{BuddyBlocksDeviceBuilder, BuddyBlocksDevice};
#[test]
fn test_buddy_blocks_device() {
env_logger::init();
let _handle = startup_global_time_loop(100);
let builder = MultiTaskRuntimeBuilder::default();
let rt = builder.build();
let rt_copy = rt.clone();
rt.spawn(async move {
let _r = remove_file("./buddy_blocks/000.dat");
let _r = remove_file("./buddy_blocks/000.dat.0");
let _r = remove_file("./buddy_blocks/000.dat.1");
let mut builder = BuddyBlocksDeviceBuilder::new("./buddy_blocks");
let device = builder
.build(rt_copy.clone())
.await
.unwrap();
assert!(device.is_full_free());
assert!(device.is_freed(&BlockLocation::empty()));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), device.capacity().unwrap());
assert_eq!(device.used_size(), 0);
assert_eq!(device.block_unit_len(), 4096);
assert_eq!(device.max_block_size(), 4096 * 4096 * 8);
assert_eq!(device.get_url().unwrap().to_string().as_str(),
"file:///E:/rust/pi_mastser/crate%20master/pi_store/buddy_blocks/");
assert_eq!(device.get_status() as u8, 1);
let mut blocks = Vec::with_capacity(10);
for size in vec![1, 4096, 4097, 8192, 8193, 10000, 20000, 65536, 65537, 4096 * 4096 * 8, 4096 * 4096 * 8 + 1] {
let block = device.alloc_block(size).await;
match size {
1 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 1));
assert_eq!(device.used_size(), 1 * 4096);
},
4096 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 2));
assert_eq!(device.used_size(), 2 * 4096);
},
4097 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 4));
assert_eq!(device.used_size(), 4 * 4096);
},
8192 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 6));
assert_eq!(device.used_size(), 6 * 4096);
},
8193 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 10));
assert_eq!(device.used_size(), 10 * 4096);
},
10000 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 14));
assert_eq!(device.used_size(), 14 * 4096);
},
20000 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 22));
assert_eq!(device.used_size(), 22 * 4096);
},
65536 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 38));
assert_eq!(device.used_size(), 38 * 4096);
},
65537 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70));
assert_eq!(device.used_size(), 70 * 4096);
},
134217728 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70));
assert_eq!(device.used_size(), 134504448);
},
134217729 => {
assert!(block.is_empty());
assert!(device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70));
assert_eq!(device.used_size(), 134504448);
},
_ => unimplemented!(),
}
blocks.push(block);
}
for (index, block) in blocks.iter().enumerate() {
if !device.is_freed(&block) {
let r = device
.write(block, &format!("This is {:?}", index).into_bytes())
.await;
assert!(r.is_ok());
}
}
for (index, block) in blocks.iter().enumerate() {
if !device.is_freed(&block) {
let r = device
.read(block)
.await;
assert!(r.is_ok());
assert_eq!(String::from_utf8_lossy(&r.unwrap()[..9]).to_string(), format!("This is {:?}", index));
println!("read {:?} ok", index);
}
}
rt_copy.timeout(6000).await;
let from = "./buddy_blocks/000.dat";
let to = "./buddy_blocks/000.dat.0";
let r = copy(from, to);
assert!(r.is_ok());
for (index, block) in blocks.into_iter().enumerate() {
if !device.is_freed(&block) {
println!("free block: {:?}", block);
let r = device.free_block(&block).await;
assert!(r);
assert!(device.is_freed(&block));
match index {
0 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 69));
assert_eq!(device.used_size(), 134504448 - 1 * 4096);
},
1 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 68));
assert_eq!(device.used_size(), 134504448 - 2 * 4096);
},
2 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 66));
assert_eq!(device.used_size(), 134504448 - 4 * 4096);
},
3 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 64));
assert_eq!(device.used_size(), 134504448 - 6 * 4096);
},
4 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 60));
assert_eq!(device.used_size(), 134504448 - 10 * 4096);
},
5 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 56));
assert_eq!(device.used_size(), 134504448 - 14 * 4096);
},
6 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 48));
assert_eq!(device.used_size(), 134504448 - 22 * 4096);
},
7 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 32));
assert_eq!(device.used_size(), 134504448 - 38 * 4096);
},
8 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 0));
assert_eq!(device.used_size(), 134504448 - 70 * 4096);
},
9 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.used_size(), 134504448 - 70 * 4096 - 4096 * 4096 * 8);
},
_ => unimplemented!(),
}
}
}
println!("=======================");
let mut blocks = Vec::with_capacity(10);
for size in vec![1, 4096, 4097, 8192, 8193, 10000, 20000, 65536, 65537, 4096 * 4096 * 8, 4096 * 4096 * 8 + 1] {
let block = device.alloc_block(size).await;
match size {
1 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 1));
assert_eq!(device.used_size(), 1 * 4096);
},
4096 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 2));
assert_eq!(device.used_size(), 2 * 4096);
},
4097 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 4));
assert_eq!(device.used_size(), 4 * 4096);
},
8192 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 6));
assert_eq!(device.used_size(), 6 * 4096);
},
8193 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 10));
assert_eq!(device.used_size(), 10 * 4096);
},
10000 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 14));
assert_eq!(device.used_size(), 14 * 4096);
},
20000 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 22));
assert_eq!(device.used_size(), 22 * 4096);
},
65536 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 38));
assert_eq!(device.used_size(), 38 * 4096);
},
65537 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 70));
assert_eq!(device.used_size(), 70 * 4096);
},
134217728 => {
assert!(!block.is_empty());
assert!(!device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70));
assert_eq!(device.used_size(), 134504448);
},
134217729 => {
assert!(block.is_empty());
assert!(device.is_freed(&block));
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70));
assert_eq!(device.used_size(), 134504448);
},
_ => unimplemented!(),
}
blocks.push(block);
}
for (index, block) in blocks.iter().enumerate() {
if !device.is_freed(&block) {
let r = device
.write(block, &format!("This is {:?}", index).into_bytes())
.await;
assert!(r.is_ok());
}
}
for (index, block) in blocks.iter().enumerate() {
if !device.is_freed(&block) {
let r = device
.read(block)
.await;
assert!(r.is_ok());
assert_eq!(String::from_utf8_lossy(&r.unwrap()[..9]).to_string(), format!("This is {:?}", index));
println!("read {:?} ok", index);
}
}
rt_copy.timeout(6000).await;
let from = "./buddy_blocks/000.dat";
let to = "./buddy_blocks/000.dat.1";
let r = copy(from, to);
assert!(r.is_ok());
for (index, block) in blocks.into_iter().enumerate() {
if !device.is_freed(&block) {
println!("free block: {:?}", block);
let r = device.free_block(&block).await;
assert!(r);
assert!(device.is_freed(&block));
match index {
0 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 69));
assert_eq!(device.used_size(), 134504448 - 1 * 4096);
},
1 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 68));
assert_eq!(device.used_size(), 134504448 - 2 * 4096);
},
2 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 66));
assert_eq!(device.used_size(), 134504448 - 4 * 4096);
},
3 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 64));
assert_eq!(device.used_size(), 134504448 - 6 * 4096);
},
4 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 60));
assert_eq!(device.used_size(), 134504448 - 10 * 4096);
},
5 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 56));
assert_eq!(device.used_size(), 134504448 - 14 * 4096);
},
6 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 48));
assert_eq!(device.used_size(), 134504448 - 22 * 4096);
},
7 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 32));
assert_eq!(device.used_size(), 134504448 - 38 * 4096);
},
8 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 0));
assert_eq!(device.used_size(), 134504448 - 70 * 4096);
},
9 => {
assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.avail_size().unwrap(), 4096 * 4096 * 8 * 2);
assert_eq!(device.used_size(), 134504448 - 70 * 4096 - 4096 * 4096 * 8);
},
_ => unimplemented!(),
}
}
}
});
thread::sleep(Duration::from_millis(1000000000));
}
#[test]
fn test_load_buddy_blocks_device_after_crashed() {
env_logger::init();
let _handle = startup_global_time_loop(100);
let builder = MultiTaskRuntimeBuilder::default();
let rt = builder.build();
let rt_copy = rt.clone();
rt.spawn(async move {
let mut builder = BuddyBlocksDeviceBuilder::new("./buddy_blocks1");
builder = builder.set_collect_interval(Duration::from_millis(1000000000));
let device = builder
.build(rt_copy.clone())
.await
.unwrap();
assert_eq!(device.max_block_size(), 4096 * 4096 * 8);
assert_eq!(device.get_url().unwrap().to_string().as_str(),
"file:///E:/rust/pi_mastser/crate%20master/pi_store/buddy_blocks1/");
assert_eq!(device.get_status() as u8, 1);
let metadata = device.get_metadata().await;
println!("device metadata: {:#?}", metadata);
let mut blocks = Vec::with_capacity(10);
for size in vec![1, 4096, 4097, 8192, 8193, 10000, 20000, 65536, 65537, 4096 * 4096 * 8, 4096 * 4096 * 8 + 1] {
let block = device.alloc_block(size).await;
blocks.push(block);
}
for (index, block) in blocks.iter().enumerate() {
if !device.is_freed(&block) {
let r = device
.write(block, &format!("This is {:?}", index).into_bytes())
.await;
assert!(r.is_ok());
}
}
for (index, block) in blocks.iter().enumerate() {
if !device.is_freed(&block) {
let r = device
.read(block)
.await;
assert!(r.is_ok());
assert_eq!(String::from_utf8_lossy(&r.unwrap()[..9]).to_string(), format!("This is {:?}", index));
println!("read {:?} ok", index);
}
}
let r = device.mamually_commit_block_groups().await;
assert!(r.is_ok());
let r = device.mamually_commit_block_indexes().await;
assert!(r.is_ok());
let metadata = device.get_metadata().await;
println!("device metadata: {:#?}", metadata);
std::process::exit(0);
});
thread::sleep(Duration::from_millis(1000000000));
}
#[test]
fn test_simple_device() {
let builder = MultiTaskRuntimeBuilder::default();
let rt = builder.build();
let rt_copy = rt.clone();
rt.spawn(async move {
match SimpleDevice::open(rt_copy, "./device/0.simple", None).await {
Err(e) => panic!("Open simple device failed, reason: {:?}", e),
Ok(device) => {
println!("!!!!!!device: {:?}", device.get_status());
let location = device.alloc_block(50).await;
println!("!!!!!!location: {:?}", location);
match device.write(&location,
&Binary::new("Hello Simple device".to_string().into_bytes())).await {
Err(e) => panic!("Write block failed, reason: {:?}", e),
Ok(len) => {
println!("!!!!!!write ok, len: {}", len);
}
}
match device.read(&location).await {
Err(e) => panic!("Read block failed, reason: {:?}", e),
Ok(block) => {
println!("read writed data: {:?}", String::from_utf8_lossy(block.as_ref()))
}
}
},
}
});
thread::sleep(Duration::from_millis(1000000000));
}
#[test]
fn test_simple_device_collect() {
let builder = MultiTaskRuntimeBuilder::default();
let rt = builder.build();
let rt_copy = rt.clone();
rt.spawn(async move {
match SimpleDevice::open(rt_copy, "./device/0.simple", None).await {
Err(e) => panic!("Open simple device failed, reason: {:?}", e),
Ok(device) => {
println!("!!!!!!device: {:?}", device.get_status());
match device.collect_alloced_blocks(&[BlockLocation::from(1)]).await {
Err(e) => println!("Collect alloced failed, reason: {:?}", e),
Ok(size) => {
println!("collect alloced ok, size: {}", size);
}
}
let location = device.alloc_block(50).await;
println!("!!!!!!location: {:?}", location);
match device.write(&location,
&Binary::new("Hello Simple device".to_string().into_bytes())).await {
Err(e) => panic!("Write block failed, reason: {:?}", e),
Ok(len) => {
println!("!!!!!!write ok, len: {}", len);
}
}
match device.read(&location).await {
Err(e) => panic!("Read block failed, reason: {:?}", e),
Ok(block) => {
println!("read writed data: {:?}", String::from_utf8_lossy(block.as_ref()))
}
}
},
}
});
thread::sleep(Duration::from_millis(1000000000));
}