searcher/searchserver/src/ccpixsearch.cpp
changeset 0 671dee74050a
child 1 6f2c1c46032b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/searcher/searchserver/src/ccpixsearch.cpp	Mon Apr 19 14:40:16 2010 +0300
@@ -0,0 +1,354 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+#include "CCPixSearch.h"
+#include "CSearchDocument.h"
+#include "common.h"
+#include "SearchServerLogger.h"
+#include "CCPixAsyncronizer.h"
+#include "SearchServerHelper.h"
+
+namespace {
+
+/**
+ * cpix_DocFieldEnum destroyer for TCleanupItem
+ * @param aCpixDocFieldEnum CPix document
+ */
+void CpixDocFieldEnumDestroyer(TAny* aCpixDocFieldEnum)
+	{
+	cpix_DocFieldEnum_destroy( static_cast<cpix_DocFieldEnum*>( aCpixDocFieldEnum ) );
+	}
+
+} // namespace
+
+CCPixSearch* CCPixSearch::NewL()
+	{
+	CCPixSearch* self = CCPixSearch::NewLC();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CCPixSearch* CCPixSearch::NewLC()
+	{
+	CCPixSearch* self = new (ELeave) CCPixSearch();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+CCPixSearch::CCPixSearch()
+	: iPendingTask(EPendingTaskNone)
+	{
+	}
+
+CCPixSearch::~CCPixSearch()
+	{
+	delete iAsyncronizer;
+	if ( iHits )
+		{
+		cpix_Hits_destroy( iHits );
+		}
+
+	delete iBaseAppClass;
+	delete iDefaultSearchFieldZ;
+	
+	cpix_Query_destroy(iQuery);
+	cpix_QueryParser_destroy(iQueryParser);
+	cpix_Analyzer_destroy(iAnalyzer);
+	cpix_IdxSearcher_releaseDb(iIdxDb);
+	}
+
+void CCPixSearch::ConstructL()
+	{
+	iAsyncronizer = CCPixAsyncronizer::NewL();
+	}
+
+void CCPixSearch::CancelAll(const RMessage2& aMessage)
+	{
+    if (iPendingTask == EPendingTaskSearch)
+	    {
+		iAsyncronizer->Cancel();
+		cpix_CancelAction cancelAction = 
+            cpix_IdxSearcher_cancelSearch(iIdxDb, iPendingJobId);
+		LogCancelAction(cancelAction);
+		
+		cpix_ClearError(iIdxDb);
+		aMessage.Complete(KErrNone);
+		}
+    else if (iPendingTask == EPendingTaskDocument)
+    	{
+		iAsyncronizer->Cancel();
+		cpix_CancelAction cancelAction = 
+            cpix_Hits_cancelDoc(iHits, iPendingJobId);
+	   	LogCancelAction(cancelAction);
+	   	
+		cpix_ClearError(iHits);
+	   	aMessage.Complete(KErrNone);
+    	}
+    else if ( iPendingTask != EPendingTaskNone )
+        {
+        // Do nothing here. Wait until asynchronous functions
+        // completes and complete request after that.
+        iAsyncronizer->CancelWhenDone(aMessage);
+        }
+    else 
+        {
+        // else must complete the message now
+        aMessage.Complete(KErrNone);
+        }
+
+    iPendingTask = EPendingTaskNone;
+	}
+
+void CCPixSearch::LogCancelAction(cpix_CancelAction aCancelAction)
+    {
+#ifdef CPIX_LOGGING_ENABLED
+    CPIXLOGSTRING2("Cancel action code %d", aCancelAction);
+#endif // CPIX_LOGGING_ENABLED
+    }
+
+void CCPixSearch::CompletionCallback(void *aCookie, cpix_JobId aJobId)
+	{
+	CCPixSearch* object = (CCPixSearch*)aCookie;
+
+	// Sanity check
+	if (object == NULL || 
+		object->iPendingJobId != aJobId)
+		return;
+	
+	// Call the asyncronizers completion code
+	CCPixAsyncronizer* asyncronizer = object->iAsyncronizer;
+	asyncronizer->CompletionCallback();
+	}
+
+TBool CCPixSearch::SearchL(const TDesC& aSearchTerms, MCPixAsyncronizerObserver* aObserver, const RMessage2& aMessage)
+    {
+    PERFORMANCE_LOG_START("CCPixSearch::SearchL");
+    
+    if (iPendingTask != EPendingTaskNone)
+        User::Leave(KErrInUse);
+
+    // Destroy previous hits
+    iDocumentCount = 0;
+    cpix_Hits_destroy( iHits );
+    iHits = NULL; 
+    // Allocate search terms (allow zero termination)
+    HBufC* searchTerms = HBufC::NewLC(aSearchTerms.Length() + 1);
+    TPtr searchTermsPtr = searchTerms->Des();
+    searchTermsPtr.Copy(aSearchTerms);
+    
+    // Destroy previous query
+    cpix_Query_destroy( iQuery );
+    iQuery = NULL;
+    
+    // Commit the new query
+    iQuery = cpix_QueryParser_parse(iQueryParser, reinterpret_cast<const wchar_t*>(searchTermsPtr.PtrZ()) );
+    SearchServerHelper::CheckCpixErrorL(iQuery, KErrQueryParsingFailed);
+    
+    // Cleanup terms
+    CleanupStack::PopAndDestroy(searchTerms);
+    
+    // Commit the search
+    if ( iQuery )
+	    {
+	    iPendingJobId = cpix_IdxSearcher_asyncSearch(iIdxDb, iQuery, (void*)this, &CompletionCallback);
+	    SearchServerHelper::CheckCpixErrorL(iIdxDb, KErrDatabaseQueryFailed);
+    	iPendingTask = EPendingTaskSearch;
+	    iAsyncronizer->Start(ECPixTaskTypeSearch, aObserver, aMessage);
+	    
+        return ETrue;
+        }
+    
+    // Search was not committed
+    return EFalse;
+    }
+
+TInt CCPixSearch::SearchCompleteL()
+    {
+    PERFORMANCE_LOG_START("CCPixSearch::SearchCompleteL");
+    // Request is no more pending
+    iPendingTask = EPendingTaskNone;
+    
+    // Get the hits
+    iHits = cpix_IdxSearcher_asyncSearchResults(iIdxDb, iPendingJobId);
+    SearchServerHelper::CheckCpixErrorL(iIdxDb, KErrDatabaseQueryFailed);
+	iDocumentCount = cpix_Hits_length(iHits);
+	SearchServerHelper::CheckCpixErrorL(iHits, KErrDatabaseQueryFailed);
+	
+	return iDocumentCount; 
+    }
+       
+void CCPixSearch::GetDocumentL(TInt aIndex, MCPixAsyncronizerObserver* aObserver, const RMessage2& aMessage)
+	{
+	PERFORMANCE_LOG_START("CCPixSearch::GetDocumentL");
+	
+    if (iPendingTask != EPendingTaskNone)
+        User::Leave(KErrInUse);
+		
+	if (aIndex<0 || aIndex >= iDocumentCount )
+		{
+		User::Leave(KErrDocumentAccessFailed);
+		}
+	
+    iPendingTask = EPendingTaskDocument;
+    iPendingJobId = cpix_Hits_asyncDoc(iHits, aIndex, &iCurrentCpixDocument, (void*)this, &CompletionCallback);
+    if ( cpix_Failed(iHits) )
+        {
+        SearchServerHelper::LogErrorL(*(iHits->err_));
+        cpix_ClearError(iHits);
+        User::Leave(KErrDocumentAccessFailed);
+        }
+    iAsyncronizer->Start(ECPixTaskTypeGetDocument, aObserver, aMessage);
+	}
+
+CSearchDocument* CCPixSearch::GetDocumentCompleteL()
+	{
+	PERFORMANCE_LOG_START("CCPixSearch::GetDocumentCompleteL");
+	
+    // Request is no more pending
+    iPendingTask = EPendingTaskNone;
+	
+	cpix_Hits_asyncDocResults(iHits, iPendingJobId);
+	SearchServerHelper::CheckCpixErrorL(iHits, KErrDocumentAccessFailed);
+
+	const wchar_t* documentId = cpix_Document_getFieldValue(&iCurrentCpixDocument, LCPIX_DOCUID_FIELD);
+	SearchServerHelper::CheckCpixErrorL(&iCurrentCpixDocument, KErrDatabaseQueryFailed);
+	
+	TPtrC documentIdPtr(KNullDesC);
+	if (documentId)
+		documentIdPtr.Set(reinterpret_cast<const TUint16*>(documentId));
+
+	const wchar_t* documentAppClass = cpix_Document_getFieldValue(&iCurrentCpixDocument, LCPIX_APPCLASS_FIELD);
+	SearchServerHelper::CheckCpixErrorL(&iCurrentCpixDocument, KErrDatabaseQueryFailed);
+	
+	TPtrC documentAppClassPtr(KNullDesC);
+	if (documentAppClass)
+		documentAppClassPtr.Set(reinterpret_cast<const TUint16*>(documentAppClass));
+
+	const wchar_t* documentExcerpt = cpix_Document_getFieldValue(&iCurrentCpixDocument, LCPIX_EXCERPT_FIELD);
+	SearchServerHelper::CheckCpixErrorL(&iCurrentCpixDocument, KErrDatabaseQueryFailed);
+	
+	TPtrC documentExcerptPtr(KNullDesC);
+	if (documentExcerpt)
+		documentExcerptPtr.Set(reinterpret_cast<const TUint16*>(documentExcerpt));
+
+	CSearchDocument* document = CSearchDocument::NewLC(documentIdPtr, documentAppClassPtr, documentExcerptPtr);
+
+	cpix_DocFieldEnum* docFieldEnum = cpix_Document_fields(&iCurrentCpixDocument);
+
+	// push to cleanup stack.
+	CleanupStack::PushL( TCleanupItem(CpixDocFieldEnumDestroyer, docFieldEnum) );
+
+	SearchServerHelper::CheckCpixErrorL(&iCurrentCpixDocument, KErrDocumentAccessFailed);
+
+	cpix_Field field;
+
+	while (cpix_DocFieldEnum_hasMore(docFieldEnum))
+		{
+		cpix_DocFieldEnum_next(docFieldEnum, &field);
+		SearchServerHelper::CheckCpixErrorL(docFieldEnum, KErrDatabaseQueryFailed);
+		
+		const wchar_t* name = cpix_Field_name(&field);
+		SearchServerHelper::CheckCpixErrorL(&field, KErrDatabaseQueryFailed);
+
+		TPtrC namePtr( reinterpret_cast<const TUint16*>( name ) );
+		if (    namePtr == TPtrC( (TUint16*)LCPIX_DOCUID_FIELD )
+			 || namePtr == TPtrC( (TUint16*)LCPIX_APPCLASS_FIELD )
+			 || namePtr == TPtrC( (TUint16*)LCPIX_EXCERPT_FIELD ) )
+			{
+			continue;  // These fields have already been added
+			}
+
+		const wchar_t* value = cpix_Field_stringValue(&field);
+		SearchServerHelper::CheckCpixErrorL(&field, KErrDatabaseQueryFailed);
+		
+		TPtrC stringvalue( reinterpret_cast<const TUint16*>( value ) );
+		document->AddFieldL(namePtr, stringvalue);
+		}
+
+	CleanupStack::PopAndDestroy(docFieldEnum);
+	
+	CleanupStack::Pop(document);
+	
+	return document;
+	}
+
+void CCPixSearch::SetAnalyzerL(const TDesC& aAnalyzer)
+	{
+	cpix_QueryParser_destroy( iQueryParser ); 
+	iQueryParser = NULL; 
+	
+	cpix_Analyzer_destroy( iAnalyzer ); 
+	iAnalyzer = NULL; 
+	
+	// Create analyzer
+	cpix_Result result;
+	
+	HBufC* analyzer = HBufC::NewLC(aAnalyzer.Length() + 1);
+	TPtr analyzerPtr = analyzer->Des();
+	analyzerPtr.Copy(aAnalyzer);
+	const wchar_t* cAnalyzer = reinterpret_cast<const wchar_t*>(analyzerPtr.PtrZ());
+
+	iAnalyzer = cpix_Analyzer_create(&result, cAnalyzer);
+	SearchServerHelper::CheckCpixErrorL(&result, KErrCannotCreateAnalyzer);
+
+	CleanupStack::PopAndDestroy( analyzer ); 
+
+	iQueryParser = 
+		cpix_QueryParser_create(&result,
+			reinterpret_cast<const wchar_t*>(iDefaultSearchFieldZ->Des().PtrZ()), 
+			iAnalyzer);
+	SearchServerHelper::CheckCpixErrorL(&result, KErrCannotCreateQueryParser);
+	}
+
+void CCPixSearch::OpenDatabaseL(const TDesC& aBaseAppClass, const TDesC& aDefaultSearchField)
+	{
+	// Release data associated with old database 
+	delete iDefaultSearchFieldZ;
+	iDefaultSearchFieldZ = NULL;
+	delete iBaseAppClass;
+	iBaseAppClass = NULL;
+	cpix_IdxSearcher_releaseDb( iIdxDb );
+	iIdxDb = NULL;
+	
+	// Allocate default search field (space for zero terminated)
+	iDefaultSearchFieldZ = HBufC::NewL(aDefaultSearchField.Size() + 1);
+	TPtr defaultSearchFieldPtr = iDefaultSearchFieldZ->Des();
+	defaultSearchFieldPtr.Copy(aDefaultSearchField);
+	
+	// Allocate base app class (space for zero terminated)
+	iBaseAppClass = HBufC8::NewL(aBaseAppClass.Size() + 1);
+	TPtr8 baseAppClassPtr = iBaseAppClass->Des();
+	baseAppClassPtr.Copy(aBaseAppClass);
+	
+    // Try to open database
+    cpix_Result result;
+    iIdxDb = 
+		cpix_IdxSearcher_openDb(
+			&result,
+            reinterpret_cast<const char*>( baseAppClassPtr.PtrZ() ));
+    SearchServerHelper::CheckCpixErrorL(&result, KErrCannotOpenDatabase);
+
+	// Set default analyzer
+	SetAnalyzerL(TPtrC((TUint16*)CPIX_ANALYZER_DEFAULT)); 
+	}
+
+TBool CCPixSearch::IsOpen()
+	{
+	return (iIdxDb != NULL);
+	}
+