⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 streambtreecontroller.h

📁 b tree code for index in the database design
💻 H
📖 第 1 页 / 共 2 页
字号:

	if ( node->less_ )
	{
		NodeType *less;
		if ( !loadNode( &less, node->less_ ) ) return false;
		freeChunks_.erase( node->less_ );
		readAllOffsets( less );
		if ( less ) releaseNode( less->addr_ );

		// Iterate other children if we have a less one
		for ( int i = 0; i < node->count(); i++ )
		{
			NodeType *kid = 0;

			if ( node->elems_[ i ].link_ )
			{
				if ( !loadNode( &kid, node->elems_[ i ].link_ ) ) return false;
			}
			freeChunks_.erase( node->elems_[ i ].link_ );

			if ( kid )
			{
				readAllOffsets( kid );
				releaseNode( kid->addr_ );
			}
		}
	}

	return true;
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::deleteNode

template< int NodeSize, typename KeyT, typename DataT >
void StreamBTreeController< NodeSize, KeyT, DataT >::deleteNode( NodeType* node )
{
	typename ChunkCacheMap::iterator iter = cache_.find( node->addr_ );

	if ( iter != cache_.end() )
	{
		cache_.erase( iter );
	}

	freeChunks_.insert( node->addr_ );
	delete node;
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::loadNode

template< int NodeSize, typename KeyT, typename DataT >
bool StreamBTreeController< NodeSize, KeyT, DataT >::loadNode( 
			NodeType **node, int addr )
{
	if ( !addr )
	{
		*node = 0;
		return true;
	}

	typename ChunkCacheMap::iterator iter = cache_.find( addr );

	if ( iter == cache_.end() )
	{
		*node = new NodeType();
		storage_->seek( addr );
		storage_->read( ( char* ) *node, sizeof( NodeType ) );

		if ( addr == ( *node )->addr_ )
		{
			CacheData cacheData( *node );
			cache_[ addr ] = cacheData;
		}
	}
	else
	{
		*node = iter->node;
	}

	if ( ( *node )->addr_ != addr )
	{
		// Storage is corrupted!
		return false;
	}

	return true;
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::saveNode

template< int NodeSize, typename KeyT, typename DataT >
void StreamBTreeController< NodeSize, KeyT, DataT >::saveNode( NodeType *node )
{
	node->flags_ = 0;
	storage_->seek( node->addr_ );
	storage_->write( ( const char* ) node, sizeof( NodeType ) );
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::flushChanges

template< int NodeSize, typename KeyT, typename DataT >
void StreamBTreeController< NodeSize, KeyT, DataT >::flushChanges()
{
	if ( !storage_ ) return;

	// Journaling
	if ( journal_ )
	{
		JBufferedOutputStream< JStream > journal( journal_ );
		if ( journal.size() > 0 )
		{
			journal.resize( 0 );
		}

		bool firstTime = true;
		guint complete = 0;

		typename ChunkCacheMap::iterator iter = cache_.begin();
		for ( ; iter != cache_.end(); iter++ )
		{
			NodeType *node = iter->node;

			if ( NodeType::NodeChanged == node->flags_ )
			{
				if ( firstTime )
				{
					// Write completion label
					journal.seek( 0 );
					journal.write( ( char* ) &complete, sizeof( complete ) );
					journal.write( ( char* ) &rootAddr_, sizeof( rootAddr_ ) );
					firstTime = false;
				}

				node->flags_ = 0;
				journal.write( ( const char* ) node, sizeof( NodeType ) );
				node->flags_ = NodeType::NodeChanged;
			}
		}

		if ( !firstTime )
		{
			// Complete it
			journal.seekRaw( 0 );
			complete = ~0;
			journal.write( ( char* ) &complete, sizeof( complete ) );
			journal.flush();
		}
		journal.setSource( 0 );
	}

	// Actual saving
	typename ChunkCacheMap::iterator iter = cache_.begin();
	for ( ; iter != cache_.end(); iter++ )
	{
		if ( NodeType::NodeChanged == iter->node->flags_ )
		{
			// Save node
			saveNode( iter->node );
		}
	}

	// Write root
	if ( rootAddr_ )
	{
		storage_->seek( sizeof( int ) );
		storage_->write( ( char* ) &rootAddr_, sizeof( rootAddr_ ) );
		rootAddr_ = 0;
	}

	// Clear journal
	if ( journal_ ) journal_->resize( 0 );
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::releaseCache

template< int NodeSize, typename KeyT, typename DataT >
void StreamBTreeController< NodeSize, KeyT, DataT >::releaseCache()
{
	if ( cacheSize() > maxCacheSize_ )
	{
		clearCache();
		return;
	}
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::clearCache

template< int NodeSize, typename KeyT, typename DataT >
void StreamBTreeController< NodeSize, KeyT, DataT >::clearCache()
{
	flushChanges();

	typename ChunkCacheMap::iterator iter = cache_.begin();
	for ( ; iter != cache_.end(); iter++ )
	{
		if ( iter->node != root_ )
		{
			delete iter->node;
		}
	}

	cache_.clear();
	if ( root_ )
	{
		cache_[ root_->addr_ ] = CacheData( root_ );
	}
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::releaseNode

template< int NodeSize, typename KeyT, typename DataT >
void StreamBTreeController< NodeSize, KeyT, DataT >::releaseNode( int addr )
{
	typename ChunkCacheMap::iterator iter = cache_.find( addr );

	if ( cache_.end() != iter )
	{
		if ( NodeType::NodeChanged == iter->node->flags_ )
		{
			flushChanges();
			releaseNode( addr );
			return;
		}

		if ( iter->node != root_ )
		{
			delete iter->node;
			cache_.erase( iter );
		}
	}
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::rootAddr

template< int NodeSize, typename KeyT, typename DataT >
int StreamBTreeController< NodeSize, KeyT, DataT >::rootAddr()
{
	int addr = 0;
	storage_->seek( sizeof( int ) );
	storage_->read( ( char* ) &addr, sizeof( addr ) );
	return addr;
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::closeController

template< int NodeSize, typename KeyT, typename DataT >
void StreamBTreeController< NodeSize, KeyT, DataT >::closeController()
{
	cache_.clear();

	if ( storage_ )
	{
		if ( !freeChunks_.empty() )
		{
			// Save removed nodes list
			guint rlistAddr = storage_->size();
			QByteArray rblock;
			FreeChunksSet::const_iterator iter = freeChunks_.begin();
			guint aaddr = 0;
			for ( ; iter != freeChunks_.end(); iter++ )
			{
				aaddr = *iter;
				rblock.resize( rblock.size() + sizeof( aaddr ) );
				::memcpy( rblock.data() + rblock.size() - sizeof( aaddr ), 
					( char* ) &aaddr, sizeof( aaddr ) );
			}
			freeChunks_.clear();

			storage_->seek( rlistAddr );
			storage_->write( rblock.data(), rblock.size() );

			storage_->seek( constRemovedAddr );
			storage_->write( ( char* ) &rlistAddr, sizeof( rlistAddr ) );
		}

		storage_->close();
		storage_ = 0;

		if ( journal_ )
		{
			journal_->close();
			journal_ = 0;
		}
	}
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::rootAddr

template< int NodeSize, typename KeyT, typename DataT >
void StreamBTreeController< NodeSize, KeyT, DataT >::rootAddr( int addr )
{
	rootAddr_ = addr;
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::rootAddr

template< int NodeSize, typename KeyT, typename DataT >
guint StreamBTreeController< NodeSize, KeyT, DataT >::cacheSize() const
{
	return sizeof( NodeType )*cache_.size();
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::setMaxCacheSize

template< int NodeSize, typename KeyT, typename DataT >
void StreamBTreeController< NodeSize, KeyT, DataT >::setMaxCacheSize( guint maxSize )
{
	maxCacheSize_ = maxSize;
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::getMaxCacheSize

template< int NodeSize, typename KeyT, typename DataT >
guint StreamBTreeController< NodeSize, KeyT, DataT >::getMaxCacheSize()
{
	return maxCacheSize_;
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::getMaxCacheSize

template< int NodeSize, typename KeyT, typename DataT >
bool StreamBTreeController< NodeSize, KeyT, DataT >::nodeInCache( int addr )
{
	return cache_.end() != cache_.find( addr );
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::getMaxCacheSize

template< int NodeSize, typename KeyT, typename DataT >
JStream* StreamBTreeController< NodeSize, KeyT, DataT >::storage()
{
	return storage_;
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::clear

template< int NodeSize, typename KeyT, typename DataT >
bool StreamBTreeController< NodeSize, KeyT, DataT >::clear()
{
	// Clear cache
	typename ChunkCacheMap::iterator iter = cache_.begin();
	for ( ; iter != cache_.end(); iter++ )
	{
		delete iter->node;
	}

	cache_.clear();
	freeChunks_.clear();
	root_  = 0;

	JStream *treeStorage = storage_;
	storage_->resize( 0 );
	storage_ = 0;

	return open( treeStorage, maxCacheSize_ );
}

//	===================================================================
//	StreamBTreeController< NodeSize, KeyT, DataT >::root

template< int NodeSize, typename KeyT, typename DataT >
typename StreamBTreeController< NodeSize, KeyT, DataT >::NodeType* 
		StreamBTreeController< NodeSize, KeyT, DataT >::root()
{
	return root_;
}

#endif // __StreamBTreeController_h__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -