diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2016-12-18 11:15:31 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2016-12-19 14:15:49 +0000 |
commit | 3a007a2d6476b73f58101724785f384cc2d9e64a (patch) | |
tree | 49a6b45a616bf4516589c00aa73ea826abd22bfd /storage | |
parent | 3d547ac70592fe56a6ddb37021c38bb3ed275733 (diff) |
GC unused code.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/src/tests/storageutil/recordflatfiletest.cpp | 314 | ||||
-rw-r--r-- | storage/src/vespa/storage/storageutil/recordflatfile.cpp | 155 | ||||
-rw-r--r-- | storage/src/vespa/storage/storageutil/recordflatfile.h | 339 |
3 files changed, 0 insertions, 808 deletions
diff --git a/storage/src/tests/storageutil/recordflatfiletest.cpp b/storage/src/tests/storageutil/recordflatfiletest.cpp deleted file mode 100644 index e08dd88dc67..00000000000 --- a/storage/src/tests/storageutil/recordflatfiletest.cpp +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/fastos/fastos.h> -#include <cppunit/extensions/HelperMacros.h> -#include <iostream> -#include <string> -#include <vespa/storage/storageutil/recordflatfile.h> - -using namespace document; -using namespace storage; -using namespace std; -using namespace document; - -class RecordFlatFile_Test : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(RecordFlatFile_Test); - CPPUNIT_TEST(testAdd); - CPPUNIT_TEST(testUpdate); - CPPUNIT_TEST(testRemove); - CPPUNIT_TEST(testExists); - CPPUNIT_TEST(testGetRecord); - CPPUNIT_TEST(testClear); - CPPUNIT_TEST(testSimpleUsage); - CPPUNIT_TEST(testValid); - CPPUNIT_TEST_SUITE_END(); - - string _testFile; - unsigned int _chunkSize; - - void setupTestFile(); - -public: - void setUp(); - - RecordFlatFile_Test(void) - : _testFile(), - _chunkSize(0) - { - } - -protected: - void testAdd(); - void testUpdate(); - void testRemove(); - void testExists(); - void testGetRecord(); - void testClear(); - void testSimpleUsage(); - void testValid(); -}; - -CPPUNIT_TEST_SUITE_REGISTRATION(RecordFlatFile_Test); - -namespace { - - const bool debug = false; - - class MyRecord { - private: - unsigned int _id; - unsigned int _value; - unsigned int _valid; - - public: - MyRecord(void) - : _id(0u), - _value(0u), - _valid(0u) - { - } - MyRecord(unsigned int id, unsigned int value, bool valid = true) - : _id(id), _value(value), _valid(valid ? 0 : 0xFFFFFFFF) {} - - const unsigned int& getId() const { return _id; } - unsigned int getValue() const { return _value; } - void setValue(unsigned int value) { _value = value; } - bool isValid() const { return (_valid == 0); } - - bool operator==(const MyRecord& record) const { - return (_id == record._id && _value == record._value); - } - }; - - ostream& operator<<(ostream& out, MyRecord record) { - out << "MyRecord(" << record.getId() << ", " << record.getValue() - << ")"; - return out; - } - - class BlockMessage { - private: - string _name; - static unsigned int _indent; - - public: - BlockMessage(const string& name) : _name(name) { - if (debug) { - for (unsigned int i=0; i<_indent; i++) cout << " "; - cout << "Block started: " << _name << "\n" << flush; - } - _indent++; - } - ~BlockMessage() { - _indent--; - if (debug) { - for (unsigned int i=0; i<_indent; i++) cout << " "; - cout << "Block completed: " << _name << "\n" << flush; - } - } - }; - - unsigned int BlockMessage::_indent(0); - -} - -void RecordFlatFile_Test::setUp() { - _testFile = "recordflatfile.testfile"; - _chunkSize = 4; -} - -void RecordFlatFile_Test::setupTestFile() { - BlockMessage message("setupTestFile()"); - RecordFlatFile<MyRecord, unsigned int> flatfile(_testFile, _chunkSize); - flatfile.clear(); - for (unsigned int i=1; i<=8; ++i) { - flatfile.add(MyRecord(i, 10+i)); - } - CPPUNIT_ASSERT_EQUAL(8u, flatfile.getSize()); - for (unsigned int i=1; i<=8; ++i) { - CPPUNIT_ASSERT_EQUAL(MyRecord(i, 10+i), *flatfile[i-1]); - } -} - - -void RecordFlatFile_Test::testAdd() { - BlockMessage message("testAdd()"); - setupTestFile(); - RecordFlatFile<MyRecord, unsigned int> flatfile(_testFile, _chunkSize); - flatfile.add(MyRecord(9, 19)); - CPPUNIT_ASSERT_EQUAL(9u, flatfile.getSize()); - CPPUNIT_ASSERT_EQUAL(MyRecord(1, 11), *flatfile[0]); - CPPUNIT_ASSERT_EQUAL(MyRecord(2, 12), *flatfile[1]); - CPPUNIT_ASSERT_EQUAL(MyRecord(7, 17), *flatfile[6]); - CPPUNIT_ASSERT_EQUAL(MyRecord(8, 18), *flatfile[7]); - CPPUNIT_ASSERT_EQUAL(MyRecord(9, 19), *flatfile[8]); -} - -void RecordFlatFile_Test::testUpdate() { - BlockMessage message("testUpdate()"); - setupTestFile(); - RecordFlatFile<MyRecord, unsigned int> flatfile(_testFile, _chunkSize); - CPPUNIT_ASSERT(!flatfile.update(MyRecord(0, 20))); - CPPUNIT_ASSERT(flatfile.update(MyRecord(4, 19))); - CPPUNIT_ASSERT_EQUAL(8u, flatfile.getSize()); - CPPUNIT_ASSERT_EQUAL(MyRecord(1, 11), *flatfile[0]); - CPPUNIT_ASSERT_EQUAL(MyRecord(3, 13), *flatfile[2]); - CPPUNIT_ASSERT_EQUAL(MyRecord(4, 19), *flatfile[3]); - CPPUNIT_ASSERT_EQUAL(MyRecord(5, 15), *flatfile[4]); - CPPUNIT_ASSERT_EQUAL(MyRecord(8, 18), *flatfile[7]); -} - -void RecordFlatFile_Test::testRemove() { - BlockMessage message("testRemove()"); - setupTestFile(); - RecordFlatFile<MyRecord, unsigned int> flatfile(_testFile, _chunkSize); - flatfile.remove(3); - CPPUNIT_ASSERT_EQUAL(7u, flatfile.getSize()); - CPPUNIT_ASSERT_EQUAL(MyRecord(1, 11), *flatfile[0]); - CPPUNIT_ASSERT_EQUAL(MyRecord(2, 12), *flatfile[1]); - CPPUNIT_ASSERT_EQUAL(MyRecord(8, 18), *flatfile[2]); - CPPUNIT_ASSERT_EQUAL(MyRecord(4, 14), *flatfile[3]); - CPPUNIT_ASSERT_EQUAL(MyRecord(5, 15), *flatfile[4]); - CPPUNIT_ASSERT_EQUAL(MyRecord(6, 16), *flatfile[5]); - CPPUNIT_ASSERT_EQUAL(MyRecord(7, 17), *flatfile[6]); -} - -void RecordFlatFile_Test::testExists() { - BlockMessage message("testExists()"); - setupTestFile(); - RecordFlatFile<MyRecord, unsigned int> flatfile(_testFile, _chunkSize); - CPPUNIT_ASSERT(flatfile.exists(3)); - CPPUNIT_ASSERT(flatfile.exists(1)); - CPPUNIT_ASSERT(!flatfile.exists(11)); - CPPUNIT_ASSERT(flatfile.exists(6)); - CPPUNIT_ASSERT(flatfile.exists(5)); - CPPUNIT_ASSERT(!flatfile.exists(0)); -} - -void RecordFlatFile_Test::testGetRecord() { - BlockMessage message("testGetRecord()"); - setupTestFile(); - RecordFlatFile<MyRecord, unsigned int> flatfile(_testFile, _chunkSize); - CPPUNIT_ASSERT_EQUAL(MyRecord(4, 14), *flatfile.getRecord(4)); - CPPUNIT_ASSERT(flatfile.getRecord(0).get() == 0); -} - -void RecordFlatFile_Test::testClear() { - try{ - BlockMessage message("testClear()"); - setupTestFile(); - RecordFlatFile<MyRecord, unsigned int> flatfile(_testFile, _chunkSize); - flatfile.clear(); - struct stat filestats; - CPPUNIT_ASSERT(stat(_testFile.c_str(), &filestats) == -1); - } catch (exception& e) { - cerr << "Caught exception '" << e.what() << "' in testClear()" << endl; - throw; - } -} - -void RecordFlatFile_Test::testSimpleUsage() -{ - BlockMessage message("testSimpleUsage()"); - RecordFlatFile<MyRecord, unsigned int> flatfile("recordflatfile.testfile"); - flatfile.clear(); - - CPPUNIT_ASSERT_EQUAL(false, flatfile.exists(34u)); - CPPUNIT_ASSERT_EQUAL((MyRecord*) 0, flatfile.getRecord(23u).get()); - - MyRecord record1(12, 54); - MyRecord record2(34, 62); - - flatfile.add(record1); - flatfile.add(record2); - - CPPUNIT_ASSERT_EQUAL(true, flatfile.exists(12u)); - CPPUNIT_ASSERT_EQUAL((MyRecord*) 0, flatfile.getRecord(23u).get()); - unique_ptr<MyRecord> result(flatfile.getRecord(34u)); - CPPUNIT_ASSERT(result.get() != 0); - CPPUNIT_ASSERT_EQUAL(62u, result->getValue()); - - record2.setValue(67); - flatfile.update(record2); - - unique_ptr<MyRecord> result2(flatfile.getRecord(34u)); - CPPUNIT_ASSERT(result2.get() != 0); - CPPUNIT_ASSERT_EQUAL(67u, result2->getValue()); - - flatfile.remove(12); - CPPUNIT_ASSERT_EQUAL(false, flatfile.exists(12u)); - - flatfile.clear(); - CPPUNIT_ASSERT_EQUAL(false, flatfile.exists(34u)); -} - -void RecordFlatFile_Test::testValid() -{ - BlockMessage message("testValid()"); - RecordFlatFile<MyRecord, unsigned int> flatfile("recordflatfile.testfile"); - flatfile.clear(); - - MyRecord record1(12, 54, true); - MyRecord record2(34, 62, false); - MyRecord record3(15, 69, true); - MyRecord record4(50, 93, false); - - // Test that valid entries doesn't generate errors - flatfile.add(record1); - CPPUNIT_ASSERT(!flatfile.errorsFound()); - CPPUNIT_ASSERT_EQUAL((size_t) 0, flatfile.getErrors().size()); - - // Test that invalid entries do - flatfile.add(record2); - CPPUNIT_ASSERT(flatfile.errorsFound()); - CPPUNIT_ASSERT_EQUAL((size_t) 1, flatfile.getErrors().size()); - string expected("Adding invalid record '34' to file " - "recordflatfile.testfile."); - CPPUNIT_ASSERT_EQUAL(expected, *flatfile.getErrors().begin()); - - // Checking that errors are kept if not cleared - flatfile.add(record3); - CPPUNIT_ASSERT_EQUAL((size_t) 1, flatfile.getErrors().size()); - CPPUNIT_ASSERT_EQUAL(expected, *flatfile.getErrors().begin()); - - // Checking that clearing errors work - flatfile.clearErrors(); - CPPUNIT_ASSERT_EQUAL((size_t) 0, flatfile.getErrors().size()); - - flatfile.add(record4); - flatfile.clearErrors(); - - // Checking that entries read in get method generates warning - unique_ptr<MyRecord> result(flatfile.getRecord(12)); - CPPUNIT_ASSERT_EQUAL((size_t) 0, flatfile.getErrors().size()); - result = flatfile.getRecord(15); - CPPUNIT_ASSERT_EQUAL((size_t) 1, flatfile.getErrors().size()); - expected = "Found corrupted entry in file recordflatfile.testfile"; - CPPUNIT_ASSERT_EQUAL(expected, *flatfile.getErrors().begin()); - flatfile.clearErrors(); - - // Checking that reading invalid entries generate exception - try{ - result = flatfile.getRecord(50); - CPPUNIT_FAIL("Expected exception"); - } catch (IoException& e) { - expected = "IoException(): Entry requested '50' is corrupted in file " - "recordflatfile.testfile at getRecord in"; - string actual(e.what()); - if (actual.size() > expected.size()) - actual = actual.substr(0, expected.size()); - CPPUNIT_ASSERT_EQUAL(expected, actual); - } - CPPUNIT_ASSERT_EQUAL((size_t) 1, flatfile.getErrors().size()); - expected = "Found corrupted entry in file recordflatfile.testfile"; - CPPUNIT_ASSERT_EQUAL(expected, *flatfile.getErrors().begin()); - flatfile.clearErrors(); - - // Check that you get warning when deleting if last entry is invalid - flatfile.remove(12); - CPPUNIT_ASSERT_EQUAL((size_t) 1, flatfile.getErrors().size()); - expected = "Last entry in file recordflatfile.testfile is invalid"; - CPPUNIT_ASSERT_EQUAL(expected, *flatfile.getErrors().begin()); - - flatfile.clear(); -} diff --git a/storage/src/vespa/storage/storageutil/recordflatfile.cpp b/storage/src/vespa/storage/storageutil/recordflatfile.cpp deleted file mode 100644 index 2951ae702e9..00000000000 --- a/storage/src/vespa/storage/storageutil/recordflatfile.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/fastos/fastos.h> -#include <vespa/storage/storageutil/recordflatfile.h> - -#include <sys/stat.h> -#include <sys/types.h> - -using document::IoException; -using namespace std; -using namespace storage; - -namespace { - - string getLastError(FastOS_File&) { - // Potential memory leak if string's operator new throws bad_alloc - // or other exception. - char *ptr = FastOS_File::GetLastErrorString(); - string error(ptr); - free(ptr); - return error; - } - -} - -ExceptionThrowingFile:: -ExceptionThrowingFile(const string& filename) - : _file(filename.c_str()) -{ -} - -void ExceptionThrowingFile::openReadOnly() -throw (IoException) -{ - if (!_file.OpenReadOnly()) { - throw IoException( - "FastOS_File.OpenReadOnly reported: "+getLastError(_file), - VESPA_STRLOC); - } -} - -void ExceptionThrowingFile::openWriteOnly() -throw (IoException) -{ - if (!_file.OpenWriteOnly()) { - throw IoException( - "FastOS_File.OpenWriteOnly reported: "+getLastError(_file), - VESPA_STRLOC); - } -} - -void ExceptionThrowingFile::openReadWrite() -throw (IoException) -{ - if (!_file.OpenReadWrite()) { - throw IoException( - "FastOS_File.OpenReadWrite reported: "+getLastError(_file), - VESPA_STRLOC); - } -} - -void ExceptionThrowingFile::read(void* buffer, unsigned int length) -throw (IoException) -{ - // Can't do arithmetics on void*, so casting first. - char* cbuffer = static_cast<char*>(buffer); - unsigned int totalRead = 0; - while (totalRead < length) { - unsigned int readSize = length - totalRead; - ssize_t count = _file.Read(cbuffer + totalRead, readSize); - if (count == -1) { - throw IoException( - "FastOS_File.Read reported: "+getLastError(_file), - VESPA_STRLOC); - } else if (count == 0) { - throw IoException("FastOS_File.Read returned 0", - VESPA_STRLOC); - } - totalRead += count; - } -} - -void ExceptionThrowingFile:: -write(const void* buffer, unsigned int length) -throw (IoException) -{ - if (!_file.CheckedWrite(buffer, length)) { - throw IoException( - "Call to FastOS_File.CheckedWrite() failed: "+getLastError(_file), - VESPA_STRLOC); - } -} - -void ExceptionThrowingFile::setPosition(int64_t position) -throw (IoException) -{ - if (!_file.SetPosition(position)) { - throw IoException( - "Call to FastOS_File.SetPosition() failed: "+getLastError(_file), - VESPA_STRLOC); - } -} - -int64_t ExceptionThrowingFile::getPosition() -throw (IoException) -{ - int64_t position = _file.GetPosition(); - if (position == -1) { - throw IoException( - "Call to FastOS_File.GetPosition() failed: "+getLastError(_file), - VESPA_STRLOC); - } - assert(position >= 0); - return position; -} - -int64_t ExceptionThrowingFile::getSize() -throw (IoException) -{ - int64_t size = _file.GetSize(); - if (size == -1) { - throw IoException( - "Call to FastOS_File.GetSize() failed: "+getLastError(_file), - VESPA_STRLOC); - } - assert(size >= 0); - return size; -} - -void ExceptionThrowingFile::setSize(int64_t size) -throw (IoException) -{ - if (!_file.SetSize(size)) { - throw IoException( - "Call to FastOS_File.SetSize() failed: "+getLastError(_file), - VESPA_STRLOC); - } -} - -void ExceptionThrowingFile::remove() -throw (IoException) -{ - if (!_file.Delete()) { - throw IoException( - "Call to FastOS_File.Remove() failed: "+getLastError(_file), - VESPA_STRLOC); - } -} - -bool ExceptionThrowingFile::exists() -throw (IoException) -{ - struct stat fileinfo; - return (stat(_file.GetFileName(), &fileinfo) == 0); -} diff --git a/storage/src/vespa/storage/storageutil/recordflatfile.h b/storage/src/vespa/storage/storageutil/recordflatfile.h deleted file mode 100644 index 801338bd697..00000000000 --- a/storage/src/vespa/storage/storageutil/recordflatfile.h +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * @class storage::RecordFlatFile - * @ingroup allocator - * - * @brief Templated class for keeping fixed sized records of primitives on disk. - * - * This file is used to keep a number of fixed sized records on disk, - * it provides an abstraction layer, such that one doesn't have to worry - * about the disk access. - * - * It implements the disk access using FastOS_File and opens the file - * in combined Read/Write mode if writing is necessary. - * - * New entries are appended without checking if they previous exist. - * Updating entries change them in place. Deleting entries, moves the - * last entry in the file into the position of the entry that is being - * deleted, and file is truncated to fit. - * - * The class is defined to be a template, to prevent the need for the - * extra resources consumed by using inheritance. - * - * A record implementation should look something like this: - * - * class Record { - * public: - * Record(const Record&); - * - * Id getId() const; - * Record& operator=(const Record&); - * bool isValid(); - * }; - * - * class Id { - * public: - * operator==(const Id&) const; - * }; - * - * ostream& operator<<(ostream& out, const Id&); - * - * NB: As records are written directly from memory to disk, and are - * reconstructed merely by copying disk content back into memory, they - * cannot include pointers or references as these types of variables would - * not be correctly saved and restored. It is thus safes to only use - * primitives. - * - * Note that this interface is not threadsafe. The class keeps a memory - * area for buffering, that is used during both read and write operations. - * Thus only one operation can be performed at a time. - * - * @author H�kon Humberset - * @date 2005-04-28 - * @version $Id$ - */ - -#pragma once - -#include <cassert> -#include <vespa/vespalib/util/exceptions.h> -#include <list> -#include <memory> -#include <stdexcept> -#include <sstream> -#include <string> - -namespace storage { - -/** - * Helper class to get a FastOS file that throws exceptions. - */ -class ExceptionThrowingFile { -private: - FastOS_File _file; - -public: - ExceptionThrowingFile(const std::string& filename); - - void openReadOnly() throw (vespalib::IoException); - void openWriteOnly() throw (vespalib::IoException); - void openReadWrite() throw (vespalib::IoException); - void read(void* _buffer, unsigned int length) throw (vespalib::IoException); - void write(const void* _buffer, unsigned int length) - throw (vespalib::IoException); - void setPosition(int64_t position) throw (vespalib::IoException); - int64_t getPosition() throw (vespalib::IoException); - void setSize(int64_t size) throw (vespalib::IoException); - int64_t getSize() throw (vespalib::IoException); - void remove() throw (vespalib::IoException); - bool exists() throw (vespalib::IoException); -}; - -template<class Record, class Id> -class RecordFlatFile { -private: - RecordFlatFile(const RecordFlatFile &); - RecordFlatFile& operator=(const RecordFlatFile &); - - Record *_record; // Cache of a chunk of records - const std::string _path; - const unsigned int _chunkSize; // In kilobytes - const unsigned int _maxChunkRecordCount; - mutable std::list<std::string> _nonFatalErrors; - -public: - RecordFlatFile(const std::string& path, unsigned int chunksize = 4096) - throw (vespalib::IllegalArgumentException, vespalib::FatalException, - vespalib::IoException); - ~RecordFlatFile(); - - bool exists(const Id& id) const throw (vespalib::IoException); - std::unique_ptr<Record> getRecord(const Id& id) const - throw (vespalib::IoException); - - bool update(const Record& record) throw (vespalib::IoException); - void add(const Record& record) throw (vespalib::IoException); - bool remove(const Id& id) throw (vespalib::IoException); - void clear() throw (vespalib::IoException); - - // Functions to get entries in the flatfile by index. Used by tests to - // ensure correct operation. - unsigned int getSize() const throw (vespalib::IoException); - std::unique_ptr<Record> operator[](unsigned int index) const - throw (document::IllegalArgumentException, vespalib::IoException); - - bool errorsFound() const { return (_nonFatalErrors.size() > 0); } - const std::list<std::string>& getErrors() const { return _nonFatalErrors; } - void clearErrors() { _nonFatalErrors.clear(); } -}; - -template<class Record, class Id> RecordFlatFile<Record, Id>:: -RecordFlatFile(const std::string& path,unsigned int chunksize) -throw (document::IllegalArgumentException, document::FatalException, - vespalib::IoException) - : _record(0), - _path(path), - _chunkSize(chunksize * sizeof(Record)), - _maxChunkRecordCount(chunksize), - _nonFatalErrors() -{ - if (_maxChunkRecordCount == 0) { - throw document::IllegalArgumentException( - "RecordFlatFile("+_path+"): Chunksize given doesn't allow for any " - "records. Increase chunksize to at least sizeof(Record)", VESPA_STRLOC); - } - _record = new Record[chunksize]; - if (!_record) { - throw document::FatalException( - "RecordFlatFile("+_path+"): Failed to allocate buffer", VESPA_STRLOC); - } - // Make sure file exists - ExceptionThrowingFile file(_path); - file.openReadWrite(); -} - -template<class Record, class Id> -RecordFlatFile<Record, Id>::~RecordFlatFile() -{ - delete[] _record; -} - -template<class Record, class Id> -bool RecordFlatFile<Record, Id>::exists(const Id& id) const -throw (vespalib::IoException) -{ - return (getRecord(id).get() != (Record*) 0); -} - -template<class Record, class Id> std::unique_ptr<Record> -RecordFlatFile<Record, Id>::getRecord(const Id& id) const -throw (vespalib::IoException) -{ - ExceptionThrowingFile file(_path); - if (file.exists()) { - file.openReadOnly(); - unsigned int recordCount = file.getSize() / sizeof(Record); - unsigned int currentRecord = 0; - while (currentRecord < recordCount) { - unsigned int chunkRecordCount = - std::min(_maxChunkRecordCount, recordCount - currentRecord); - file.read(_record, chunkRecordCount * sizeof(Record)); - for (unsigned int i=0; i<chunkRecordCount; ++i) { - if (_record[i].getId() == id) { - if (!_record[i].isValid()) { - std::ostringstream ost; - ost << "Entry requested '" << id << "' is corrupted " - << "in file " << _path; - throw vespalib::IoException(ost.str(), VESPA_STRLOC); - } - return std::unique_ptr<Record>(new Record(_record[i])); - } - if (!_record[i].isValid()) { - _nonFatalErrors.push_back( - "Found corrupted entry in file "+_path); - } - } - currentRecord += chunkRecordCount; - } - } - return std::unique_ptr<Record>(0); -} - -template<class Record, class Id> -bool RecordFlatFile<Record, Id>::update(const Record& record) -throw (vespalib::IoException) -{ - if (!record.isValid()) { - std::ostringstream ost; - ost << "Updating " << _path << " using invalid record '" - << record.getId() << "'."; - _nonFatalErrors.push_back(ost.str()); - } - ExceptionThrowingFile file(_path); - file.openReadWrite(); - unsigned int recordCount = file.getSize() / sizeof(Record); - unsigned int currentRecord = 0; - while (currentRecord < recordCount) { - unsigned int chunkRecordCount = - std::min(_maxChunkRecordCount, recordCount - currentRecord); - file.read(_record, chunkRecordCount * sizeof(Record)); - for (unsigned int i=0; i<chunkRecordCount; ++i) { - if (_record[i].getId() == record.getId()) { - _record[i] = record; - file.setPosition(file.getPosition() - - (chunkRecordCount - i) * sizeof(Record)); - file.write(&_record[i], sizeof(Record)); - return true; - } - } - currentRecord += chunkRecordCount; - } - return false; -} - -template<class Record, class Id> -void RecordFlatFile<Record, Id>::add(const Record& record) -throw (vespalib::IoException) -{ - if (!record.isValid()) { - std::ostringstream ost; - ost << "Adding invalid record '" - << record.getId() << "' to file " << _path << "."; - _nonFatalErrors.push_back(ost.str()); - } - ExceptionThrowingFile file(_path); - file.openWriteOnly(); - file.setPosition(file.getSize()); - file.write(&record, sizeof(Record)); -} - -template<class Record, class Id> -bool RecordFlatFile<Record, Id>::remove(const Id& id) -throw (vespalib::IoException) -{ - ExceptionThrowingFile file(_path); - file.openReadWrite(); - int64_t fileSize = file.getSize(); - if (fileSize == 0) return false; - Record last; - { // Read the last entry - file.setPosition(file.getSize() - sizeof(Record)); - file.read(&last, sizeof(Record)); - if (!last.isValid()) { - _nonFatalErrors.push_back( - "Last entry in file "+_path+" is invalid"); - } - if (last.getId() == id) { - file.setSize(file.getSize() - sizeof(Record)); - return true; - } - file.setPosition(0); - } - - unsigned int recordCount = file.getSize() / sizeof(Record); - unsigned int currentRecord = 0; - while (currentRecord < recordCount) { - unsigned int chunkRecordCount = - std::min(_maxChunkRecordCount, recordCount - currentRecord); - file.read(_record, chunkRecordCount * sizeof(Record)); - for (unsigned int i=0; i<chunkRecordCount; ++i) { - if (_record[i].getId() == id) { - _record[i] = last; - file.setPosition(file.getPosition() - - (chunkRecordCount - i) * sizeof(Record)); - file.write(&_record[i], sizeof(Record)); - file.setSize(file.getSize() - sizeof(Record)); - return true; - } - if (!_record[i].isValid()) { - _nonFatalErrors.push_back( - "Found corrupted entry in file "+_path); - } - } - currentRecord += chunkRecordCount; - } - return false; -} - -template<class Record, class Id> -void RecordFlatFile<Record, Id>::clear() -throw (vespalib::IoException) -{ - ExceptionThrowingFile file(_path); - file.remove(); -} - -template<class Record, class Id> -unsigned int RecordFlatFile<Record, Id>::getSize() const -throw (vespalib::IoException) -{ - ExceptionThrowingFile file(_path); - file.openReadOnly(); - int64_t fileSize = file.getSize(); - if (fileSize % sizeof(Record) != 0) { - _nonFatalErrors.push_back( - "Filesize is not a whole number of records. " - "File "+_path+" corrupted or wrong size gotten."); - } - return static_cast<unsigned int>(fileSize / sizeof(Record)); -} - -template<class Record, class Id> -std::unique_ptr<Record> RecordFlatFile<Record, Id>:: -operator[](unsigned int index) const -throw (document::IllegalArgumentException, vespalib::IoException) -{ - ExceptionThrowingFile file(_path); - file.openReadOnly(); - unsigned int recordCount = file.getSize() / sizeof(Record); - if (index >= recordCount) { - throw document::IllegalArgumentException( - "RecordFlatFile.operator[]: Access outside of bounds", VESPA_STRLOC); - } - file.setPosition(index * sizeof(Record)); - file.read(_record, sizeof(Record)); - return std::unique_ptr<Record>(new Record(_record[0])); -} - -} - |