563 lines
12 KiB
C
563 lines
12 KiB
C
|
|
/*
|
|||
|
|
----
|
|||
|
|
This file is part of SECONDO.
|
|||
|
|
|
|||
|
|
Copyright (C) 2004-2009, University in Hagen, Faculty of Mathematics
|
|||
|
|
and Computer Science, Database Systems for New Applications.
|
|||
|
|
|
|||
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|||
|
|
it under the terms of the GNU General Public License as published by
|
|||
|
|
the Free Software Foundation; either version 2 of the License, or
|
|||
|
|
(at your option) any later version.
|
|||
|
|
|
|||
|
|
SECONDO 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 General Public License for more details.
|
|||
|
|
|
|||
|
|
You should have received a copy of the GNU General Public License
|
|||
|
|
along with SECONDO; if not, write to the Free Software
|
|||
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
|
----
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#pragma once
|
|||
|
|
|
|||
|
|
#include "AttrArray.h"
|
|||
|
|
#include "Attribute.h"
|
|||
|
|
#include "LRUCache.h"
|
|||
|
|
#include "ReadWrite.h"
|
|||
|
|
#include "Algebras/Relation-C++/RelationAlgebra.h"
|
|||
|
|
#include "SecondoSMI.h"
|
|||
|
|
#include "Shared.h"
|
|||
|
|
#include "SmiUtils.h"
|
|||
|
|
#include <string>
|
|||
|
|
#include "TBlock.h"
|
|||
|
|
|
|||
|
|
namespace CRelAlgebra
|
|||
|
|
{
|
|||
|
|
class CRelIterator;
|
|||
|
|
class CRelBlockIterator;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Implements a column-oriented relation.
|
|||
|
|
|
|||
|
|
The main functionality provided is appending tuples, retrieving tuple-blocks
|
|||
|
|
and persisting / restoring the relation.
|
|||
|
|
|
|||
|
|
The whole relation (sequence of tuples) is split up into tuple-blocks.
|
|||
|
|
This hapens on insertion.
|
|||
|
|
Once a tuple-block excceeds a specified size (in bytes) a new tuple-block is
|
|||
|
|
appended.
|
|||
|
|
|
|||
|
|
This class uses ~TBlock~s as tuple-block representation which implements the
|
|||
|
|
column-oriented aspects can be further parameterized by a ~TBlockInfo~.
|
|||
|
|
|
|||
|
|
To potentialy improve random access of tuple-blocks a specified number of
|
|||
|
|
blocks is cached.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
class CRel
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
/*
|
|||
|
|
Creates a ~CRel~ using ~TBlock~s specified by ~blockInfo~, the
|
|||
|
|
~desiredBlockSize~ in bytes and ~cacheSize~ representing the number of
|
|||
|
|
blocks to cache.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRel(const PTBlockInfo &blockInfo, uint64_t desiredBlockSize,
|
|||
|
|
uint64_t cacheSize);
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Creates a ~CRel~ using ~TBlock~s specified by ~blockInfo~ and ~cacheSize~
|
|||
|
|
representing the number of blocks to cache.
|
|||
|
|
|
|||
|
|
The ~CRel~ is restored from the data provided by ~source~.
|
|||
|
|
|
|||
|
|
Precondition: the data held by ~source~ was created by a ~CRel~ with similar
|
|||
|
|
~blockInfo~
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRel(const PTBlockInfo &blockInfo, uint64_t cacheSize, Reader &source);
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Destroys this ~CRel~ instance.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
~CRel();
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns the ~TBlockInfo~ used by the ~TBlock~s in this relation.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
const PTBlockInfo &GetBlockInfo() const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Persists this relation into the provided ~target~.
|
|||
|
|
|
|||
|
|
This actually only saves metadata.
|
|||
|
|
The rest is stored in three files created by this relation.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
void Save(Writer &target);
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Removes all tupleblocks from this relation.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
void Clear();
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Deletes the files created by this relation.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
void DeleteFiles();
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns the number of columns of this ~CRel~.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
uint64_t GetColumnCount() const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns the number of tuples in this ~CRel~.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
uint64_t GetRowCount() const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns the number of tuple-blocks in this ~CRel~.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
uint64_t GetBlockCount() const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns the desired block size of this ~CRel~.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
uint64_t GetDesiredBlockSize() const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns the maximum number of tuple blocks cached by this ~CRel~.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
uint64_t GetCacheSize() const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Appends a tuple to this relation.
|
|||
|
|
|
|||
|
|
Preconditions:
|
|||
|
|
*~tuple~ must point to a array of ~AttrArrayEntry~
|
|||
|
|
*~tuple~ must contain ~GetColumnCount()~ entries
|
|||
|
|
*the attribute-array types of the entries must match the attribute-array
|
|||
|
|
types of this relation's columns
|
|||
|
|
*/
|
|||
|
|
void Append(const AttrArrayEntry* tuple);
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Appends a tuple to this relation.
|
|||
|
|
|
|||
|
|
This function does not touch the ~Attribute~'s reference counters.
|
|||
|
|
|
|||
|
|
Preconditions:
|
|||
|
|
*~tuple~ must point to a array of ~Attribute~ pointers
|
|||
|
|
*~tuple~ must contain ~GetColumnCount()~ entries
|
|||
|
|
*the attribute types of the entries must match the attribute types of this
|
|||
|
|
relation's columns
|
|||
|
|
*/
|
|||
|
|
void Append(Attribute** tuple);
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Appends a tuple to this relation.
|
|||
|
|
|
|||
|
|
Preconditions:
|
|||
|
|
*~tuple~ must represent a valid ~TBlockEntry~
|
|||
|
|
*~tuple~'s ~TBlock~ must have a similar ~TBlockInfo~ to this relation
|
|||
|
|
*/
|
|||
|
|
void Append(const TBlockEntry &tuple);
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Appends a tuple to this relation.
|
|||
|
|
|
|||
|
|
This function does not touch the ~Tuple~'s reference counter.
|
|||
|
|
|
|||
|
|
Preconditions:
|
|||
|
|
*~tuple~ must contain ~GetColumnCount()~ attributes
|
|||
|
|
*the attribute types of the tuple's attributes must match the attribute
|
|||
|
|
types of this relation's columns
|
|||
|
|
*/
|
|||
|
|
void Append(const Tuple &tuple);
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Accesses a tuple block by it's ~index~.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
TBlock &GetBlock(uint64_t index) const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns a ~CRelIterator~ over this relation's tuples.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRelIterator GetIterator() const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns a ~CRelBlockIterator~ over this relation's tuple blocks.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRelBlockIterator GetBlockIterator() const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
~CRelIterator~s used (only!) for range-loop support.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRelIterator begin() const;
|
|||
|
|
CRelIterator end() const;
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
/*
|
|||
|
|
Class representing a entry of the tuple-block cache.
|
|||
|
|
If a entry leaves the cache and was marked ~modified~ the ~block~ gets
|
|||
|
|
saved.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
class BlockCacheEntry
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
TBlock *block;
|
|||
|
|
|
|||
|
|
bool modified;
|
|||
|
|
|
|||
|
|
BlockCacheEntry();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Used to save and restore part of a ~TBlockHeader~'s data in one read / write
|
|||
|
|
operation.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
class BlockHeader
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
uint64_t rowCount,
|
|||
|
|
size;
|
|||
|
|
|
|||
|
|
BlockHeader();
|
|||
|
|
|
|||
|
|
BlockHeader(const TBlock &block);
|
|||
|
|
|
|||
|
|
TBlockHeader ToHeader(SmiFileId columnFileId, SmiFileId flobFileId);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Represents a block of ~TBlock~ metadata.
|
|||
|
|
Saving ~TBlock~ metadata in blocks saves read / write operations.
|
|||
|
|
We allways keep one ~BlockRecord~ in memory so ~sizeLimit~ should be chosen
|
|||
|
|
keeping that in mind.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
class BlockRecord
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
static const uint64_t sizeLimit = 1024 * 1024;
|
|||
|
|
|
|||
|
|
uint64_t index;
|
|||
|
|
|
|||
|
|
char *data;
|
|||
|
|
|
|||
|
|
bool modified;
|
|||
|
|
|
|||
|
|
BlockRecord();
|
|||
|
|
|
|||
|
|
BlockRecord(const BlockRecord &instance) = delete;
|
|||
|
|
|
|||
|
|
~BlockRecord();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
PTBlockInfo m_blockInfo;
|
|||
|
|
|
|||
|
|
const uint64_t m_desiredBlockSize;
|
|||
|
|
|
|||
|
|
uint64_t m_rowCount,
|
|||
|
|
m_blockCount,
|
|||
|
|
m_nextBlockIndex;
|
|||
|
|
|
|||
|
|
mutable uint64_t m_recordCount;
|
|||
|
|
|
|||
|
|
const uint64_t m_blockRecordEntrySize,
|
|||
|
|
m_blockRecordEntryCount,
|
|||
|
|
m_blockRecordSize;
|
|||
|
|
|
|||
|
|
mutable BlockRecord m_blockRecord;
|
|||
|
|
|
|||
|
|
SmiFileId m_blockFileId,
|
|||
|
|
m_columnFileId;
|
|||
|
|
|
|||
|
|
mutable SmiRecordFile m_blockFile;
|
|||
|
|
|
|||
|
|
Shared<SmiRecordFile> m_columnFile;
|
|||
|
|
|
|||
|
|
mutable LRUCache<BlockCacheEntry> m_blockCache;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Deleted copy-constructor to prevent pointer copies
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRel(const CRel&) = delete;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
This internal append function accepts all ~T~ which are valid in
|
|||
|
|
~TBlock.Append(T)~. This saves us some redundant code.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
template<class T>
|
|||
|
|
void TAppend(T tuple);
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Saves a ~TBlock~ with the provided ~index~.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
void SaveBlock(uint64_t index, TBlock &block) const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Restores a ~TBlock~ with the provided ~index~.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
TBlock *LoadBlock(uint64_t index) const;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Gets the ~BlockRecord~ containing the metadata for the requested
|
|||
|
|
~blockIndex~.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
BlockRecord &GetBlockRecord(uint64_t blockIndex) const;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
A iterator over a ~CRel~’s tuple-blocks.
|
|||
|
|
|
|||
|
|
Changes of the ~CRel~ invalidate the iterator which is not reflected by
|
|||
|
|
~CRelBlockIterator.IsValid~. Further usage is considered undefined behaviour.
|
|||
|
|
|
|||
|
|
The functions are defined in this header file to enable inlining.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
class CRelBlockIterator
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
/*
|
|||
|
|
Creates a invalid iterator.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRelBlockIterator() :
|
|||
|
|
m_relation(nullptr),
|
|||
|
|
m_block(nullptr),
|
|||
|
|
m_index(0)
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Creates a iterator pointing at the first block in the passed ~relation~.
|
|||
|
|
If the ~relation~ is empty the iterator is invalid.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRelBlockIterator(const CRel *relation) :
|
|||
|
|
m_relation(relation),
|
|||
|
|
m_block(relation->GetBlockCount() > 0 ? &relation->GetBlock(0) : nullptr),
|
|||
|
|
m_index(0)
|
|||
|
|
{
|
|||
|
|
if (m_block != nullptr)
|
|||
|
|
{
|
|||
|
|
m_block->IncRef();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
~CRelBlockIterator()
|
|||
|
|
{
|
|||
|
|
if (m_block != nullptr)
|
|||
|
|
{
|
|||
|
|
m_block->DecRef();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Determines if the iterator's current position is valid.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
bool IsValid()
|
|||
|
|
{
|
|||
|
|
return m_block != nullptr;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns the ~TBlock~ at the iterator's current position.
|
|||
|
|
|
|||
|
|
Precondition: ~IsValid()~
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
TBlock &Get()
|
|||
|
|
{
|
|||
|
|
return *m_block;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Moves the iterator to the next position.
|
|||
|
|
Returns true if that position is still valid.
|
|||
|
|
|
|||
|
|
Precondition: ~IsValid()~
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
bool MoveToNext()
|
|||
|
|
{
|
|||
|
|
if (m_block != nullptr)
|
|||
|
|
{
|
|||
|
|
m_block->DecRef();
|
|||
|
|
|
|||
|
|
if (++m_index < m_relation->GetBlockCount())
|
|||
|
|
{
|
|||
|
|
m_block = &m_relation->GetBlock(m_index);
|
|||
|
|
m_block->IncRef();
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_block = nullptr;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
const CRel *m_relation;
|
|||
|
|
|
|||
|
|
TBlock *m_block;
|
|||
|
|
|
|||
|
|
uint64_t m_index;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
A iterator over a ~CRel~’s tuples.
|
|||
|
|
|
|||
|
|
Changes of the ~CRel~ invalidate the iterator which is not reflected by
|
|||
|
|
~CRelIterator.IsValid~. Further usage is considered undefined behaviour.
|
|||
|
|
|
|||
|
|
The functions are defined in this header file to enable inlining.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
class CRelIterator
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
/*
|
|||
|
|
Creates a invalid iterator.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRelIterator()
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Creates a iterator pointing at the first tuple in the passed ~relation~.
|
|||
|
|
If the ~relation~ is empty the iterator is invalid.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
CRelIterator(const CRel *relation) :
|
|||
|
|
m_blockIterator(relation),
|
|||
|
|
m_tupleIterator(m_blockIterator.IsValid() ?
|
|||
|
|
TBlockIterator(&m_blockIterator.Get()) :
|
|||
|
|
TBlockIterator())
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Determines if the iterator's current position is valid.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
bool IsValid()
|
|||
|
|
{
|
|||
|
|
return m_tupleIterator.IsValid();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Returns a ~TBlockEntry~ representing the tuple at the iterator's current
|
|||
|
|
position.
|
|||
|
|
|
|||
|
|
Precondition: ~IsValid()~
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
const TBlockEntry &Get()
|
|||
|
|
{
|
|||
|
|
return m_tupleIterator.Get();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const TBlockEntry &operator * () const
|
|||
|
|
{
|
|||
|
|
return m_tupleIterator.Get();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Moves the iterator to the next position.
|
|||
|
|
~MoveToNext~ returns true if that position is still valid.
|
|||
|
|
|
|||
|
|
Precondition: ~IsValid()~
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
bool MoveToNext()
|
|||
|
|
{
|
|||
|
|
if (m_tupleIterator.IsValid())
|
|||
|
|
{
|
|||
|
|
if (!m_tupleIterator.MoveToNext())
|
|||
|
|
{
|
|||
|
|
do
|
|||
|
|
{
|
|||
|
|
if (!m_blockIterator.MoveToNext())
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
m_tupleIterator = m_blockIterator.Get().GetIterator();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
while (!m_tupleIterator.IsValid());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CRelIterator &operator ++ ()
|
|||
|
|
{
|
|||
|
|
MoveToNext();
|
|||
|
|
|
|||
|
|
return *this;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Compares this iterator and the ~other~ iterator for equality.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
bool operator == (const CRelIterator &other) const
|
|||
|
|
{
|
|||
|
|
return m_tupleIterator == other.m_tupleIterator;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
Compares this iterator and the ~other~ iterator for inequality.
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
bool operator != (const CRelIterator &other) const
|
|||
|
|
{
|
|||
|
|
return m_tupleIterator != other.m_tupleIterator;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
CRelBlockIterator m_blockIterator;
|
|||
|
|
|
|||
|
|
TBlockIterator m_tupleIterator;
|
|||
|
|
};
|
|||
|
|
}
|