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

📄 diskstoragemanager.cc

📁 一个非常好的GIS开源新版本
💻 CC
字号:
// Spatial Index Library//// Copyright (C) 2002 Navel Ltd.//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA////  Email://    mhadji@gmail.com#include "../spatialindex/SpatialIndexImpl.h"#include <unistd.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <cstring>#ifdef WIN32#include <io.h>#ifdef _MSC_VER#include <basetsd.h>#endif//_MSC_VER#define fsync(fd) _commit(fd)#endif#include "DiskStorageManager.h"using namespace SpatialIndex;using namespace SpatialIndex::StorageManager;using std::map;using std::vector;#ifdef _MSC_VERtypedef SSIZE_T ssize_t;#endif//_MSC_VERSpatialIndex::IStorageManager* SpatialIndex::StorageManager::returnDiskStorageManager(Tools::PropertySet& ps){	IStorageManager* sm = new DiskStorageManager(ps);	return sm;}SpatialIndex::IStorageManager* SpatialIndex::StorageManager::createNewDiskStorageManager(std::string& baseName, unsigned long pageSize){	Tools::Variant var;	Tools::PropertySet ps;	var.m_varType = Tools::VT_BOOL;	var.m_val.blVal = true;	ps.setProperty("Overwrite", var);		// overwrite the file if it exists.	var.m_varType = Tools::VT_PCHAR;	var.m_val.pcVal = const_cast<char*>(baseName.c_str());	ps.setProperty("FileName", var);		// .idx and .dat extensions will be added.	var.m_varType = Tools::VT_ULONG;	var.m_val.ulVal = pageSize;	ps.setProperty("PageSize", var);		// specify the page size. Since the index may also contain user defined data		// there is no way to know how big a single node may become. The storage manager		// will use multiple pages per node if needed. Off course this will slow down performance.	return returnDiskStorageManager(ps);}SpatialIndex::IStorageManager* SpatialIndex::StorageManager::loadDiskStorageManager(std::string& baseName){	Tools::Variant var;	Tools::PropertySet ps;	var.m_varType = Tools::VT_PCHAR;	var.m_val.pcVal = const_cast<char*>(baseName.c_str());	ps.setProperty("FileName", var);		// .idx and .dat extensions will be added.	return returnDiskStorageManager(ps);}DiskStorageManager::DiskStorageManager(Tools::PropertySet& ps) : m_pageSize(0), m_nextPage(-1), m_buffer(0){	Tools::Variant var;	// Open/Create flag.	bool bOverwrite = false;	var = ps.getProperty("Overwrite");	if (var.m_varType != Tools::VT_EMPTY)	{		if (var.m_varType != Tools::VT_BOOL) throw Tools::IllegalArgumentException("Property Overwrite must be Tools::VT_BOOL");		bOverwrite = var.m_val.blVal;	}	// storage filename.	var = ps.getProperty("FileName");	if (var.m_varType != Tools::VT_EMPTY)	{		if (var.m_varType != Tools::VT_PCHAR) throw Tools::IllegalArgumentException("Property FileName must be Tools::VT_PCHAR");		int cLen = strlen(var.m_val.pcVal);		char* pIndexFile = new char[cLen + 10];		char* pDataFile = new char[cLen + 10];		sprintf(pIndexFile, "%s.idx", var.m_val.pcVal);		sprintf(pDataFile, "%s.dat", var.m_val.pcVal);		// check if file exists.		bool bFileExists = true;		int e1 = access(pIndexFile, F_OK);		int e2 = access(pDataFile, F_OK);		if (e1 != 0 || e2 != 0) bFileExists = false;		if (! bFileExists) bOverwrite = true;		// check if file can be read/written.		if (bOverwrite == false)		{			int e1 = access(pIndexFile, R_OK | W_OK);			int e2 = access(pDataFile, R_OK | W_OK);			if ((e1 != 0 || e2 != 0) && bFileExists)			{				delete[] pIndexFile;				delete[] pDataFile;				throw Tools::IllegalArgumentException("Index file cannot be read/writen.");			}		}		int cMode = (bOverwrite) ? O_CREAT | O_RDWR | O_TRUNC : O_RDWR;		m_indexFile = open(pIndexFile, cMode, 0644);		if (m_indexFile < 0)		{			delete[] pIndexFile;			delete[] pDataFile;			throw Tools::IllegalArgumentException("Index file cannot be opened.");		}		m_dataFile = open(pDataFile, cMode, 0644);		if (m_dataFile < 0)		{			delete[] pIndexFile;			delete[] pDataFile;			throw Tools::IllegalArgumentException("Data file cannot be opened.");		}		delete[] pIndexFile;		delete[] pDataFile;	}	else	{		throw Tools::IllegalArgumentException("Property FileName was not specified.");	}	// find page size.	if (bOverwrite == true)	{		var = ps.getProperty("PageSize");		if (var.m_varType != Tools::VT_EMPTY)		{			if (var.m_varType != Tools::VT_ULONG) throw Tools::IllegalArgumentException("Property PageSize must be Tools::VT_ULONG");			m_pageSize = var.m_val.ulVal;			m_nextPage = 0;		}		else		{			throw Tools::IllegalArgumentException("A new storage manager is created and property PageSize was not specified.");		}	}	else	{		ssize_t bytesread = read(m_indexFile, &m_pageSize, sizeof(unsigned long));		if (bytesread != sizeof(unsigned long)) throw Tools::IllegalStateException("Failed reading pageSize.");		bytesread = read(m_indexFile, &m_nextPage, sizeof(long));		if (bytesread != sizeof(long)) throw Tools::IllegalStateException("Failed reading nextPage.");	}	// create buffer.	m_buffer = new byte[m_pageSize];	memset(m_buffer, 0, m_pageSize);	if (bOverwrite == false)	{		unsigned long count;		long id, page;		ssize_t bytesread;		// load empty pages in memory.		bytesread = read(m_indexFile, &count, sizeof(unsigned long));		if (bytesread != sizeof(unsigned long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");		for (unsigned long cCount = 0; cCount < count; cCount++)		{			bytesread = read(m_indexFile, &page, sizeof(long));			if (bytesread != sizeof(long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");			m_emptyPages.push(page);		}		// load index table in memory.		bytesread = read(m_indexFile, &count, sizeof(unsigned long));		if (bytesread != sizeof(unsigned long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");		for (unsigned long cCount = 0; cCount < count; cCount++)		{			Entry* e = new Entry();			bytesread = read(m_indexFile, &id, sizeof(long));			if (bytesread != sizeof(long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");			bytesread = read(m_indexFile, &(e->m_length), sizeof(unsigned long));			if (bytesread != sizeof(unsigned long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");			unsigned long count2;			bytesread = read(m_indexFile, &count2, sizeof(unsigned long));			if (bytesread != sizeof(unsigned long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");			for (unsigned long cCount2 = 0; cCount2 < count2; cCount2++)			{				bytesread = read(m_indexFile, &page, sizeof(long));				if (bytesread != sizeof(long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");				e->m_pages.push_back(page);			}			m_pageIndex.insert(std::pair<long, Entry* >(id, e));		}	}}DiskStorageManager::~DiskStorageManager(){	flush();	close(m_indexFile);	close(m_dataFile);	if (m_buffer != 0) delete[] m_buffer;	map<long, Entry*>::iterator it = m_pageIndex.begin();	while (it != m_pageIndex.end())	{		delete (*it).second;		it++;	}}void DiskStorageManager::flush(){	ssize_t byteswritten;	off_t seek = lseek(m_indexFile, 0, SEEK_SET);	if (seek < 0) throw Tools::IllegalStateException("Corrupted storage manager index file.");	byteswritten = write(m_indexFile, &m_pageSize, sizeof(unsigned long));	if (byteswritten != sizeof(unsigned long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");	byteswritten = write(m_indexFile, &m_nextPage, sizeof(long));	if (byteswritten != sizeof(long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");	unsigned long count = m_emptyPages.size();	long id, page;	byteswritten = write(m_indexFile, &count, sizeof(unsigned long));	if (byteswritten != sizeof(unsigned long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");	while (! m_emptyPages.empty())	{		page = m_emptyPages.top(); m_emptyPages.pop();		byteswritten = write(m_indexFile, &page, sizeof(long));		if (byteswritten != sizeof(long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");	}	count = m_pageIndex.size();	byteswritten = write(m_indexFile, &count, sizeof(unsigned long));	if (byteswritten != sizeof(unsigned long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");	map<long, Entry*>::iterator it = m_pageIndex.begin();	while (it != m_pageIndex.end())	{		id = (*it).first;		byteswritten = write(m_indexFile, &id, sizeof(long));		if (byteswritten != sizeof(long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");		count = (*it).second->m_length;		byteswritten = write(m_indexFile, &count, sizeof(long));		if (byteswritten != sizeof(long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");		count = (*it).second->m_pages.size();		byteswritten = write(m_indexFile, &count, sizeof(long));		if (byteswritten != sizeof(long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");		for (unsigned long cIndex = 0; cIndex < count; cIndex++)		{			page = (*it).second->m_pages[cIndex];			byteswritten = write(m_indexFile, &page, sizeof(long));			if (byteswritten != sizeof(long)) throw Tools::IllegalStateException("Corrupted storage manager index file.");		}		it++;	}	fsync(m_indexFile);	fsync(m_dataFile);}void DiskStorageManager::loadByteArray(const long id, unsigned long& len, byte** data){	map<long, Entry*>::iterator it = m_pageIndex.find(id);	if (it == m_pageIndex.end()) throw Tools::InvalidPageException(id);	vector<long>& pages = (*it).second->m_pages;	unsigned long cNext = 0;	unsigned long cTotal = pages.size();	len = (*it).second->m_length;	*data = new byte[len];	byte* ptr = *data;	unsigned long cLen;	unsigned long cRem = len;	do	{		off_t seek = lseek(m_dataFile, pages[cNext] * m_pageSize, SEEK_SET);		if (seek < 0) throw Tools::IllegalStateException("Corrupted data file.");		ssize_t bytesread = read(m_dataFile, m_buffer, m_pageSize);		if (bytesread <= 0) throw Tools::IllegalStateException("Corrupted data file.");		cLen = (cRem > m_pageSize) ? m_pageSize : cRem;		memcpy(ptr, m_buffer, cLen);		ptr += cLen;		cRem -= cLen;		cNext++;	}	while (cNext < cTotal);}void DiskStorageManager::storeByteArray(long& id, const unsigned long len, const byte* const data){	if (id == NewPage)	{		Entry* e = new Entry();		e->m_length = len;		const byte* ptr = data;		long cPage;		unsigned long cRem = len;		unsigned long cLen;		while (cRem > 0)		{			if (! m_emptyPages.empty())			{				cPage = m_emptyPages.top(); m_emptyPages.pop();			}			else			{				cPage = m_nextPage;				m_nextPage++;			}			cLen = (cRem > m_pageSize) ? m_pageSize : cRem;			memcpy(m_buffer, ptr, cLen);			off_t seek = lseek(m_dataFile, cPage * m_pageSize, SEEK_SET);			if (seek < 0) throw Tools::IllegalStateException("Corrupted data file.");			ssize_t byteswritten = write(m_dataFile, m_buffer, m_pageSize);			if (byteswritten <= 0) throw Tools::IllegalStateException("Corrupted data file.");			ptr += cLen;			cRem -= cLen;			e->m_pages.push_back(cPage);		}		id = e->m_pages[0];		m_pageIndex.insert(std::pair<long, Entry*>(id, e));	}	else	{		// find the entry.		map<long, Entry*>::iterator it = m_pageIndex.find(id);		// check if it exists.		if (it == m_pageIndex.end()) throw Tools::IndexOutOfBoundsException(id);		Entry* oldEntry = (*it).second;		m_pageIndex.erase(it);		Entry* e = new Entry();		e->m_length = len;		const byte* ptr = data;		long cPage;		unsigned long cRem = len;		unsigned long cLen, cNext = 0;		while (cRem > 0)		{			if (cNext < oldEntry->m_pages.size())			{				cPage = oldEntry->m_pages[cNext];				cNext++;			}			else if (! m_emptyPages.empty())			{				cPage = m_emptyPages.top(); m_emptyPages.pop();			}			else			{				cPage = m_nextPage;				m_nextPage++;			}			cLen = (cRem > m_pageSize) ? m_pageSize : cRem;			memcpy(m_buffer, ptr, cLen);			off_t seek = lseek(m_dataFile, cPage * m_pageSize, SEEK_SET);			if (seek < 0) throw Tools::IllegalStateException("Corrupted data file.");			ssize_t byteswritten = write(m_dataFile, m_buffer, m_pageSize);			if (byteswritten <= 0) throw Tools::IllegalStateException("Corrupted data file.");			ptr += cLen;			cRem -= cLen;			e->m_pages.push_back(cPage);		}		while (cNext < oldEntry->m_pages.size())		{			m_emptyPages.push(oldEntry->m_pages[cNext]);			cNext++;		}		m_pageIndex.insert(std::pair<long, Entry*>(id, e));		delete oldEntry;	}}void DiskStorageManager::deleteByteArray(const long id){	map<long, Entry*>::iterator it = m_pageIndex.find(id);	if (it == m_pageIndex.end()) throw Tools::InvalidPageException(id);	for (unsigned long cIndex = 0; cIndex < (*it).second->m_pages.size(); cIndex++)	{		m_emptyPages.push((*it).second->m_pages[cIndex]);	}	delete (*it).second;	m_pageIndex.erase(it);}

⌨️ 快捷键说明

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