Skip to content

Commit

Permalink
Implement farm resizing
Browse files Browse the repository at this point in the history
  • Loading branch information
nazar-pc committed Aug 9, 2023
1 parent a8e780d commit 4f080d8
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 49 deletions.
85 changes: 52 additions & 33 deletions crates/subspace-farmer/src/single_disk_plot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use crate::single_disk_plot::piece_reader::PieceReader;
pub use crate::single_disk_plot::plotting::PlottingError;
use crate::single_disk_plot::plotting::{plotting, plotting_scheduler};
use crate::utils::JoinOnDrop;
use bytesize::ByteSize;
use derive_more::{Display, From};
use event_listener_primitives::{Bag, HandlerId};
use futures::channel::{mpsc, oneshot};
Expand Down Expand Up @@ -283,22 +282,12 @@ pub enum SingleDiskPlotError {
/// Piece cache error
#[error("Piece cache error: {0}")]
PieceCacheError(#[from] DiskPieceCacheError),
/// Can't preallocate metadata file, probably not enough space on disk
#[error("Can't preallocate metadata file, probably not enough space on disk: {0}")]
CantPreallocateMetadataFile(io::Error),
/// Can't preallocate plot file, probably not enough space on disk
#[error("Can't preallocate plot file, probably not enough space on disk: {0}")]
CantPreallocatePlotFile(io::Error),
/// Can't resize plot after creation
#[error(
"Usable plotting space of plot {id} {new_space} is different from {old_space} when plot \
was created, resizing isn't supported yet"
)]
CantResize {
/// Plot ID
id: SingleDiskPlotId,
/// Space allocated during plot creation
old_space: ByteSize,
/// New desired plot size
new_space: ByteSize,
},
/// Wrong chain (genesis hash)
#[error(
"Genesis hash of plot {id} {wrong_chain} is different from {correct_chain} when plot was \
Expand Down Expand Up @@ -474,15 +463,7 @@ impl SingleDiskPlot {
let public_key = identity.public_key().to_bytes().into();

let single_disk_plot_info = match SingleDiskPlotInfo::load_from(&directory)? {
Some(single_disk_plot_info) => {
if allocated_space != single_disk_plot_info.allocated_space() {
return Err(SingleDiskPlotError::CantResize {
id: *single_disk_plot_info.id(),
old_space: ByteSize::b(single_disk_plot_info.allocated_space()),
new_space: ByteSize::b(allocated_space),
});
}

Some(mut single_disk_plot_info) => {
if &farmer_app_info.genesis_hash != single_disk_plot_info.genesis_hash() {
return Err(SingleDiskPlotError::WrongChain {
id: *single_disk_plot_info.id(),
Expand Down Expand Up @@ -518,6 +499,24 @@ impl SingleDiskPlot {
);
}

if allocated_space != single_disk_plot_info.allocated_space() {
info!(
old_space = %bytesize::to_string(single_disk_plot_info.allocated_space(), true),
new_space = %bytesize::to_string(allocated_space, true),
"Farm size has changed"
);

{
let new_allocated_space = allocated_space;
let SingleDiskPlotInfo::V0 {
allocated_space, ..
} = &mut single_disk_plot_info;
*allocated_space = new_allocated_space;
}

single_disk_plot_info.store_to(&directory)?;
}

single_disk_plot_info
}
None => {
Expand Down Expand Up @@ -596,24 +595,25 @@ impl SingleDiskPlot {
}
};

// TODO: Consider file locking to prevent other apps from modifying itS
// TODO: Consider file locking to prevent other apps from modifying it
let mut metadata_file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(directory.join(Self::METADATA_FILE))?;

let (metadata_header, metadata_header_mmap) = if metadata_file.seek(SeekFrom::End(0))? == 0
{
let metadata_size = metadata_file.seek(SeekFrom::End(0))?;
let expected_metadata_size =
RESERVED_PLOT_METADATA + sector_metadata_size as u64 * u64::from(target_sector_count);
let (metadata_header, metadata_header_mmap) = if metadata_size == 0 {
let metadata_header = PlotMetadataHeader {
version: 0,
sector_count: 0,
};

metadata_file.preallocate(
RESERVED_PLOT_METADATA
+ sector_metadata_size as u64 * u64::from(target_sector_count),
)?;
metadata_file
.preallocate(expected_metadata_size)
.map_err(SingleDiskPlotError::CantPreallocateMetadataFile)?;
metadata_file.write_all_at(metadata_header.encode().as_slice(), 0)?;

let metadata_header_mmap = unsafe {
Expand All @@ -624,21 +624,36 @@ impl SingleDiskPlot {

(metadata_header, metadata_header_mmap)
} else {
let metadata_header_mmap = unsafe {
if metadata_size != expected_metadata_size {
// Allocating the whole file (`set_len` below can create a sparse file, which will
// cause writes to fail later)
metadata_file
.preallocate(expected_metadata_size)
.map_err(SingleDiskPlotError::CantPreallocateMetadataFile)?;
// Truncating file (if necessary)
metadata_file.set_len(expected_metadata_size)?;
}
let mut metadata_header_mmap = unsafe {
MmapOptions::new()
.len(PlotMetadataHeader::encoded_size())
.map_mut(&metadata_file)?
};

let metadata_header = PlotMetadataHeader::decode(&mut metadata_header_mmap.as_ref())
.map_err(SingleDiskPlotError::FailedToDecodeMetadataHeader)?;
let mut metadata_header =
PlotMetadataHeader::decode(&mut metadata_header_mmap.as_ref())
.map_err(SingleDiskPlotError::FailedToDecodeMetadataHeader)?;

if metadata_header.version != Self::SUPPORTED_PLOT_VERSION {
return Err(SingleDiskPlotError::UnexpectedMetadataVersion(
metadata_header.version,
));
}

if metadata_header.sector_count > target_sector_count {
metadata_header.sector_count = target_sector_count;
metadata_header.encode_to(&mut metadata_header_mmap.as_mut());
}

(metadata_header, metadata_header_mmap)
};

Expand Down Expand Up @@ -674,9 +689,13 @@ impl SingleDiskPlot {
.open(directory.join(Self::PLOT_FILE))?,
);

// Allocating the whole file (`set_len` below can create a sparse file, which will cause
// writes to fail later)
plot_file
.preallocate(sector_size as u64 * u64::from(target_sector_count))
.map_err(SingleDiskPlotError::CantPreallocatePlotFile)?;
// Truncating file (if necessary)
plot_file.set_len(sector_size as u64 * u64::from(target_sector_count))?;

let piece_cache = DiskPieceCache::open(&directory, cache_capacity)?;

Expand Down
22 changes: 7 additions & 15 deletions crates/subspace-farmer/src/single_disk_plot/piece_cache.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use derive_more::Display;
use memmap2::{Mmap, MmapOptions};
use std::fs::{File, OpenOptions};
use std::io::{Seek, SeekFrom};
use std::path::Path;
use std::sync::Arc;
use std::{fs, io, mem};
Expand Down Expand Up @@ -62,26 +61,19 @@ impl DiskPieceCache {
return Err(DiskPieceCacheError::ZeroCapacity);
}

let mut file = OpenOptions::new()
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(directory.join(Self::PIECE_CACHE_FILE))?;

let current_file_size = file.seek(SeekFrom::End(0))?;
let expected_size = Self::element_size() * capacity;
if current_file_size == 0 {
// Empty file
file.preallocate(expected_size as u64)
.map_err(DiskPieceCacheError::CantPreallocateCacheFile)?;
} else if current_file_size == expected_size as u64 {
// Already correct size
} else {
panic!(
"Resizing not supported, single disk plot must have checked this before getting \
here"
);
}
// Allocating the whole file (`set_len` below can create a sparse file, which will cause
// writes to fail later)
file.preallocate(expected_size as u64)
.map_err(DiskPieceCacheError::CantPreallocateCacheFile)?;
// Truncating file (if necessary)
file.set_len(expected_size as u64)?;

let read_mmap = unsafe { MmapOptions::new().len(expected_size).map(&file)? };
#[cfg(unix)]
Expand Down
2 changes: 1 addition & 1 deletion crates/subspace-farmer/src/single_disk_plot/plotting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ where

if sector_index + 1 > metadata_header.sector_count {
metadata_header.sector_count = sector_index + 1;
metadata_header_mmap.copy_from_slice(metadata_header.encode().as_slice());
metadata_header.encode_to(&mut metadata_header_mmap.as_mut());
}
{
let mut sectors_metadata = sectors_metadata.write();
Expand Down

0 comments on commit 4f080d8

Please sign in to comment.