aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.cc.svn-base')
-rw-r--r--sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.cc.svn-base501
1 files changed, 501 insertions, 0 deletions
diff --git a/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.cc.svn-base b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.cc.svn-base
new file mode 100644
index 000000000..ecf1c9139
--- /dev/null
+++ b/sci-libs/libspatialindex/svn/trunk/src/storagemanager/.svn/text-base/DiskStorageManager.cc.svn-base
@@ -0,0 +1,501 @@
+// 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 <fstream>
+#include <cstring>
+
+// For checking if a file exists - hobu
+#include <sys/stat.h>
+
+#include "../spatialindex/SpatialIndexImpl.h"
+#include "DiskStorageManager.h"
+
+using namespace SpatialIndex;
+using namespace SpatialIndex::StorageManager;
+
+bool CheckFilesExists(Tools::PropertySet& ps)
+{
+ bool bExists = false;
+
+ std::string filename("");
+ std::string idx("idx");
+ std::string dat("dat");
+
+ Tools::Variant idx_name;
+ Tools::Variant dat_name;
+ Tools::Variant fn;
+
+ idx_name = ps.getProperty("FileNameIdx");
+ dat_name = ps.getProperty("FileNameDat");
+ fn = ps.getProperty("FileName");
+
+ if (idx_name.m_varType != Tools::VT_EMPTY) dat = std::string(idx_name.m_val.pcVal);
+ if (dat_name.m_varType != Tools::VT_EMPTY) idx = std::string(dat_name.m_val.pcVal);
+ if (fn.m_varType != Tools::VT_EMPTY) filename = std::string(fn.m_val.pcVal);
+
+ struct stat stats;
+
+ std::ostringstream os;
+ int ret;
+ os << filename <<"."<<dat;
+ std::string data_name = os.str();
+ ret = stat(data_name.c_str(), &stats);
+
+ if (ret == 0) bExists = true;
+
+ os.str("");
+ os << filename <<"."<<idx;
+ std::string index_name = os.str();
+ ret = stat(index_name.c_str(), &stats);
+
+ if ((ret == 0) && (bExists == true)) bExists = true;
+
+ return bExists;
+}
+SpatialIndex::IStorageManager* SpatialIndex::StorageManager::returnDiskStorageManager(Tools::PropertySet& ps)
+{
+ IStorageManager* sm = new DiskStorageManager(ps);
+ return sm;
+}
+
+SpatialIndex::IStorageManager* SpatialIndex::StorageManager::createNewDiskStorageManager(std::string& baseName, uint32_t 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("SpatialIndex::DiskStorageManager: 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("SpatialIndex::DiskStorageManager: Property FileName must be Tools::VT_PCHAR");
+
+ std::string idx("idx");
+ std::string dat("dat");
+
+ Tools::Variant idx_name = ps.getProperty("FileNameIdx");
+ if (idx_name.m_varType != Tools::VT_EMPTY) idx = std::string(idx_name.m_val.pcVal);
+
+ Tools::Variant dat_name = ps.getProperty("FileNameDat");
+ if (dat_name.m_varType != Tools::VT_EMPTY) dat = std::string(dat_name.m_val.pcVal);
+
+ std::string sIndexFile = std::string(var.m_val.pcVal) + "." + idx;
+ std::string sDataFile = std::string(var.m_val.pcVal) + "." + dat;
+
+ // check if file exists.
+ bool bFileExists = CheckFilesExists(ps);
+
+ // check if file can be read/written.
+ if (bFileExists == true && bOverwrite == false)
+ {
+ m_indexFile.open(sIndexFile.c_str(), std::ios::in | std::ios::out | std::ios::binary);
+ m_dataFile.open(sDataFile.c_str(), std::ios::in | std::ios::out | std::ios::binary);
+
+ if (m_indexFile.fail() || m_dataFile.fail())
+ throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Index/Data file cannot be read/writen.");
+ }
+ else
+ {
+ m_indexFile.open(sIndexFile.c_str(), std::ios::in | std::ios::out | std::ios::binary | std::ios::trunc);
+ m_dataFile.open(sDataFile.c_str(), std::ios::in | std::ios::out | std::ios::binary | std::ios::trunc);
+
+ if (m_indexFile.fail() || m_dataFile.fail())
+ throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: Index/Data file cannot be created.");
+
+ }
+ }
+ else
+ {
+ throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: 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("SpatialIndex::DiskStorageManager: Property PageSize must be Tools::VT_ULONG");
+ m_pageSize = var.m_val.ulVal;
+ m_nextPage = 0;
+ }
+ else
+ {
+ throw Tools::IllegalArgumentException("SpatialIndex::DiskStorageManager: A new storage manager is created and property PageSize was not specified.");
+ }
+ }
+ else
+ {
+ m_indexFile.read(reinterpret_cast<char*>(&m_pageSize), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Failed reading pageSize.");
+
+ m_indexFile.read(reinterpret_cast<char*>(&m_nextPage), sizeof(id_type));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Failed reading nextPage.");
+ }
+
+ // create buffer.
+ m_buffer = new byte[m_pageSize];
+ bzero(m_buffer, m_pageSize);
+
+ if (bOverwrite == false)
+ {
+ uint32_t count;
+ id_type page, id;
+
+ // load empty pages in memory.
+ m_indexFile.read(reinterpret_cast<char*>(&count), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ for (uint32_t cCount = 0; cCount < count; ++cCount)
+ {
+ m_indexFile.read(reinterpret_cast<char*>(&page), sizeof(id_type));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+ m_emptyPages.push(page);
+ }
+
+ // load index table in memory.
+ m_indexFile.read(reinterpret_cast<char*>(&count), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ for (uint32_t cCount = 0; cCount < count; ++cCount)
+ {
+ Entry* e = new Entry();
+
+ m_indexFile.read(reinterpret_cast<char*>(&id), sizeof(id_type));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ m_indexFile.read(reinterpret_cast<char*>(&(e->m_length)), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ uint32_t count2;
+ m_indexFile.read(reinterpret_cast<char*>(&count2), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ for (uint32_t cCount2 = 0; cCount2 < count2; ++cCount2)
+ {
+ m_indexFile.read(reinterpret_cast<char*>(&page), sizeof(id_type));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+ e->m_pages.push_back(page);
+ }
+ m_pageIndex.insert(std::pair<id_type, Entry* >(id, e));
+ }
+ }
+}
+
+DiskStorageManager::~DiskStorageManager()
+{
+ flush();
+ m_indexFile.close();
+ m_dataFile.close();
+ if (m_buffer != 0) delete[] m_buffer;
+
+ std::map<id_type, Entry*>::iterator it;
+ for (it = m_pageIndex.begin(); it != m_pageIndex.end(); ++it) delete (*it).second;
+}
+
+void DiskStorageManager::flush()
+{
+ m_indexFile.seekp(0, std::ios_base::beg);
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ m_indexFile.write(reinterpret_cast<const char*>(&m_pageSize), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ m_indexFile.write(reinterpret_cast<const char*>(&m_nextPage), sizeof(id_type));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ uint32_t count = static_cast<uint32_t>(m_emptyPages.size());
+ id_type page, id;
+
+ m_indexFile.write(reinterpret_cast<const char*>(&count), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ while (! m_emptyPages.empty())
+ {
+ page = m_emptyPages.top(); m_emptyPages.pop();
+ m_indexFile.write(reinterpret_cast<const char*>(&page), sizeof(id_type));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+ }
+
+ count = static_cast<uint32_t>(m_pageIndex.size());
+
+ m_indexFile.write(reinterpret_cast<const char*>(&count), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ std::map<id_type, Entry*>::iterator it;
+
+ for (it = m_pageIndex.begin(); it != m_pageIndex.end(); ++it)
+ {
+ id = (*it).first;
+ m_indexFile.write(reinterpret_cast<const char*>(&id), sizeof(id_type));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ uint32_t length = (*it).second->m_length;
+ m_indexFile.write(reinterpret_cast<const char*>(&length), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ count = static_cast<uint32_t>((*it).second->m_pages.size());
+ m_indexFile.write(reinterpret_cast<const char*>(&count), sizeof(uint32_t));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+
+ for (uint32_t cIndex = 0; cIndex < count; ++cIndex)
+ {
+ page = (*it).second->m_pages[cIndex];
+ m_indexFile.write(reinterpret_cast<const char*>(&page), sizeof(id_type));
+ if (m_indexFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted storage manager index file.");
+ }
+ }
+
+ m_indexFile.flush();
+ m_dataFile.flush();
+}
+
+void DiskStorageManager::loadByteArray(const id_type page, uint32_t& len, byte** data)
+{
+ std::map<id_type, Entry*>::iterator it = m_pageIndex.find(page);
+
+ if (it == m_pageIndex.end())
+ throw InvalidPageException(page);
+
+ std::vector<id_type>& pages = (*it).second->m_pages;
+ uint32_t cNext = 0;
+ uint32_t cTotal = static_cast<uint32_t>(pages.size());
+
+ len = (*it).second->m_length;
+ *data = new byte[len];
+
+ byte* ptr = *data;
+ uint32_t cLen;
+ uint32_t cRem = len;
+
+ do
+ {
+ m_dataFile.seekg(pages[cNext] * m_pageSize, std::ios_base::beg);
+ if (m_dataFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file.");
+
+ m_dataFile.read(reinterpret_cast<char*>(m_buffer), m_pageSize);
+ if (m_dataFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: 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(id_type& page, const uint32_t len, const byte* const data)
+{
+ if (page == NewPage)
+ {
+ Entry* e = new Entry();
+ e->m_length = len;
+
+ const byte* ptr = data;
+ id_type cPage;
+ uint32_t cRem = len;
+ uint32_t 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);
+
+ m_dataFile.seekp(cPage * m_pageSize, std::ios_base::beg);
+ if (m_dataFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file.");
+
+ m_dataFile.write(reinterpret_cast<const char*>(m_buffer), m_pageSize);
+ if (m_dataFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file.");
+
+ ptr += cLen;
+ cRem -= cLen;
+ e->m_pages.push_back(cPage);
+ }
+
+ page = e->m_pages[0];
+ m_pageIndex.insert(std::pair<id_type, Entry*>(page, e));
+ }
+ else
+ {
+ // find the entry.
+ std::map<id_type, Entry*>::iterator it = m_pageIndex.find(page);
+
+ // check if it exists.
+ if (it == m_pageIndex.end())
+ throw InvalidPageException(page);
+
+ Entry* oldEntry = (*it).second;
+
+ m_pageIndex.erase(it);
+
+ Entry* e = new Entry();
+ e->m_length = len;
+
+ const byte* ptr = data;
+ id_type cPage;
+ uint32_t cRem = len;
+ uint32_t 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);
+
+ m_dataFile.seekp(cPage * m_pageSize, std::ios_base::beg);
+ if (m_dataFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: Corrupted data file.");
+
+ m_dataFile.write(reinterpret_cast<const char*>(m_buffer), m_pageSize);
+ if (m_dataFile.fail())
+ throw Tools::IllegalStateException("SpatialIndex::DiskStorageManager: 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<id_type, Entry*>(page, e));
+ delete oldEntry;
+ }
+}
+
+void DiskStorageManager::deleteByteArray(const id_type page)
+{
+ std::map<id_type, Entry*>::iterator it = m_pageIndex.find(page);
+
+ if (it == m_pageIndex.end())
+ throw InvalidPageException(page);
+
+ for (uint32_t cIndex = 0; cIndex < (*it).second->m_pages.size(); ++cIndex)
+ {
+ m_emptyPages.push((*it).second->m_pages[cIndex]);
+ }
+
+ delete (*it).second;
+ m_pageIndex.erase(it);
+}