use std::{fmt, mem};
use super::avl;
use super::dmu_objset::ObjectSet;
use super::from_bytes::FromBytes;
use super::zfs;
const SPACE_MAP_HISTOGRAM_SIZE: usize = 32;
#[derive(Debug)]
pub struct SpaceMapPhys {
object: u64, objsize: u64, alloc: u64,
}
impl FromBytes for SpaceMapPhys {}
pub struct SpaceMap {
start: u64, size: u64, shift: u8, length: u64, alloc: u64, object: u64, blksz: u32, phys: SpaceMapPhys, }
impl SpaceMap {
pub fn open(os: &mut ObjectSet,
object: u64,
start: u64,
size: u64,
shift: u8)
-> zfs::Result<Self> {
assert!(object != 0);
let phys = SpaceMapPhys {
object: 0, objsize: 0, alloc: 0, };
let block_size = 0;
let mut space_map = SpaceMap {
start: start,
size: size,
shift: shift,
object: object,
length: 0,
alloc: 0,
blksz: block_size,
phys: phys,
};
Ok(space_map)
}
pub fn load_avl(&self,
tree: &mut avl::Tree<Segment, u64>,
bytes: &[u8],
map_type: MapType)
-> Result<(), &str> {
for i in 0..(self.size as usize) {
let entry = Entry::from_bytes(&bytes[i * mem::size_of::<Entry>()..]).unwrap();
let entry_map_type = match entry.map_type() {
Some(map_type) => map_type,
None => {
return Err("Invalid map type");
}
};
if entry.debug() != 1 && entry_map_type == map_type {
tree.insert(Segment::from_entry(&entry));
}
}
tree.in_order(|node| {
println!("{:?}", node.value());
});
Ok(())
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum MapType {
Alloc = 0,
Free = 1,
}
impl MapType {
pub fn from_u64(u: u64) -> Option<Self> {
match u {
0 => Some(MapType::Alloc),
1 => Some(MapType::Free),
_ => None,
}
}
}
#[derive(Copy, Clone)]
pub struct Entry(u64);
impl FromBytes for Entry {}
impl Entry {
pub fn debug(&self) -> u64 {
(self.0 >> 63) & 0x1 }
pub fn size(&self) -> u64 {
self.0 & 0x7FFF }
pub fn map_type(&self) -> Option<MapType> {
MapType::from_u64((self.0 >> 15) & 0x1) }
pub fn offset(&self) -> u64 {
(self.0 >> 16) & 0x7FFFFFFFFFFF }
pub fn action(&self) -> u64 {
(self.0 >> 60) & 0x7 }
pub fn sync_pass(&self) -> u64 {
(self.0 >> 50) & 0x3FF }
pub fn txg(&self) -> u64 {
self.0 & 0x3FFFFFFFFFFFF }
}
impl fmt::Debug for Entry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.debug() == 1 {
try!(write!(f,
"DEBUG: action:0x{:X} sync_pass:{:X} txg:0x{:X}",
self.action(),
self.sync_pass(),
self.txg()));
} else {
try!(write!(f,
"ENTRY: size:0x{:X} map_type:{:?} offset:0x{:X}",
self.size(),
self.map_type(),
self.offset()));
}
Ok(())
}
}
#[derive(Debug)]
pub struct Segment {
pub start: u64,
pub size: u64,
}
impl Segment {
fn from_entry(entry: &Entry) -> Self {
Segment {
start: entry.offset(),
size: entry.size(),
}
}
}