aboutsummaryrefslogtreecommitdiffstats
path: root/storage
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2016-12-18 11:15:31 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2016-12-19 14:15:49 +0000
commit3a007a2d6476b73f58101724785f384cc2d9e64a (patch)
tree49a6b45a616bf4516589c00aa73ea826abd22bfd /storage
parent3d547ac70592fe56a6ddb37021c38bb3ed275733 (diff)
GC unused code.
Diffstat (limited to 'storage')
-rw-r--r--storage/src/tests/storageutil/recordflatfiletest.cpp314
-rw-r--r--storage/src/vespa/storage/storageutil/recordflatfile.cpp155
-rw-r--r--storage/src/vespa/storage/storageutil/recordflatfile.h339
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]));
-}
-
-}
-