blob: f62c4061acec9b170a882ad2f80138f6638cd631 [file] [log] [blame]
/*
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
*
* Distributable under the terms of either the Apache License (Version 2.0) or
* the GNU Lesser General Public License, as specified in the COPYING file.
*
* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
*/
#include "CLucene/StdHeader.h"
#include "SegmentInfos.h"
#include "CLucene/store/Directory.h"
#include "CLucene/util/Misc.h"
CL_NS_USE(store)
CL_NS_USE(util)
CL_NS_DEF(index)
SegmentInfo::SegmentInfo(const QString& Name, const int32_t DocCount,
CL_NS(store)::Directory* Dir)
: docCount(DocCount)
, dir(Dir)
{
//Func - Constructor. Initialises SegmentInfo.
//Pre - Name holds the unique name in the directory Dir
// DocCount holds the number of documents in the segment
// Dir holds the Directory where the segment resides
//Post - The instance has been created. name contains the duplicated string
// Name. docCount = DocCount and dir references Dir
name = Name;
}
SegmentInfo::~SegmentInfo()
{
}
SegmentInfos::SegmentInfos(bool _deleteMembers)
: deleteMembers(_deleteMembers)
{
//Func - Constructor
//Pre - deleteMembers indicates if the instance to be created must delete
// all SegmentInfo instances it manages when the instance is destroyed
// or not true -> must delete, false may not delete
//Post - An instance of SegmentInfos has been created.
//initialize counter to 0
counter = 0;
version = Misc::currentTimeMillis();
}
SegmentInfos::~SegmentInfos()
{
//Func - Destructor
//Pre - true
//Post - The instance has been destroyed. Depending on the constructor used
// the SegmentInfo instances that this instance managed have been
// deleted or not.
if (deleteMembers) {
segmentInfosType::iterator it;
for (it = infos.begin(); it != infos.end(); ++it)
_CLLDELETE(*it);
}
//Clear the list of SegmentInfo instances - make sure everything is deleted
infos.clear();
}
SegmentInfo* SegmentInfos::info(int32_t i) const
{
//Func - Returns a reference to the i-th SegmentInfo in the list.
//Pre - i >= 0
//Post - A reference to the i-th SegmentInfo instance has been returned
CND_PRECONDITION(i >= 0, "i contains negative number");
//Get the i-th SegmentInfo instance
SegmentInfo *ret = infos.value(i, 0);
//Condition check to see if the i-th SegmentInfo has been retrieved
CND_CONDITION(ret != NULL, "No SegmentInfo instance found");
return ret;
}
void SegmentInfos::clearto(size_t _min)
{
// Make sure we actually need to remove
if (infos.size() > _min) {
segmentInfosType::iterator itr;
segmentInfosType::iterator eitr = infos.end();
segmentInfosType::iterator bitr = infos.begin() + _min;
for(itr = bitr; itr != eitr; ++itr)
_CLLDELETE((*itr));
infos.erase(bitr, eitr);
}
}
void SegmentInfos::add(SegmentInfo* info)
{
infos.push_back(info);
}
int32_t SegmentInfos::size() const
{
return infos.size();
}
void SegmentInfos::read(Directory* directory)
{
//Func - Reads segments file that resides in directory.
//Pre - directory contains a valid reference
//Post - The segments file has been read and for each segment found
// a SegmentsInfo intance has been created and stored.
//Open an IndexInput to the segments file and check if valid
IndexInput* input = directory->openInput(QLatin1String("segments"));
if (input) {
try {
int32_t format = input->readInt();
// file contains explicit format info
if (format < 0) {
// check that it is a format we can understand
if (format < FORMAT) {
TCHAR err[30];
_sntprintf(err, 30, _T("Unknown format version: %d"), format);
_CLTHROWT(CL_ERR_Runtime, err);
}
// read version
version = input->readLong();
// read counter
counter = input->readInt();
} else {
// file is in old format without explicit format info
counter = format;
}
//Temporary variable for storing the name of the segment
char aname[CL_MAX_PATH] = { 0 };
TCHAR tname[CL_MAX_PATH] = { 0 };
//read segmentInfos
for (int32_t i = input->readInt(); i > 0; --i) {
// read the name of the segment
input->readString(tname, CL_MAX_PATH);
STRCPY_TtoA(aname, tname, CL_MAX_PATH);
//Instantiate a new SegmentInfo Instance
SegmentInfo* si = _CLNEW SegmentInfo(QLatin1String(aname),
input->readInt(), directory);
//Condition check to see if si points to an instance
CND_CONDITION(si != NULL, "Memory allocation for si failed") ;
//store SegmentInfo si
infos.push_back(si);
}
if (format >= 0) {
// in old format the version number may be at the end of the file
if (input->getFilePointer() >= input->length()) {
// old file format without version number
version = Misc::currentTimeMillis();
} else {
// read version
version = input->readLong();
}
}
} _CLFINALLY (
//destroy the inputStream input. The destructor of IndexInput will
//also close the Inputstream input
_CLDELETE(input);
);
}
}
void SegmentInfos::write(Directory* directory)
{
//Func - Writes a new segments file based upon the SegmentInfo instances it manages
//Pre - directory is a valid reference to a Directory
//Post - The new segment has been written to disk
//Open an IndexOutput to the segments file and check if valid
IndexOutput* output = directory->createOutput(QLatin1String("segments.new"));
if (output) {
try {
// write FORMAT
output->writeInt(FORMAT);
// every write changes the index
output->writeLong(++version);
// Write the counter
output->writeInt(counter);
// Write the number of SegmentInfo Instances which is equal to the number
// of segments in directory as each SegmentInfo manages a single segment
output->writeInt(infos.size());
//temporary value for wide segment name
TCHAR tname[CL_MAX_PATH];
//Iterate through all the SegmentInfo instances
for (uint32_t i = 0; i < infos.size(); ++i) {
//Retrieve the SegmentInfo
SegmentInfo *si = infos.value(i, 0);
//Condition check to see if si has been retrieved
CND_CONDITION(si != NULL, "No SegmentInfo instance found");
//Write the name of the current segment
int32_t count = si->name.toWCharArray(tname);
tname[count] = '\0';
output->writeString(tname, _tcslen(tname));
//Write the number of documents in the segment
output->writeInt(si->docCount);
}
} _CLFINALLY(
output->close();
_CLDELETE(output);
);
// install new segment info
directory->renameFile(QLatin1String("segments.new"),
QLatin1String("segments"));
}
}
int64_t SegmentInfos::readCurrentVersion(Directory* directory)
{
int32_t format = 0;
int64_t version = 0;
IndexInput* input = directory->openInput(QLatin1String("segments"));
try {
format = input->readInt();
if (format < 0){
if (format < FORMAT) {
TCHAR err[30];
_sntprintf(err, 30, _T("Unknown format version: %d"), format);
_CLTHROWT(CL_ERR_Runtime, err);
}
// read version
version = input->readLong();
}
} _CLFINALLY (
input->close();
_CLDELETE(input);
);
if (format < 0)
return version;
// We cannot be sure about the format of the file. Therefore we have to
// read the whole file and cannot simply seek to the version entry.
SegmentInfos segmentInfos;
segmentInfos.read(directory);
return segmentInfos.getVersion();
}
CL_NS_END