/* | |
* 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 |