I'm getting a strange error after attempting to open, read, and/or write many files. After about 20-25 writes I start getting the following error
Panicked at 'called `Result::unwrap()` on an `Err` value: Io(Error { kind: UnexpectedEof, message: "failed to fill whole buffer" })', stable-fs-0.1.11/src/storage/types.rs:85:51
Even after doing a redeploy I am still unable to open any additional files after I hit what feels like some sort of limit.
Here is a simple canister that illustrates the problem.
After running dfx cansiter call canister write_25_files
once it cannot be called again without this error popping up. Nor can read_25_file
be called without this same error.
use std::{
cell::RefCell,
io::{self, Read, Write},
};
use ic_stable_structures::{
memory_manager::{MemoryId, MemoryManager},
DefaultMemoryImpl,
};
thread_local! {
static MEMORY_MANAGER_REF_CELL: RefCell<MemoryManager<DefaultMemoryImpl>> = RefCell::new(MemoryManager::init(DefaultMemoryImpl::default()));
}
#[ic_cdk::init]
fn my_init() {
let polyfill_memory =
MEMORY_MANAGER_REF_CELL.with(|manager| manager.borrow().get(MemoryId::new(0)));
ic_wasi_polyfill::init_with_memory(&[], &[], polyfill_memory);
}
#[ic_cdk::post_upgrade]
fn my_post_upgrade() {
let polyfill_memory =
MEMORY_MANAGER_REF_CELL.with(|thing| thing.borrow().get(MemoryId::new(0)));
ic_wasi_polyfill::init_with_memory(&[], &[], polyfill_memory);
}
#[ic_cdk::update]
pub fn write_25_files() {
let dir_name = "auto";
let file_count: u8 = 25;
std::fs::create_dir_all(dir_name).unwrap();
for i in 0..file_count {
let path = format!("{}/my_file_{}.txt", dir_name, i);
ic_cdk::println!("Writing to {}", path);
let mut file = std::fs::OpenOptions::new()
.create(true)
.write(true)
.open(&path)
.unwrap();
let write_buff = [i; SIZE_OF_FILE];
file.write(&write_buff).unwrap();
drop(file);
}
}
#[ic_cdk::update]
pub fn read_25_files() {
let dir_name = "auto";
let file_count: u8 = 25;
std::fs::create_dir_all(dir_name).unwrap();
for i in 0..file_count {
let path = format!("{}/my_file_{}.txt", dir_name, i);
ic_cdk::println!("Writing to {}", path);
let mut file = std::fs::OpenOptions::new()
.create(true)
.read(true)
.open(&path)
.unwrap();
let mut read_buf = [1, 1, 1];
let num_bytes = file.read(&mut read_buf).unwrap();
ic_cdk::println!("Read {} bytes {}", num_bytes, path);
}
}