searchengine/cpix/cpix/inc/private/idxdbmgr.h
changeset 0 671dee74050a
child 23 d4d56f5e7c55
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/searchengine/cpix/cpix/inc/private/idxdbmgr.h	Mon Apr 19 14:40:16 2010 +0300
@@ -0,0 +1,594 @@
+/*
+* 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: 
+*
+*/
+
+#ifndef CPIX_IDXDBMGR_H
+#define CPIX_IDXDBMGR_H
+
+
+#include "fwdtypes.h"
+#include "initparams.h"
+#include "cpixsynctools.h"
+
+
+namespace Cpix
+{
+    /**
+     * An extra indirection introduced in order to be able to
+     * implement transparent release of resources while they are
+     * inactive.
+     */
+    class IIdxDbInfo
+    {
+    private:
+        int              refCount_;
+        IIdxDb         * ptr_;
+        mutable long     lastAccessedSecs_;
+
+    public:
+        void incRefCount();
+
+        /**
+         * @return true if refcount has dropped to zero.
+         */
+        void decRefCount();
+
+        /**
+         * @return the reference count
+         */
+        int refCount() const;
+
+        /**
+         * Plain getting the ptr_ member.
+         */
+        IIdxDb * ptr() const;
+
+        
+        /**
+         * Getting the ptr_ member for use: lastAccessedSecs_ is updated.
+         */
+        IIdxDb * getPtrForUse() const;
+        
+
+        /**
+         * Forcefully sets the ptr_ to the given value. If the current
+         * ptr_ is not NULL, it destroys it, giving no consideration
+         * to flush information, as they will be discarded anyway.
+         */
+        void setPtr(IIdxDb * ptr);
+
+
+        /**
+         * Releases the currently held pointer, that is returns it
+         * while setting the ptr_ member to NULL. Does not destroy
+         * anything. Ownership of previous ptr_ value passes to
+         * caller.
+         */
+        IIdxDb * release();
+    
+
+        /** OBS
+         * destroys the ptr, possibly resetting the refCount_
+         * /
+        void destroy(bool resetRefCount);
+        */
+        
+        void restIfIdle(long   nowSec,
+                        size_t maxIdleSec);
+
+        IIdxDbInfo();
+
+        long lastAccessedSecs() const;
+
+        void dbgDumpState(size_t idx) const;
+
+    private:
+        void accessed() const;
+    };
+
+
+    /**
+     * This singleton class provides mapping between base application
+     * types and their containing index database paths, as well as
+     * mapping between index database paths and existing IdxDb
+     * instances.
+     *
+     * The mapping between base application types and their index
+     * database paths are persisted to a CPix specific configuration
+     * file.
+     */
+    class IdxDbMgr
+    {
+    private:
+        //
+        // private members
+        //
+
+        typedef std::string QualBaseAppClass;
+        typedef std::string IdxDbPath;
+
+        typedef std::pair<std::string, IdxDbHndl> PathAndHndl;
+
+        std::map<QualBaseAppClass, PathAndHndl>   qbacs_;
+        std::vector<IIdxDbInfo>                   idxDbs_;
+
+        // MultiIdxDb instances are stored here, see comments for
+        // createMultiIdxDbHndl() for further details
+        std::vector<IIdxDbInfo>                   multiIdxDbs_;
+
+        std::string                               cpixDir_;
+        std::string                               regFilePath_;
+
+        size_t                                    maxIdleSec_;
+
+        static IdxDbMgr *                         instance_;
+        static const char                         delimiter_;
+
+        Cpt::Mutex                                mutex_;
+
+        Version                                   version_;
+
+        InitParams                                initParams_;
+
+
+        // each housekeeping increases this counter
+        typedef size_t                            HousekeepCounter;
+        HousekeepCounter                          housekeepCounter_;
+        
+        // IIdxDb instances scheduled for deferred deletions are
+        // tracked with this structure
+        struct IIdxDbToDestroy
+        {
+            IIdxDb                              * ptr_;
+            HousekeepCounter                      housekeepCounter_;
+
+            IIdxDbToDestroy(IIdxDb           * ptr,
+                            HousekeepCounter   housekeepCounter);
+        };
+
+        std::list<IIdxDbToDestroy>                idxDbsToDestroy_;
+
+
+    public:
+        //
+        // public operations
+        //
+
+        /**
+         * Must be called once, before anything else doing with
+         * indexes is ever attempted. IdxDbMgr::instance does not
+         * function propertly unless this method has been called at
+         * least once. Calling it multiple times does not hurt.
+         */
+        static void init(InitParams & initParams);
+
+
+
+        static IdxDbMgr * instance();
+
+
+        /**
+         * Scraps all existing databases if they are not in
+         * use. Thread-safe (locks the singleton instance).
+         */
+        static void scrapAll();
+        
+
+        static void shutdownAll();
+
+
+        /**
+         * (Re-)defines an index on a qualified base app class. The
+         * qualified base app class - associated index database path
+         * must be defined already (cf. defineVolume).
+         *
+         * Thread safe.
+         */
+        IdxDbHndl create(const char   * qualBaseAppClass);
+
+        
+        /**
+         * Qualified base app class is a base app class specification
+         * that is qualified with a volume id. General pattern for
+         * qualified base app class string: "@VOLUMEID:BASEAPPCLASS".
+         *
+         * Thread neutral - has nothing to do with the singleton
+         * instance.
+         *
+         * @param domainSelector a generic domain selection string
+         * (basically, a list of app classes)
+         *
+         * @return true if the given string is a single qualified base
+         * app class
+         */
+        static bool isQualBaseAppClass(const char * domainSelector);
+
+        /**
+         * Thread neutral - has nothing to do with the singleton
+         * instance.
+         *
+         * @param appClass a single app class
+         * 
+         * @param baseAppClass - may be qualified or unqualified
+         *
+         * @return true if the request for the app class should
+         * involve using the physical volume associated to
+         * baseAppClass
+         */
+        static bool matchAppClass(const char * appClass,
+                                  const char * baseAppClass);
+
+
+        /**
+         * Thread neutral - has nothing to do with the singleton
+         * instance.
+         *
+         * @param domainSelector is a string that can specify somehow
+         * what sort of indexes / volumes / documents we want to
+         * access. It is a non-empty list of app classes
+         * 
+         * @param baseAppClass - may be qualified or unqualified
+         *
+         * @return true if the domain selector string mandates
+         * involving the physical volume associated to baseAppClass to
+         * be used
+         */
+        static bool match(const char * domainSelector,
+                          const char * baseAppClass);
+
+
+
+        /**
+         * Gets a next version number. IdxDb and MultiIdxDb instances
+         * are upgrading their version numbers as they go through
+         * changes.
+         */
+        Version getNextVersion();
+
+
+        /**
+         * Gets a valid handle for a base app class. Thread-safe.
+         *
+         * @param baseAppClass may be qualified or unqualified
+         * (qualification means volume id prefix).
+         *
+         * @param allowMultiSearch if true then searching multiple
+         * indexes in vase of unqualified base app class is allowed
+         * (coming through cpix_IdxSearcher API object).
+         */
+        IdxDbHndl getHndl(const char * domainSelector,
+                          bool         allowMultiSearch);
+
+        
+        /**
+         * Gets the pointer for the handle, the pointer must be
+         * non-NULL. Thread-safe.
+         */
+        IIdxDb * get(IdxDbHndl handle);
+
+        
+        /**
+         * Increments the refcount for the handle (does not create
+         * anything). Thread-safe.
+         */
+        void incRefHndl(IdxDbHndl handle);
+
+
+        /**
+         * Releases the resources associated to handle (decrements
+         * refcount and releases if 0). Thread-safe.
+         */
+        void releaseHndl(IdxDbHndl handle);
+
+        
+        /**
+         * Defines a volume (physical index). Thread-safe.
+         *
+         * @param qualBaseAppClass new qualified base app class. This
+         * qualified base app class must not be already associated
+         * with a different path (redefinition to the same path is
+         * allowed (= NOP)).
+         *
+         * @param indexDbPath the path to associated to the q base app
+         * class
+         */
+        void defineVolume(const char * qualBaseAppClass,
+                          const char * indexDbPath);
+
+        /**
+         * Undefines the volume associated to
+         * defineVolume. Thread-safe.
+         */
+        void undefineVolume(const char * qualBaseAppClass);
+
+        
+        /**
+         * Perform regular housekeeping tasks. Thread-safe.
+         */
+        void doHousekeepingOnAll();
+
+
+        /**
+         * In case of some very serious problem, we dump state.
+         */
+        void dbgDumpState();
+
+        
+        /**
+         * @return the "clHitsPageSize" initial parameter CPix core
+         * was initialized with (stored by the singleton).
+         */
+        size_t getClHitsPageSize() const;
+        
+
+        /**
+         * Creates (or recreates) an empty clucene index in the given
+         * clucene directory.
+         *
+         * NOTE: Differs from RecreateFsCpixIdx that the path argument
+         * here is a clucene dir, not CPix dir.
+         *
+         * @param cluceneDir the directory to create (or recreate) the
+         * empty clucene index in. It must NOT be NULL. The path must
+         * exist.
+         */
+        static void IdxDbMgr::RecreateFsClIdx(const char * cluceneDir);
+
+
+        /**
+         * Tries to open the physical index residing at the given
+         * path.
+         *
+         * @param cpixDir the directory containing the index database
+         *
+         * NOTE cpix index is not the same as clucene index
+         * directory. cpix index directory may contain zero, one or
+         * more clucene index directories and some other marker
+         * files. See idxdbdelta.h
+         *
+         * @throws whatever (LuceneError, ...)
+         */
+        static void OpenFsIdx(const char * cpixDir);
+
+
+        /**
+         * Physically destroys the index database under the path, and
+         * tries to re-create an empty one in its place.
+         *
+         * NOTE: differs from RecreateFsClIdx that the path argument
+         * here is CPix dir, not clucene dir.
+         *
+         * @param cpixDir the path to the directory in which the cpix
+         * index resides. This path is assumed to be there, but it is
+         * not necessary for any files underneath to be there.
+         *
+         * Cpix index is not the same as clucene index directory. cpix
+         * index directory may contain zero, one or more clucene index
+         * directories and some other marker files. See idxdbdelta.h
+         *
+         * @throws some exception in case of failure
+         */
+        static void RecreateFsCpixIdx(const char * cpixDir);
+
+    private:
+        //
+        // private methods
+        //
+
+        /**
+         * Private constructor.
+         *
+         * @param ip InitParams instance if given by the client at
+         * cpix_init() time (or a default one created by IIdxDb::init()).
+         */
+        IdxDbMgr(InitParams & ip);
+
+
+        ~IdxDbMgr();
+        
+        
+        /**
+         * Performs couple of sanity checks wrt. to the base app class
+         * and the intented idxDbPath, whether they collide with some
+         * existing entries.
+         *
+         * Not thread-safe.
+         *
+         * @param succeeded pointer to the boolean telling the result
+         * of the check. May be NULL, in which case this method throws
+         * an exception in case of error (if not NULL, problem is
+         * reported on std out and boolean value is set).
+         */
+        void sanityCheck(const std::string & baseAppClass,
+                         const std::string & idxDbPath,
+                         bool              * succeeded);
+
+
+        /**
+         * Thread-neutral, does not use singleton instance.
+         *
+         * @param the path to make sure that it exists
+         *
+         * @param recreate if true, then any existing index db will be
+         * re-created. Otherwise, it will be (re-)created only if it
+         * does not exist or corrupt (cannot be opened).
+         */
+        static void InitFileSystem(const char * path,
+                                   bool         recreate);
+
+
+        /**
+         * Creates an actual IdxDb instance first initializeing the
+         * file system (InitFileSystem()) and then adding the created
+         * instance to its allocated slot (handle). If InitFileSystem()
+         * fails, it will remove the erroneous / stale
+         * qualBaseAppClass - path association from the registry and
+         * persists it.
+         *
+         * Not thread-safe
+         *
+         * @param handle the handle to get the instance for
+         *
+         * @param path the designated path for the index database
+         *
+         * @param recreate whether to recreate the index in the case
+         * it is there
+         *
+         * @param qualBaseAppClass the qualified base app class
+         * identifying the volume (physical index) we are about to
+         * create an IdxDb for
+         */
+        void createIdxDbInstance(IdxDbHndl    handle,
+                                 const char * path,
+                                 bool         recreate,
+                                 const char * qualBaseAppClass);
+        
+        /**
+         * Not thread-safe.
+         *
+         * Veneer function to the overloaded version (figures out
+         * path, qbac all by itself).
+         */
+        void createIdxDbInstance(IdxDbHndl    handle,
+                                 bool         recreate);
+
+
+        /**
+         * Loads the registry. Not thread-safe.
+         */
+        void loadReg();
+        
+
+        /**
+         * Persists the registry. Not thread-safe.
+         */
+        void storeReg();
+
+
+        /**
+         * Generates the automatic index database path for a qualified
+         * base app class. Not thread-safe.
+         */
+        std::string getAutomaticIdxDbPath(const char * qualBaseAppClass);
+
+
+        /**
+         * Thread-neutral, nothing to do with instance.
+         * 
+         * @param qualBaseAppClass a qualified base app class
+         *
+         * @return the pointer within the original C string where the
+         * base app class part starts, right after the volume
+         * identifier and delimiter.
+         */
+        static const char * getBaseAppClassPart(const char * qualBaseAppClass);
+
+        
+        friend class MultiIdxDb;
+
+        /**
+         * Increments the reference count of the IdxDb instance at a
+         * given handle. Does not create / instantiate anything.
+         *
+         * Not thread-safe, the caller must lock on "this". This
+         * private method is called from MultiIdxDb (friend), but that
+         * function is called by this instance (from defineVolume())
+         * which already locks this instance. Sorry for the coupling
+         * (but one unnecessary recursive locks less this way).
+         */
+        void incIdxDbRefCount(IdxDbHndl    handle);
+
+
+        /**
+         * Creates a new MultiIdxDb instance and a handler for
+         * it. MultiIdxDb instances are NOT reused accross different
+         * clients, even if they ask for the same, they get different
+         * instances. (The inferred IdxDb instance will be shared
+         * though.)
+         *
+         * The reason we handle multi idx db instance through handles
+         * is that cpix_IdxSearch API object this way only refers to
+         * handle-s that may resolve to an IdxDb* or a MultiIdxDb*.
+         *
+         * Since instances are not reused, once a MultiIdxDb instance
+         * is destroyed, it's handle can be reused. These handles are
+         * stored in a different vector.
+         *
+         * The difference between handles that resolve to IdxDb* and
+         * the ones that resolve to MultiIdxDb* is that the latter
+         * ones have their highest bits set as a marker.
+         *
+         * Not thread-safe, the caller must lock on this.
+         */
+        IdxDbHndl createMultiIdxDbHndl(const char * domainSelector);
+
+
+        /**
+         * @returns if the given hande is a handle for multi idx db
+         * (highest bit is set).
+         */
+        static bool isMultiIdxDbHndl(IdxDbHndl handle);
+
+
+        /**
+         * Checks handle sanity. Out of bounds indexing (handle is an
+         * index to one of two vectors) is checked. If the handle is
+         * referring to multi idx db pointers, then the pointer must
+         * be non-NULL. If the handle refers to IdxDb* instances then
+         * it's up to the allowUndefinedIdxDb argument to allow it or
+         * not.
+         *
+         * throws CpixExc on insanity
+         */
+        void checkHndlSanity(IdxDbHndl handle,
+                             bool      allowUndefinedIdxDb);
+
+
+
+        /**
+         * During undefineVolume we unregister an index, but we can't
+         * immediately delete the corresponding pointer otherwise we
+         * risk a crash if there is a job still using it.
+         *
+         * Thus we do deferred deletion. This method allows scheduling
+         * an IIdxDb* instance for deletion, it will be a housekeeping
+         * that will destroy it.
+         */
+        void scheduleForDeletion(IIdxDb * toDestroy);
+
+
+        /**
+         * ALL IIdxDb instances scheduled for deletion (by a call to
+         * scheduleForDeletion()) are deleted here.
+         */
+        void deleteAllScheduledIdxDbs();
+
+
+        /**
+         * Some IIdxDb instance scheduled for deletion (by a call to
+         * scheduleForDeletion()) are deleted here. There is a
+         * heuristical decision about when a scheduled instance can be
+         * actually deleted.
+         */
+        void deleteSomeScheduledIdxDbs();
+
+    }; // class
+
+
+
+}
+
+#endif