searcher/searchserver/src/ccpixidxdb.cpp
changeset 0 671dee74050a
child 1 6f2c1c46032b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/searcher/searchserver/src/ccpixidxdb.cpp	Mon Apr 19 14:40:16 2010 +0300
@@ -0,0 +1,573 @@
+/*
+* 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 "CCPixIdxDb.h"
+#include "CSearchDocument.h"
+#include "common.h"
+#include "SearchServerLogger.h"
+#include "CCPixAsyncronizer.h"
+
+#include <f32file.h>
+
+#include "SearchServerConfiguration.h"
+#include "SearchServerHelper.h"
+
+namespace {
+
+void DumpDocument(const CSearchDocument& aDocument)
+	{
+#ifdef CPIX_LOGGING_ENABLED
+	CPIXLOGSTRING2("DumpDocument START _docuid=%S", &(aDocument.Id()));
+
+	_LIT(KDocUid, CPIX_DOCUID_FIELD);
+	const TInt fieldCount = aDocument.FieldCount();
+	for (TInt i = 0; i < fieldCount; i++)
+		{
+		const CDocumentField& field = aDocument.Field(i);
+		
+		if (field.Name() == KDocUid())
+			{
+			continue; // lets not print this information out twice.
+			}
+		CPIXLOGSTRING3("DumpDocument FieldName=%S,Value=%S", &(field.Name()), &(field.Value()));
+		}
+	CPIXLOGSTRING2("DumpDocument END _docuid=%S", &(aDocument.Id()));
+#endif // CPIX_LOGGING_ENABLED
+	}
+
+/**
+ * InitParams destroyer for TCleanupItem
+ * @param aCpixInitParams CPix related init parameter
+ */
+void CpixInitParamsDestroyer(TAny* aCpixInitParams)
+    {
+    cpix_InitParams_destroy( static_cast<cpix_InitParams*>( aCpixInitParams ) );
+    }
+
+/**
+ * cpix_Document destroyer for TCleanupItem
+ * @param aCpixDocument CPix document
+ */
+void CpixDocumentDestroyer(TAny* aCpixDocument)
+    {
+    cpix_Document_destroy( static_cast<cpix_Document*>( aCpixDocument ) );
+    }
+
+/**
+ * cpix_DocFieldEnum destroyer for TCleanupItem
+ * @param aCpixDocFieldEnum CPix document
+ */
+void CpixDocFieldEnumDestroyer(TAny* aCpixDocFieldEnum)
+	{
+	cpix_DocFieldEnum_destroy( static_cast<cpix_DocFieldEnum*>( aCpixDocFieldEnum ) );
+	}
+
+} // namespace
+
+CCPixIdxDb* CCPixIdxDb::NewL()
+	{
+	CCPixIdxDb* self = CCPixIdxDb::NewLC();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CCPixIdxDb* CCPixIdxDb::NewLC()
+	{
+	CCPixIdxDb* self = new (ELeave) CCPixIdxDb();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+CCPixIdxDb::CCPixIdxDb()
+    : iIsPending(EFalse)
+    {
+    }
+
+CCPixIdxDb::~CCPixIdxDb()
+	{
+	delete iAsyncronizer;
+	delete iBaseAppClass;
+	cpix_IdxDb_releaseDb(iIdxDb);
+	cpix_Analyzer_destroy(iAnalyzer);
+	}
+
+void CCPixIdxDb::ConstructL()
+	{
+	iAsyncronizer = CCPixAsyncronizer::NewL();
+	}
+
+// Cancel any incomplete asyncronous operation
+void CCPixIdxDb::CancelAll(const RMessage2& aMessage)
+	{
+    // Do nothing here. Wait until asynchronous functions
+    // completes and complete request after that.
+    iAsyncronizer->CancelWhenDone(aMessage);
+	}
+
+void CCPixIdxDb::CompletionCallback(void *aCookie, cpix_JobId aJobId)
+	{
+	CCPixIdxDb* object = (CCPixIdxDb*)aCookie;
+
+	// Sanity check
+	if (object == NULL || 
+		object->iPendingJobId != aJobId)
+		return;
+	
+	// Call the asyncronizers completion code
+	CCPixAsyncronizer* asyncronizer = object->iAsyncronizer;
+	asyncronizer->CompletionCallback();
+	}
+
+void CCPixIdxDb::InitializeL()
+	{
+#ifdef CPIX_LOGGING_ENABLED
+	_LIT(KCPixLogDirectory, "c:\\logs\\CPix\\OpenC\\");
+	const char* CPIX_LOG_FILE = "c:\\logs\\CPix\\OpenC\\libcpix";
+	const TInt KLogSizeLimit = 400 * 1024;
+	const TInt KLogSizeCheckRecurrency = 10; 
+#endif // CPIX_LOGGING_ENABLED
+
+	RFs fs;
+	User::LeaveIfError(fs.Connect());
+	CleanupClosePushL(fs);
+#ifdef CPIX_LOGGING_ENABLED
+	TInt err = fs.MkDirAll(KCPixLogDirectory);
+
+	if ( err != KErrNone && err != KErrAlreadyExists )
+		{
+		User::Leave(err);
+		}
+#endif // CPIX_LOGGING_ENABLED	
+
+	TBuf8<30> registryPath;
+	
+	fs.CreatePrivatePath(EDriveC);
+
+	TFileName pathWithoutDrive;
+	fs.PrivatePath(pathWithoutDrive);
+
+	registryPath.Append(_L("C:"));
+	registryPath.Append(pathWithoutDrive);
+
+	cpix_Result result;
+
+        cpix_InitParams
+            * initParams = cpix_InitParams_create(&result);
+                
+        CleanupStack::PushL( TCleanupItem (CpixInitParamsDestroyer, initParams) );
+        SearchServerHelper::CheckCpixErrorL(&result,
+                                            KErrCPixInitializationFailed);
+        
+        cpix_InitParams_setCpixDir(initParams,
+                                   reinterpret_cast<const char*>( registryPath.PtrZ() ));
+        SearchServerHelper::CheckCpixErrorL(initParams,
+                                            KErrCPixInitializationFailed);
+
+        cpix_InitParams_setMaxIdleSec(initParams,
+                                      IDXDB_MAXIDLE_SEC);
+        SearchServerHelper::CheckCpixErrorL(initParams,
+                                            KErrCPixInitializationFailed);
+
+        cpix_InitParams_setQryThreadPriorityDelta(initParams,
+                                                  QRY_THREAD_PRIORITY_DELTA);
+        SearchServerHelper::CheckCpixErrorL(initParams,
+                                            KErrCPixInitializationFailed);
+        
+        cpix_InitParams_setCluceneLockDir(initParams,
+                                       "C:\\Private\\2001f6f7\\clucenelockdir\\");
+        SearchServerHelper::CheckCpixErrorL(initParams,
+                                            KErrCPixInitializationFailed);
+        
+
+#ifdef CPIX_LOGGING_ENABLED
+        cpix_InitParams_setLogFileBase(initParams,
+                                       CPIX_LOG_FILE);
+        SearchServerHelper::CheckCpixErrorL(initParams,
+                                            KErrCPixInitializationFailed);
+
+        cpix_InitParams_setLogSizeLimit(initParams,
+                                        KLogSizeLimit);
+        SearchServerHelper::CheckCpixErrorL(initParams,
+                                            KErrCPixInitializationFailed);
+
+        cpix_InitParams_setLogSizeCheckRecurrency(initParams,
+                                                  KLogSizeCheckRecurrency);
+        SearchServerHelper::CheckCpixErrorL(initParams,
+                                            KErrCPixInitializationFailed);
+#endif
+
+        cpix_init(&result,
+                  initParams);
+    
+        SearchServerHelper::CheckCpixErrorL(&result,
+                                            KErrCPixInitializationFailed);
+
+        CleanupStack::PopAndDestroy(initParams);
+
+#ifdef CPIX_LOGGING_ENABLED
+#ifdef CPIX_OPENC_LOGDBG
+    // Enable OpenC logging
+    cpix_setLogLevel(CPIX_LL_DEBUG);
+#endif
+#endif // CPIX_LOGGING_ENABLED
+
+
+	CleanupStack::PopAndDestroy(); //fs
+	}
+
+void CCPixIdxDb::Shutdown()
+	{
+	cpix_shutdown();
+	}
+
+void CCPixIdxDb::OpenDatabaseL(const TDesC& aBaseAppClass)
+	{
+	// Allocate base app class (space for zero terminated)
+	cpix_IdxDb_releaseDb( iIdxDb );
+	iIdxDb = NULL; 
+	
+	delete iBaseAppClass;
+	iBaseAppClass = NULL;	
+	
+	iBaseAppClass = HBufC8::NewL(aBaseAppClass.Size() + 1);
+	TPtr8 baseAppClassPtr = iBaseAppClass->Des();
+	baseAppClassPtr.Copy(aBaseAppClass);
+	    
+    // Try to open database
+    cpix_Result result;
+    iIdxDb = cpix_IdxDb_openDb(
+    		       &result,
+				   reinterpret_cast<const char*>( baseAppClassPtr.PtrZ() ),
+				   cpix_IDX_OPEN);
+    SearchServerHelper::CheckCpixErrorL(&result, KErrCannotOpenDatabase);
+     
+	// Set default analyzer
+	SetAnalyzerL(TPtrC16((TUint16*)CPIX_ANALYZER_DEFAULT)); 
+	}
+
+TBool CCPixIdxDb::IsOpen()
+	{
+	return (iIdxDb != NULL);
+	}
+
+TPtrC8 CCPixIdxDb::BaseAppClass()
+	{
+	TPtrC8 ptr;
+	ptr.Set( *iBaseAppClass );
+	return ptr;
+	}
+
+void CCPixIdxDb::AddL(const CSearchDocument& aDocument, MCPixAsyncronizerObserver* aObserver, const RMessage2& aMessage)
+	{	
+    if (iIsPending)
+        User::Leave(KErrInUse);
+
+    cpix_Document* document = NULL;
+	document = ConvertToCpixDocumentLC(aDocument);
+
+	CPIXLOGSTRING("CCPixIdxDb::AddL");
+	DumpDocument(aDocument);
+	iPendingJobId = cpix_IdxDb_asyncAdd(iIdxDb, document, iAnalyzer, (void*)this, &CompletionCallback);
+	CleanupStack::PopAndDestroy(document);
+	SearchServerHelper::CheckCpixErrorL(iIdxDb, KErrCannotAddDocument);
+    iIsPending = ETrue;
+	
+	iAsyncronizer->Start(ECPixTaskTypeAdd, aObserver, aMessage);
+	}
+	
+void CCPixIdxDb::AddCompleteL()
+	{
+    iIsPending = EFalse;
+	cpix_IdxDb_asyncAddResults(iIdxDb, iPendingJobId);
+	SearchServerHelper::CheckCpixErrorL(iIdxDb, KErrCannotAddDocument);
+	}
+
+void CCPixIdxDb::UpdateL(const CSearchDocument& aDocument, MCPixAsyncronizerObserver* aObserver, const RMessage2& aMessage)
+	{
+    if (iIsPending)
+        User::Leave(KErrInUse);
+
+	cpix_Document* document = NULL;	
+	document = ConvertToCpixDocumentLC(aDocument);
+
+	CPIXLOGSTRING("CCPixIdxDb::UpdateL");
+	DumpDocument(aDocument);
+    iPendingJobId = cpix_IdxDb_asyncUpdate(iIdxDb, document, iAnalyzer, (void*)this, &CompletionCallback);
+	CleanupStack::PopAndDestroy(document);
+	SearchServerHelper::CheckCpixErrorL(iIdxDb,KErrCannotUpdateDocument);
+    iIsPending = ETrue;
+
+    iAsyncronizer->Start(ECPixTaskTypeUpdate, aObserver, aMessage);
+	}
+
+void CCPixIdxDb::UpdateCompleteL()
+	{
+    iIsPending = EFalse;
+	cpix_IdxDb_asyncUpdateResults(iIdxDb, iPendingJobId);
+	SearchServerHelper::CheckCpixErrorL(iIdxDb, KErrCannotUpdateDocument);
+	}
+
+void CCPixIdxDb::DeleteDocumentsL(const TDesC& aDocUid, MCPixAsyncronizerObserver* aObserver, const RMessage2& aMessage)
+	{
+    if (iIsPending)
+        User::Leave(KErrInUse);
+	
+	CPIXLOGSTRING2("CCPixIdxDb::DeleteDocumentsL aDocUid=%S", &aDocUid);
+
+	HBufC* docUid = HBufC::NewLC(aDocUid.Length() + 1);
+	TPtr docUidPtr = docUid->Des();
+	docUidPtr.Copy(aDocUid);	
+	
+	const wchar_t* cDocumentId = reinterpret_cast<const wchar_t*>(docUidPtr.PtrZ());
+
+    iIsPending = ETrue;
+    iPendingJobId = cpix_IdxDb_asyncDeleteDocuments(iIdxDb, cDocumentId, (void*)this, &CompletionCallback);
+    SearchServerHelper::CheckCpixErrorL(iIdxDb, KErrCannotDeleteDocument);
+	CleanupStack::PopAndDestroy(docUid);	 
+	
+    iAsyncronizer->Start(ECPixTaskTypeDelete, aObserver, aMessage);
+	}
+
+void CCPixIdxDb::DeleteDocumentsCompleteL()
+	{
+    iIsPending = EFalse;
+    cpix_IdxDb_asyncDeleteDocumentsResults(iIdxDb, iPendingJobId);
+	SearchServerHelper::CheckCpixErrorL(iIdxDb, KErrCannotDeleteDocument);
+	}
+
+void CCPixIdxDb::FlushCompleteL()
+	{
+    iIsPending = EFalse;
+    cpix_IdxDb_asyncFlushResults(iIdxDb, iPendingJobId);
+	SearchServerHelper::CheckCpixErrorL(iIdxDb, KErrDatabaseFlushFailed);
+	}
+
+void CCPixIdxDb::SetAnalyzerL(const TDesC& aAnalyzer)
+	{
+	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);
+	
+	CleanupStack::PopAndDestroy( analyzer ); 
+	
+	if ( !iAnalyzer || cpix_Failed( &result ) )
+		{
+		SearchServerHelper::LogErrorL(*result.err_);
+		cpix_ClearError(&result);
+		User::Leave(KErrCannotCreateAnalyzer);
+		}
+	}
+
+void CCPixIdxDb::ResetL()
+	{
+    if (iIsPending)
+        User::Leave(KErrInUse);
+	
+	cpix_IdxDb_releaseDb(iIdxDb);
+	iIdxDb = NULL;
+
+	cpix_Result result;
+	iIdxDb = cpix_IdxDb_openDb( &result, 
+			reinterpret_cast<const char*>( iBaseAppClass->Des().PtrZ() ), cpix_IDX_CREATE );
+
+	// Leave if operation failed
+	SearchServerHelper::CheckCpixErrorL(&result, KErrCannotOpenDatabase);
+	}
+
+void CCPixIdxDb::FlushL(MCPixAsyncronizerObserver* aObserver, const RMessage2& aMessage)
+    {   
+    if (iIsPending)
+        User::Leave(KErrInUse);
+
+    
+    iPendingJobId = cpix_IdxDb_asyncFlush(iIdxDb, (void*)this, &CompletionCallback);
+    SearchServerHelper::CheckCpixErrorL(iIdxDb, KErrDatabaseFlushFailed);
+    iIsPending = ETrue;
+    
+    iAsyncronizer->Start(ECPixTaskTypeFlush, aObserver, aMessage);
+    }
+
+const char* CCPixIdxDb::GetFieldCStrLC(const CSearchDocument& aDocument, const TDesC& aFieldName )
+	{
+	const CDocumentField* field = aDocument.Field( aFieldName );
+	if ( field )
+		{
+		HBufC8* fieldValue = HBufC8::NewLC( field->Value().Size() + 1);
+		TPtr8 fieldValuePtr = fieldValue->Des();
+		fieldValuePtr.Copy( field->Value() );	
+		return reinterpret_cast<const char*>(fieldValuePtr.PtrZ());
+		}
+	else 
+		{
+		HBufC::NewLC( 1 ); // populate cleanup
+		}
+	return 0;
+	}
+
+const wchar_t* CCPixIdxDb::GetFieldWideCStrLC(const CSearchDocument& aDocument, const TDesC& aFieldName )
+ 	{
+	const CDocumentField* field = aDocument.Field( aFieldName );
+	if ( field )
+		{
+		HBufC* fieldValue = HBufC::NewLC( field->Value().Size() + 1);
+		TPtr fieldValuePtr = fieldValue->Des();
+		fieldValuePtr.Copy( field->Value() );	
+		return reinterpret_cast<const wchar_t*>(fieldValuePtr.PtrZ());
+		}
+	else 
+		{
+		HBufC::NewLC( 1 ); // populate cleanup
+		}
+	return 0;
+	}
+
+cpix_Document* CCPixIdxDb::ConvertToCpixDocumentLC(const CSearchDocument& aDocument)
+	{	
+	cpix_Document* doc = NULL; // to return;  
+	
+	const wchar_t* cDocumentId = GetFieldWideCStrLC( aDocument, TPtrC((TUint16*)LCPIX_DOCUID_FIELD) ); 
+	const char* cDocumentAppClass = GetFieldCStrLC( aDocument, TPtrC((TUint16*)LCPIX_APPCLASS_FIELD) ); 
+	const wchar_t* cDocumentExcerpt = GetFieldWideCStrLC( aDocument, TPtrC((TUint16*)LCPIX_EXCERPT_FIELD) );
+	const wchar_t* cDocumentMimeType = GetFieldWideCStrLC( aDocument, TPtrC((TUint16*)LCPIX_MIMETYPE_FIELD) );
+	
+	cpix_Result result;
+
+	// ownership of cDocumentId is not transferred
+	doc = cpix_Document_create(&result,
+							   cDocumentId, 
+							   cDocumentAppClass, 
+							   cDocumentExcerpt, 
+							   cDocumentMimeType);
+	SearchServerHelper::CheckCpixErrorL(&result, KErrCannotCreateDocument);
+	CleanupStack::PopAndDestroy(4);
+
+	if (!doc)
+		{
+		SearchServerHelper::LogErrorL(*result.err_);
+		cpix_ClearError(doc);
+		User::Leave(KErrCannotCreateDocument);
+		}
+	// document created, push to cleanup stack.
+	CleanupStack::PushL( TCleanupItem (CpixDocumentDestroyer, doc) );
+
+	// Do the necessary magic, to copy the system field boosts 
+	// from S60 document into CPix document
+	cpix_Document_setBoost( doc, aDocument.Boost() );
+	SearchServerHelper::CheckCpixErrorL(doc, KErrCannotCreateDocumentField);
+	
+	cpix_DocFieldEnum* fields = cpix_Document_fields( doc );
+	// push to cleanup stack.
+	CleanupStack::PushL( TCleanupItem (CpixDocFieldEnumDestroyer, fields) );
+
+	if ( !fields || cpix_Failed( doc ) ) 
+		{
+		SearchServerHelper::LogErrorL(*doc->err_);
+		cpix_ClearError(doc);
+		User::Leave(KErrCannotCreateDocumentField);
+		}
+	
+	while ( cpix_DocFieldEnum_hasMore( fields ) ) 
+		{
+		cpix_Field sysField;
+		cpix_DocFieldEnum_next( fields, &sysField );
+		
+		if ( cpix_Failed( fields ) ) 
+			{
+			SearchServerHelper::LogErrorL(*fields->err_);
+			cpix_ClearError(fields);
+			User::Leave(KErrCannotCreateDocumentField);
+			}
+		
+		const wchar_t* name = cpix_Field_name( &sysField ); 
+		SearchServerHelper::CheckCpixErrorL(&sysField, KErrCannotCreateDocumentField);
+		
+		TPtrC16 nameDesc;
+		nameDesc.Set( reinterpret_cast<const TUint16*>( name ), 
+					  wcslen( name ) );
+		
+		const CDocumentField* field = aDocument.Field( nameDesc );
+		if ( field )
+			{
+			cpix_Field_setBoost( &sysField, field->Boost() );
+			SearchServerHelper::CheckCpixErrorL(&sysField, KErrCannotCreateDocumentField);
+			}
+		}
+	
+	CleanupStack::PopAndDestroy(fields);
+	
+	// Copy rest of the fiels
+	// 
+	
+	for (TInt i = 0; i < aDocument.FieldCount(); i++)
+		{
+		const CDocumentField& srcField = aDocument.Field(i);
+		
+		if (    srcField.Name() == TPtrC((TUint16*)LCPIX_DOCUID_FIELD) 
+		     || srcField.Name() == TPtrC((TUint16*)LCPIX_APPCLASS_FIELD)
+		     || srcField.Name() == TPtrC((TUint16*)LCPIX_EXCERPT_FIELD)
+		     || srcField.Name() == TPtrC((TUint16*)LCPIX_MIMETYPE_FIELD)) 
+			{
+		    continue;  // These fields have already been passed
+			}
+			
+		HBufC* srcFieldName = HBufC::NewLC(srcField.Name().Length() + 1);
+		TPtr srcFieldNamePtr = srcFieldName->Des();
+		srcFieldNamePtr.Copy(srcField.Name());	
+
+		HBufC* srcFieldValue = HBufC::NewLC(srcField.Value().Length() + 1);
+		TPtr srcFieldValuePtr = srcFieldValue->Des();
+		srcFieldValuePtr.Copy(srcField.Value());	
+
+		const wchar_t* cStrName = reinterpret_cast<const wchar_t*>(srcFieldNamePtr.PtrZ());
+		const wchar_t* cStrValue = reinterpret_cast<const wchar_t*>(srcFieldValuePtr.PtrZ());
+	
+		cpix_Field toField;
+		// FIXME: Assumption that Config() is compatible with cpix config is ugly
+		cpix_Field_initialize( &toField, cStrName, cStrValue,
+							   srcField.Config() );
+
+		CleanupStack::PopAndDestroy(srcFieldValue);
+		CleanupStack::PopAndDestroy(srcFieldName);
+        SearchServerHelper::CheckCpixErrorL(&toField, KErrCannotCreateDocumentField);
+		
+		cpix_Field_setBoost( &toField, srcField.Boost() ); 
+		SearchServerHelper::CheckCpixErrorL(&toField, KErrCannotCreateDocumentField);
+		
+		cpix_Document_add(doc, ( &toField ));
+		if (cpix_Failed( doc ))
+			{
+			cpix_Field_release(&toField);
+			SearchServerHelper::LogErrorL(*doc->err_);
+			cpix_ClearError(doc);
+			User::Leave(KErrCannotCreateDocumentField);
+			}
+		}	
+
+	return doc;	
+	}
+
+// End of File
+