pub fn on_block_insert<Tx: StorageTransaction<Block, T>>(
		&self,
		tx: &mut Tx,
		parent: ComplexBlockId<Block>,
		block: ComplexBlockId<Block>,
		value: Option<T>,
		is_final: bool,
	) -> ClientResult<Option<CommitOperation<Block, T>>> {
		// this guarantee is currently provided by LightStorage && we're relying on it here
		debug_assert!(!is_final || self.best_finalized_block.hash == parent.hash);

		// we do not store any values behind finalized
		if block.number != Zero::zero() && self.best_finalized_block.number >= block.number {
			return Ok(None);
		}

		// if the block is not final, it is possibly appended to/forking from existing unfinalized fork
		if !is_final {
			let mut fork_and_action = None;

			// first: try to find fork that is known to has the best block we're appending to
			for (index, fork) in self.unfinalized.iter().enumerate() {
				if fork.try_append(&parent) {
					fork_and_action = Some((index, ForkAppendResult::Append));
					break;
				}
			}

			// if not found, check cases:
			// - we're appending to the fork for the first time after restart;
			// - we're forking existing unfinalized fork from the middle;
			if fork_and_action.is_none() {
				let best_finalized_entry_block = self.best_finalized_entry.as_ref().map(|f| f.valid_from.number);
				for (index, fork) in self.unfinalized.iter().enumerate() {
					if let Some(action) = fork.try_append_or_fork(&self.storage, &parent, best_finalized_entry_block)? {
						fork_and_action = Some((index, action));
						break;
					}
				}
			}

			// if we have found matching unfinalized fork => early exit
			match fork_and_action {
				// append to unfinalized fork
				Some((index, ForkAppendResult::Append)) => {
					let new_storage_entry = match self.unfinalized[index].head.try_update(value) {
						Some(new_storage_entry) => new_storage_entry,
						None => return Ok(Some(CommitOperation::AppendNewBlock(index, block))),
					};

					tx.insert_storage_entry(&block, &new_storage_entry);
					let operation = CommitOperation::AppendNewEntry(index, new_storage_entry.into_entry(block));
					tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation);
					return Ok(Some(operation));
				},
				// fork from the middle of unfinalized fork
				Some((_, ForkAppendResult::Fork(prev_valid_from))) => {
					// it is possible that we're inserting extra (but still required) fork here
					let new_storage_entry = StorageEntry {
						prev_valid_from: Some(prev_valid_from),
						value,
					};

					tx.insert_storage_entry(&block, &new_storage_entry);
					let operation = CommitOperation::AddNewFork(new_storage_entry.into_entry(block));
					tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation);
					return Ok(Some(operation));
				},
				None => (),
			}
		}

		// if we're here, then one of following is true:
		// - either we're inserting final block => all ancestors are already finalized AND the only thing we can do
		//   is to try to update last finalized entry
		// - either we're inserting non-final blocks that has no ancestors in any known unfinalized forks

		let new_storage_entry = match self.best_finalized_entry.as_ref() {
			Some(best_finalized_entry) => best_finalized_entry.try_update(value),
			None if value.is_some() => Some(StorageEntry { prev_valid_from: None, value }),
			None => None,
		};

		if !is_final {
			return Ok(match new_storage_entry {
				Some(new_storage_entry) => {
					tx.insert_storage_entry(&block, &new_storage_entry);
					let operation = CommitOperation::AddNewFork(new_storage_entry.into_entry(block));
					tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation);
					Some(operation)
				},
				None => None,
			});
		}

		// cleanup database from abandoned unfinalized forks and obsolete finalized entries
		let abandoned_forks = self.destroy_abandoned_forks(tx, &block);
		self.prune_finalized_entries(tx, &block);

		match new_storage_entry {
			Some(new_storage_entry) => {
				tx.insert_storage_entry(&block, &new_storage_entry);
				let operation = CommitOperation::BlockFinalized(block.clone(), Some(new_storage_entry.into_entry(block)), abandoned_forks);
				tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation);
				Ok(Some(operation))
			},
			None => Ok(Some(CommitOperation::BlockFinalized(block, None, abandoned_forks))),
		}
	}
/// When new block is inserted into database.
When new block is inserted into database.
When new block is inserted into database .
pub fn on_block_insert<Tx: StorageTransaction<Block, T>>(
		&self,
		tx: &mut Tx,
		parent: ComplexBlockId<Block>,
		block: ComplexBlockId<Block>,
		value: Option<T>,
		is_final: bool,
	) -> ClientResult<Option<CommitOperation<Block, T>>> {
		// this guarantee is currently provided by LightStorage && we're relying on it here
		debug_assert!(!is_final || self.best_finalized_block.hash == parent.hash);
		// we do not store any values behind finalized
		if block.number != Zero::zero() && self.best_finalized_block.number >= block.number {
			return Ok(None);
		}
		// if the block is not final, it is possibly appended to/forking from existing unfinalized fork
		if !is_final {
			let mut fork_and_action = None;
			// first: try to find fork that is known to has the best block we're appending to
			for (index, fork) in self.unfinalized.iter().enumerate() {
				if fork.try_append(&parent) {
					fork_and_action = Some((index, ForkAppendResult::Append));
					break;
				}
			}
			// if not found, check cases:
			// - we're appending to the fork for the first time after restart;
			// - we're forking existing unfinalized fork from the middle;
			if fork_and_action.is_none() {
				let best_finalized_entry_block = self.best_finalized_entry.as_ref().map(|f| f.valid_from.number);
				for (index, fork) in self.unfinalized.iter().enumerate() {
					if let Some(action) = fork.try_append_or_fork(&self.storage, &parent, best_finalized_entry_block)? {
						fork_and_action = Some((index, action));
						break;
					}
				}
			}
			// if we have found matching unfinalized fork => early exit
			match fork_and_action {
				// append to unfinalized fork
				Some((index, ForkAppendResult::Append)) => {
					let new_storage_entry = match self.unfinalized[index].head.try_update(value) {
						Some(new_storage_entry) => new_storage_entry,
						None => return Ok(Some(CommitOperation::AppendNewBlock(index, block))),
					};
					tx.insert_storage_entry(&block, &new_storage_entry);
					let operation = CommitOperation::AppendNewEntry(index, new_storage_entry.into_entry(block));
					tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation);
					return Ok(Some(operation));
				},
				// fork from the middle of unfinalized fork
				Some((_, ForkAppendResult::Fork(prev_valid_from))) => {
					// it is possible that we're inserting extra (but still required) fork here
					let new_storage_entry = StorageEntry {
						prev_valid_from: Some(prev_valid_from),
						value,
					};
					tx.insert_storage_entry(&block, &new_storage_entry);
					let operation = CommitOperation::AddNewFork(new_storage_entry.into_entry(block));
					tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation);
					return Ok(Some(operation));
				},
				None => (),
			}
		}
		// if we're here, then one of following is true:
		// - either we're inserting final block => all ancestors are already finalized AND the only thing we can do
		//   is to try to update last finalized entry
		// - either we're inserting non-final blocks that has no ancestors in any known unfinalized forks
		let new_storage_entry = match self.best_finalized_entry.as_ref() {
			Some(best_finalized_entry) => best_finalized_entry.try_update(value),
			None if value.is_some() => Some(StorageEntry { prev_valid_from: None, value }),
			None => None,
		};
		if !is_final {
			return Ok(match new_storage_entry {
				Some(new_storage_entry) => {
					tx.insert_storage_entry(&block, &new_storage_entry);
					let operation = CommitOperation::AddNewFork(new_storage_entry.into_entry(block));
					tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation);
					Some(operation)
				},
				None => None,
			});
		}
		// cleanup database from abandoned unfinalized forks and obsolete finalized entries
		let abandoned_forks = self.destroy_abandoned_forks(tx, &block);
		self.prune_finalized_entries(tx, &block);
		match new_storage_entry {
			Some(new_storage_entry) => {
				tx.insert_storage_entry(&block, &new_storage_entry);
				let operation = CommitOperation::BlockFinalized(block.clone(), Some(new_storage_entry.into_entry(block)), abandoned_forks);
				tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation);
				Ok(Some(operation))
			},
			None => Ok(Some(CommitOperation::BlockFinalized(block, None, abandoned_forks))),
		}
	}
pub fn on_block_insert < Tx : StorageTransaction < Block , T > > ( & self , tx : & mut Tx , parent : ComplexBlockId < Block > , block : ComplexBlockId < Block > , value : Option < T > , is_final : bool , ) -> ClientResult < Option < CommitOperation < Block , T > > > { // this guarantee is currently provided by LightStorage && we're relying on it here debug_assert ! ( is_final self best_finalized_block hash parent hash ) ; // we do not store any values behind finalized if block . number != Zero :: zero ( ) && self . best_finalized_block . number >= block . number { return Ok ( None ) ; } // if the block is not final, it is possibly appended to/forking from existing unfinalized fork if ! is_final { let mut fork_and_action = None ; // first: try to find fork that is known to has the best block we're appending to for ( index , fork ) in self . unfinalized . iter ( ) . enumerate ( ) { if fork . try_append ( & parent ) { fork_and_action = Some ( ( index , ForkAppendResult :: Append ) ) ; break ; } } // if not found, check cases: // - we're appending to the fork for the first time after restart; // - we're forking existing unfinalized fork from the middle; if fork_and_action . is_none ( ) { let best_finalized_entry_block = self . best_finalized_entry . as_ref ( ) . map ( | f | f . valid_from . number ) ; for ( index , fork ) in self . unfinalized . iter ( ) . enumerate ( ) { if let Some ( action ) = fork . try_append_or_fork ( & self . storage , & parent , best_finalized_entry_block ) ? { fork_and_action = Some ( ( index , action ) ) ; break ; } } } // if we have found matching unfinalized fork => early exit match fork_and_action { // append to unfinalized fork Some ( ( index , ForkAppendResult :: Append ) ) => { let new_storage_entry = match self . unfinalized [ index ] . head . try_update ( value ) { Some ( new_storage_entry ) => new_storage_entry , None => return Ok ( Some ( CommitOperation :: AppendNewBlock ( index , block ) ) ) , } ; tx . insert_storage_entry ( & block , & new_storage_entry ) ; let operation = CommitOperation :: AppendNewEntry ( index , new_storage_entry . into_entry ( block ) ) ; tx . update_meta ( self . best_finalized_entry . as_ref ( ) , & self . unfinalized , & operation ) ; return Ok ( Some ( operation ) ) ; } , // fork from the middle of unfinalized fork Some ( ( _ , ForkAppendResult :: Fork ( prev_valid_from ) ) ) => { // it is possible that we're inserting extra (but still required) fork here let new_storage_entry = StorageEntry { prev_valid_from : Some ( prev_valid_from ) , value , } ; tx . insert_storage_entry ( & block , & new_storage_entry ) ; let operation = CommitOperation :: AddNewFork ( new_storage_entry . into_entry ( block ) ) ; tx . update_meta ( self . best_finalized_entry . as_ref ( ) , & self . unfinalized , & operation ) ; return Ok ( Some ( operation ) ) ; } , None => ( ) , } } // if we're here, then one of following is true: // - either we're inserting final block => all ancestors are already finalized AND the only thing we can do //   is to try to update last finalized entry // - either we're inserting non-final blocks that has no ancestors in any known unfinalized forks let new_storage_entry = match self . best_finalized_entry . as_ref ( ) { Some ( best_finalized_entry ) => best_finalized_entry . try_update ( value ) , None if value . is_some ( ) => Some ( StorageEntry { prev_valid_from : None , value } ) , None => None , } ; if ! is_final { return Ok ( match new_storage_entry { Some ( new_storage_entry ) => { tx . insert_storage_entry ( & block , & new_storage_entry ) ; let operation = CommitOperation :: AddNewFork ( new_storage_entry . into_entry ( block ) ) ; tx . update_meta ( self . best_finalized_entry . as_ref ( ) , & self . unfinalized , & operation ) ; Some ( operation ) } , None => None , } ) ; } // cleanup database from abandoned unfinalized forks and obsolete finalized entries let abandoned_forks = self . destroy_abandoned_forks ( tx , & block ) ; self . prune_finalized_entries ( tx , & block ) ; match new_storage_entry { Some ( new_storage_entry ) => { tx . insert_storage_entry ( & block , & new_storage_entry ) ; let operation = CommitOperation :: BlockFinalized ( block . clone ( ) , Some ( new_storage_entry . into_entry ( block ) ) , abandoned_forks ) ; tx . update_meta ( self . best_finalized_entry . as_ref ( ) , & self . unfinalized , & operation ) ; Ok ( Some ( operation ) ) } , None => Ok ( Some ( CommitOperation :: BlockFinalized ( block , None , abandoned_forks ) ) ) , } }
When new block is inserted into database.
When new block is inserted into database .
&self
tx
&mut Tx
parent
ComplexBlockId<Block>
block
ComplexBlockId<Block>
value
Option<T>
is_final
bool
&self
tx
&mut Tx
parent
ComplexBlockId<Block>
block
ComplexBlockId<Block>
value
Option<T>
is_final
bool