NT4/private/windows/win4help/ftsrch/globals.cpp
2020-09-30 17:12:29 +02:00

842 lines
21 KiB
C++

// Globals.cpp -- Implementation for class CGlobals
#include "stdafx.h"
#include "Globals.h"
#include "Memex.h"
#include "Except.h"
#include "Hilite.h"
CGlobals *CGlobals::NewIndexGlobals(const PBYTE pbSourceName, UINT cbSourceName, FILETIME *pft,
UINT iCharsetDefault, UINT lcidDefault, UINT fdwOptions
)
{
CGlobals *pGlobals = NULL;
__try
{
pGlobals= New CGlobals(Indexer);
pGlobals->AttachIndexParams(pbSourceName, cbSourceName, pft,
iCharsetDefault, lcidDefault, fdwOptions
);
}
__except(FilterFTExceptions(_exception_code()))
{
if (pGlobals)
{
delete pGlobals; pGlobals= NULL;
}
EnableMemoryRequests(); // In case we failed for lack of virtual memory
EnableDiskRequests (); // or lack of disk space
}
return pGlobals;
}
void CGlobals::AttachIndexParams(const PBYTE pbSourceName, UINT cbSourceName, FILETIME *pft,
UINT iCharsetDefault, UINT lcidDefault, UINT fdwOptions
)
{
m_idProcess = ::GetCurrentProcessId();
Link();
AttachRef(m_ptsIndex, CTextSet::NewTextSet(pbSourceName, cbSourceName, pft,
iCharsetDefault, lcidDefault, fdwOptions
)
);
m_papts = &m_ptsIndex;
m_cts = 1;
}
ERRORCODE CGlobals::ScanTopicTitle(PBYTE pbTitle, UINT cbTitle,
UINT iTopic, HANDLE hTopic, UINT iCharset, UINT lcid
)
{
ASSERT(m_iType == Indexer);
UINT uExceptionType = 0;
ERRORCODE ec = 0;
__try
{
if (!cbTitle)
{
char ac[255];
char acstr[255];
::LoadString(hinstDLL, IDS_UNTITLED_TEMPLATE, acstr, 255);
wsprintf(ac, acstr, iTopic);
pbTitle= PBYTE(ac);
cbTitle= strlen(ac);
}
ec= m_papts[0]->ScanTopicTitle(pbTitle, cbTitle, iTopic, hTopic, iCharset, lcid);
if (!ec) ++m_cTitles;
}
__except(FilterFTExceptions(uExceptionType= _exception_code()))
{
ec= ErrorCodeForExceptions(uExceptionType);
}
return ec;
}
ERRORCODE CGlobals::ScanTopicText(PBYTE pbText, UINT cbText, UINT iCharset, UINT lcid)
{
ASSERT(m_iType == Indexer);
UINT uExceptionType = 0;
ERRORCODE ec = 0;
__try
{
ERRORCODE ec= m_papts[0]->ScanTopicText(pbText, cbText, iCharset, lcid);
}
__except(FilterFTExceptions(uExceptionType= _exception_code()))
{
ec= ErrorCodeForExceptions(uExceptionType);
}
return ec;
}
ERRORCODE CGlobals::SaveIndex(PSZ pszFileName)
{
ASSERT(m_iType == Indexer);
if (!m_cTitles) return NO_TITLE;
UINT uExceptionType = 0;
ERRORCODE ec = 0;
__try
{
__try
{
if (!pszFileName)
{
pszFileName= (PSZ) _alloca(MAX_PATH);
if (!pszFileName) { ec= OUT_OF_MEMORY; __leave; }
strcpy(pszFileName, PCHAR(m_ptsIndex->GetSourceName()));
UINT cb= strlen(pszFileName);
if ( (pszFileName[cb-3]=='h' || pszFileName[cb-3]=='H')
&& (pszFileName[cb-2]=='l' || pszFileName[cb-2]=='L')
&& (pszFileName[cb-1]=='p' || pszFileName[cb-1]=='P')
)
{
pszFileName[cb-3]='f';
pszFileName[cb-2]='t';
pszFileName[cb-1]='s';
}
else { ec= CANNOT_SAVE; __leave; }
}
m_pDiskImage= CPersist::CreateDiskImage(pszFileName,
m_ptsIndex->IndexOptions() & (TOPIC_SEARCH | PHRASE_SEARCH | PHRASE_FEEDBACK | VECTOR_SEARCH)
);
m_ptsIndex->StoreImage(m_pDiskImage);
m_pDiskImage->CompleteDiskImage();
}
__finally
{
if (m_pDiskImage)
{
if (_abnormal_termination()) m_pDiskImage->ExceptionDestructor();
else delete m_pDiskImage;
m_pDiskImage= NULL;
}
}
}
__except(FilterFTExceptions(uExceptionType= _exception_code()))
{
ec= ErrorCodeForExceptions(uExceptionType);
}
return ec;
}
CGlobals *CGlobals::NewSearcherGlobals()
{
CGlobals *pGlobals = NULL;
__try
{
pGlobals= New CGlobals(Searcher);
pGlobals->AttachSearchParams();
}
__except(FilterFTExceptions(_exception_code()))
{
if (pGlobals)
{
delete pGlobals; pGlobals= NULL;
}
EnableMemoryRequests(); // In case we failed for lack of virtual memory
EnableDiskRequests (); // or lack of disk space
}
return pGlobals;
}
void CGlobals::AttachSearchParams()
{
m_idProcess = ::GetCurrentProcessId();
Link();
m_papts= (CTextSet **) VAlloc(TRUE, SLOT_INCREMENT * sizeof(CTextSet *));
m_papPersist= (CPersist **) VAlloc(TRUE, SLOT_INCREMENT * sizeof(CPersist *));
m_ctsSlots = SLOT_INCREMENT;
}
INT CGlobals::OpenIndex(PSZ pszIndexFileName,
PBYTE pbSourceName, PUINT pcbSourceNameLimit,
FILETIME *pft,
UINT iSlot,
BOOL fUnpackDisplayForm
)
{
UINT uExceptionType = 0;
CTextSet **ppts = NULL;
CTextSet * pts = NULL;
CPersist **ppPersist = NULL;
CPersist * pPersist = NULL;
__try
{
if (m_pFind) { iSlot= DIALOG_ALREADY_ACTIVE; __leave; }
if (m_ptkc ) { iSlot= GROUP_LOADED_ALREADY; __leave; }
if (INT(iSlot) < 0)
if (m_ctsDiscarded)
{
UINT c= m_cts;
for (iSlot= UINT(-1); c--; )
if (!m_papts[c])
{
iSlot= c;
--m_ctsDiscarded;
break;
}
ASSERT(iSlot != UINT(-1));
}
else iSlot= m_cts;
if (iSlot >= m_cts)
{
m_cts= iSlot + 1;
if (m_cts >= m_ctsSlots)
{
ASSERT(m_cts == m_ctsSlots);
UINT cSlotsNew= m_ctsSlots + SLOT_INCREMENT;
ppts= (CTextSet **) VAlloc(FALSE, cSlotsNew * sizeof(CTextSet *));
CopyMemory(ppts, m_papts, m_ctsSlots * sizeof(CTextSet *));
ZeroMemory(ppts + m_ctsSlots, SLOT_INCREMENT * sizeof(CTextSet *));
ppPersist= (CPersist **) VAlloc(FALSE, cSlotsNew * sizeof(CPersist *));
CopyMemory(ppPersist, m_papPersist, m_ctsSlots * sizeof(CPersist *));
ZeroMemory(ppPersist + m_ctsSlots, SLOT_INCREMENT * sizeof(CPersist *));
VFree(m_papts ); m_papts = ppts; ppts = NULL;
VFree(m_papPersist); m_papPersist = ppPersist; ppPersist = NULL;
m_ctsSlots= cSlotsNew;
}
}
ASSERT(iSlot < m_cts);
FILENAMEBUFFER fnb;
BOOL fStartEnumeration= TRUE;
strcpy(fnb, pszIndexFileName);
for (;;)
{
UINT ec;
__try
{
pPersist= CPersist::OpenDiskImage(fnb);
if (pPersist)
pts= CTextSet::CreateImage(pPersist, pbSourceName, pcbSourceNameLimit, pft, fUnpackDisplayForm);
}
__except (FilterFTExceptions(ec= _exception_code()))
{
if (pts) { delete pts; pts = NULL; }
if (ec == STATUS_NO_MEMORY || ec == STATUS_NO_DISK_SPACE)
RaiseException(ec, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
if (pts) break;
if (pPersist) { delete pPersist; pPersist = NULL; }
if (FindFile(fnb, &fStartEnumeration)) continue;
iSlot= CANNOT_LOAD; __leave;
}
m_papPersist[iSlot]= pPersist; pPersist= NULL;
AttachRef(m_papts[iSlot], pts); pts= NULL;
m_papts[iSlot]->GetIndexInfo(pbSourceName, pcbSourceNameLimit, pft);
}
__except(FilterFTExceptions(uExceptionType= _exception_code()))
{
if (ppts ) VFree(ppts);
if (ppPersist) VFree(ppPersist);
if (pts ) delete pts;
if (pPersist) delete pPersist;
iSlot= ErrorCodeForExceptions(uExceptionType);
}
InvalidateHiliterHashTable();
return iSlot;
}
ERRORCODE CGlobals::DiscardIndex(INT iIndex)
{
if (iIndex < 0 || UINT(iIndex) >= m_cts || !m_papts[iIndex])
return INVALID_INDEX;
UINT uExceptionType = 0;
ERRORCODE ec = 0;
__try
{
DetachRef(m_papts[iIndex]);
delete m_papPersist[iIndex];
m_papPersist[iIndex]= 0;
m_ctsDiscarded++;
}
__except(FilterFTExceptions(uExceptionType= _exception_code()))
{
ec= ErrorCodeForExceptions(uExceptionType);
}
InvalidateHiliterHashTable();
return ec;
}
void CGlobals::RegisterHiliter(CHiliter* philNew)
{ // add our new hiliter to Searcher's hiliter list
ASSERT(m_iType == Searcher);
if (m_philHead) philNew->m_philNext = m_philHead;
m_philHead = philNew;
m_cHiliters++;
if (!m_pHash) GetHiliterHashTable();
}
void CGlobals::UnRegisterHiliter(CHiliter* philOld)
{ // remove hiliter to this object's globals hiliter list
ASSERT(m_iType == Searcher);
ASSERT(m_cHiliters);
CHiliter* phil = m_philHead;
CHiliter* philPrev = NULL;
for (UINT i=0; i<m_cHiliters; i++) // look for Hiliter to remove
{
if (phil==philOld)
{
if (philPrev) philPrev->m_philNext = philOld->m_philNext;
else m_philHead = philOld->m_philNext;
break;
}
else
{
philPrev = phil;
phil = phil->m_philNext;
}
}
m_cHiliters--;
}
ERRORCODE CGlobals::QueryOptions(INT iIndex, PUINT pfdwOptions)
{
if (iIndex < 0 || UINT(iIndex) >= m_cts || !m_papts[iIndex])
return INVALID_INDEX;
UINT uExceptionType = 0;
ERRORCODE ec = 0;
__try
{
if (pfdwOptions)
{
*pfdwOptions= 0;
*pfdwOptions= m_papts[iIndex]->IndexOptions();
}
}
__except(FilterFTExceptions(uExceptionType= _exception_code()))
{
ec= ErrorCodeForExceptions(uExceptionType);
}
return ec;
}
ERRORCODE CGlobals::SaveGroup(HSEARCHER hSearch, PSZ pszFileName)
{
if (!(m_cts - m_ctsDiscarded)) return NO_INDICES_LOADED;
UINT uExceptionType = 0;
ERRORCODE ec = 0;
CPersist *pDiskImage = NULL;
__try
{
pDiskImage= CPersist::CreateDiskImage(pszFileName, 0, FTGSIGNATURE, FTGVERSION);
if (!pDiskImage) { ec= CANNOT_SAVE; __leave; }
if (!m_ptkc)
{
AttachRef(m_ptkc, CTokenCollection::NewTokenCollection(m_papts, m_cts));
ASSERT(!m_ptlc);
AttachRef(m_ptlc, CTitleCollection::NewTitleCollection(m_papts, m_cts));
}
RecordIndexFiles(pDiskImage);
m_ptkc->RecordRelations(pDiskImage);
m_ptlc->RecordRelations(pDiskImage);
pDiskImage->CompleteDiskImage();
delete pDiskImage; pDiskImage= NULL;
}
__except(FilterFTExceptions(uExceptionType= _exception_code()))
{
if (pDiskImage) { delete pDiskImage; pDiskImage= NULL; }
if (m_ptkc && !m_ptlc) DetachRef(m_ptkc);
ec= ErrorCodeForExceptions(uExceptionType);
}
return ec;
}
void CGlobals::RecordIndexFiles(CPersist *pDiskImage)
{
PUINT pcTS= PUINT(pDiskImage->ReserveTableSpace(sizeof(UINT)));
*pcTS= m_cts;
PUINT paOffsets= PUINT(pDiskImage->ReserveTableSpace(m_cts * sizeof(UINT)));
UINT c= m_cts;
for (; c--; )
if (m_papts[c])
{
const BYTE *pszFileName= m_papPersist[c]->FileName();
UINT cb= strlen((const char *) pszFileName) + 1;
paOffsets[c]= pDiskImage->NextOffset();
pDiskImage->WriteBytes(pszFileName, cb);
}
else paOffsets[c]= 0;
}
ERRORCODE CGlobals::ReloadIndexFiles(CPersist *pDiskImage)
{
ASSERT(m_cts - m_ctsDiscarded == 0);
ERRORCODE ec = 0;
m_cts= m_ctsDiscarded= 0;
PUINT pcTS= PUINT(pDiskImage->ReserveTableSpace(sizeof(UINT)));
m_cts= *pcTS;
PUINT paOffsets= PUINT(pDiskImage->ReserveTableSpace(m_cts * sizeof(UINT)));
UINT c = m_cts;
PUINT pOff = paOffsets + m_cts;
for (; c; c--)
{
UINT offset= *--pOff;
if (offset)
{
PSZ pszFileName= (PSZ) pDiskImage->LocationOf(offset);
ec= OpenIndex(pszFileName, NULL, NULL, NULL, c-1, FALSE);
if (0 > ec) break;
}
else ++m_ctsDiscarded;
}
if (!ec) return 0;
DiscardAllTextSets();
return ec;
}
void CGlobals::DiscardAllTextSets()
{
UINT c;
for (c= m_cts; c--; )
if (m_papts[c]) DiscardIndex(c);
}
ERRORCODE CGlobals::LoadGroup(HSEARCHER hSearch, PSZ pszFileName)
{
if (m_cts - m_ctsDiscarded) return INDEX_LOADED_ALREADY;
ASSERT(!m_pPersistRelations);
DWORD uExceptionType = 0;
ERRORCODE ec = 0;
__try
{
FILENAMEBUFFER fnb;
BOOL fStartEnumeration= TRUE;
strcpy(fnb, pszFileName);
for (;;)
{
__try
{
m_pPersistRelations= CPersist::OpenDiskImage(fnb, FTGSIGNATURE, FTGVERSION, FTGVERSION_MIN);
}
__except(FilterFTExceptions(ec= _exception_code()))
{
if (ec == STATUS_NO_MEMORY || ec == STATUS_NO_DISK_SPACE)
RaiseException(ec, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
if (m_pPersistRelations) break;
if (FindFile(fnb, &fStartEnumeration)) continue;
ec= CANNOT_OPEN; __leave;
}
if (0 > ReloadIndexFiles(m_pPersistRelations))
{
delete m_pPersistRelations; m_pPersistRelations= NULL;
ec= CANNOT_LOAD; __leave;
}
ASSERT(!m_ptkc && !m_ptlc);
AttachRef(m_ptkc, CTokenCollection::NewTokenCollection(m_papts, m_cts, m_pPersistRelations));
AttachRef(m_ptlc, CTitleCollection::NewTitleCollection(m_papts, m_cts, m_pPersistRelations));
}
__except(FilterFTExceptions(uExceptionType= _exception_code()))
{
if (m_ptkc) DetachRef(m_ptkc);
if (m_ptlc) DetachRef(m_ptlc);
DiscardAllTextSets();
if (m_pPersistRelations) { delete m_pPersistRelations; m_pPersistRelations= NULL; }
ec= ErrorCodeForExceptions(uExceptionType);
}
return ec;
}
HWND CGlobals::OpenDialog(HWND hwndParent)
{
HWND hRet= NULL;
ASSERT(m_cts >= m_ctsDiscarded);
if (m_cts - m_ctsDiscarded == 0) return NULL;
__try
{
if (m_pFind == NULL)
{
if (!m_ptkc)
{
ASSERT(!m_ptlc);
AttachRef(m_ptkc, CTokenCollection::NewTokenCollection(m_papts, m_cts));
AttachRef(m_ptlc, CTitleCollection::NewTitleCollection(m_papts, m_cts));
}
m_pFind = CFind::NewFind(hinstDLL, IDD_FIND, hwndParent, m_papts, m_cts, m_ctsSlots,
m_ptkc, m_ptlc);
if (m_cHiliters)
{ // we may need a segmented new hash table for hiliting
if (!m_pHash) GetHiliterHashTable();
}
}
hRet = m_pFind->GetHWnd();
::SendMessage(hRet, UM_CONNECT, (WPARAM) hwndParent, 0l);
}
__except(FilterFTExceptions(_exception_code()))
{
if (m_pFind) { delete m_pFind; m_pFind= NULL; }
if (m_pHash) { delete m_pHash; m_pHash= NULL; }
if (m_ptlc) DetachRef(m_ptlc);
if (m_ptkc) DetachRef(m_ptkc);
hRet= NULL;
EnableMemoryRequests(); // In case we failed for lack of virtual memory
EnableDiskRequests (); // or lack of disk space
}
return hRet;
}
CSegHashTable *CGlobals::GetHiliterHashTable()
{ // get a segmented hash table filled with the token list
ASSERT(m_iType == Searcher); // only Searchers can take this call
if (!m_pHash)
{
if (!m_ptkc) return NULL;
m_pHash = m_ptkc->GetFilledHashTable();
}
return m_pHash;
}
void CGlobals::InvalidateHiliterHashTable()
{ // delete a segmented hash table filled from the token list
ASSERT(m_iType == Searcher); // only Searchers can take this call
if (!m_pHash) { delete m_pHash; m_pHash = NULL; }
}
CGlobals *CGlobals::NewCompressorGlobals(UINT iCharsetDefault)
{
CGlobals *pGlobals= NULL;
__try
{
pGlobals= New CGlobals(Compressor);
pGlobals->AttachCompressorParams(iCharsetDefault);
}
__except(FilterFTExceptions(_exception_code()))
{
if (pGlobals) { delete pGlobals; pGlobals= NULL; }
EnableMemoryRequests(); // In case we failed for lack of virtual memory
EnableDiskRequests (); // or lack of disk space
}
return pGlobals;
}
void CGlobals::AttachCompressorParams(UINT iCharsetDefault)
{
m_idProcess = ::GetCurrentProcessId();
Link();
m_pct = CCompressTable::NewCompressTable(iCharsetDefault);
}
CGlobals *pGlobalsList = NULL;
BOOL CGlobals::AnyGlobalsActive()
{
return BOOL(pGlobalsList);
}
void CGlobals::Link()
{
// BugBug! Need a mutex semaphore to protect the linked list work below!
m_pNextGlobal = pGlobalsList;
pGlobalsList = this;
}
void CGlobals::Unlink()
{
// BugBug! Need a mutex semaphore to protect the linked list work below!
CGlobals **ppGlobalsLast, *pGlobals;
for (ppGlobalsLast= &pGlobalsList, pGlobals= pGlobalsList;
pGlobals;
ppGlobalsLast= &(pGlobals->m_pNextGlobal), pGlobals= *ppGlobalsLast
)
if (pGlobals == this)
{
*ppGlobalsLast= pGlobals->m_pNextGlobal;
break;
}
}
void CGlobals::ProcessShutdown()
{
DWORD idThisProcess= ::GetCurrentProcessId();
CGlobals *pGlobals, *pGlobalsNext;
for (pGlobals= pGlobalsList; pGlobals; pGlobals= pGlobalsNext)
{
pGlobalsNext= pGlobals->m_pNextGlobal;
if (pGlobals->m_idProcess == idThisProcess)
delete pGlobals;
}
}
BOOL CGlobals::ValidObject(CGlobals *pg, UINT iType)
{
if (!pg) return FALSE;
if (pg->m_Signature != GLOBAL_SIGNATURE )
return FALSE;
if (pg->m_idProcess != ::GetCurrentProcessId())
return FALSE;
if (pg->m_iType != iType )
return FALSE;
return TRUE;
}
CGlobals::CGlobals(UINT iType)
{
m_Signature = GLOBAL_SIGNATURE;
m_iType = iType;
m_papts = NULL;
m_papPersist = NULL;
m_ptkc = NULL;
m_ptlc = NULL;
m_ptsIndex = NULL;
m_pct = NULL;
m_cts = 0;
m_ctsDiscarded = 0;
m_ctsSlots = 0;
m_cTitles = 0;
m_pDiskImage = NULL;
m_pFind = NULL;
m_pHash = NULL;
m_idProcess = 0;
m_pNextGlobal = NULL;
m_cHiliters = 0; // number of hiliters open
m_philHead = NULL;
}
CGlobals::CGlobals()
{
ASSERT (FALSE); // no parameter is an error
}
CGlobals::~CGlobals()
{
Unlink();
switch (m_iType)
{
case Indexer:
ASSERT(!m_pFind);
ASSERT(!m_pct );
if (m_ptsIndex) DetachRef(m_ptsIndex);
break;
case Searcher:
ASSERT(!m_pct);
if (m_pFind) { delete m_pFind; m_pFind = NULL; }
if (m_pHash) { delete m_pHash; m_pHash= NULL; }
if (m_ptkc) DetachRef(m_ptkc);
if (m_ptlc) DetachRef(m_ptlc);
if (m_papts)
{
CTextSet **ppts = m_papts;
CPersist **ppFile = m_papPersist;
UINT c = m_cts;
for (; c--; ++ppts, ++ppFile)
{
if (*ppts )
DetachRef(*ppts );
if (*ppFile)
{
delete *ppFile;
*ppFile= NULL;
}
}
VFree(m_papts ); m_papts = NULL;
VFree(m_papPersist); m_papPersist = NULL;
}
if (m_pPersistRelations) { delete m_pPersistRelations; m_pPersistRelations= NULL; }
break;
case Compressor:
ASSERT(!m_pFind);
if (m_pct)
{
delete m_pct;
m_pct= NULL;
}
break;
}
if (m_pDiskImage)
delete m_pDiskImage;
}