// ********************************************************************** // // Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef FREEZE_EVICTOR_I_H #define FREEZE_EVICTOR_I_H #include #include #include #include #include #include #include #include #include #include #include class DbTxn; namespace Freeze { class EvictorIBase; // // Helper class to prevent deactivation while the Evictor is in use // class DeactivateController : private IceUtil::Monitor { public: // // Prevents deactivation; the constructor raises // EvictorDeactivatedException if _deactivated or _deactivating is true. // class Guard { public: Guard(const DeactivateController&); ~Guard(); private: DeactivateController& _controller; }; DeactivateController(EvictorIBase*); // // Used mostly in asserts // bool deactivated() const; // // Returns true if this thread is supposed to do the deactivation and // call deactivationComplete() once done. // bool deactivate(); void deactivationComplete(); private: friend class Guard; EvictorIBase* _evictor; bool _deactivating; bool _deactivated; int _guardCount; }; class EvictorIBase : public virtual Evictor, public IceUtil::Monitor { public: virtual TransactionIPtr beforeQuery() = 0; virtual void setSize(Ice::Int); virtual Ice::Int getSize(); virtual Ice::ObjectPrx add(const Ice::ObjectPtr&, const Ice::Identity&); virtual Ice::ObjectPtr remove(const Ice::Identity&); virtual bool hasObject(const Ice::Identity&); virtual Ice::ObjectPtr locate(const Ice::Current&, Ice::LocalObjectPtr&); DeactivateController& deactivateController(); const Ice::CommunicatorPtr& communicator() const; const Ice::EncodingVersion& encoding() const; const SharedDbEnvPtr& dbEnv() const; const std::string& filename() const; bool deadlockWarning() const; Ice::Int trace() const; Ice::Int txTrace() const; void initialize(const Ice::Identity&, const std::string&, const Ice::ObjectPtr&); static void updateStats(Statistics&, IceUtil::Int64); static std::string defaultDb; static std::string indexPrefix; protected: EvictorIBase(const Ice::ObjectAdapterPtr&, const std::string&, DbEnv*, const std::string&, const FacetTypeMap&, const ServantInitializerPtr&, bool); virtual bool hasAnotherFacet(const Ice::Identity&, const std::string&) = 0; virtual Ice::ObjectPtr locateImpl(const Ice::Current&, Ice::LocalObjectPtr&) = 0; virtual void evict() = 0; std::vector allDbs() const; size_t _evictorSize; FacetTypeMap _facetTypes; DeactivateController _deactivateController; Ice::ObjectAdapterPtr _adapter; Ice::CommunicatorPtr _communicator; Ice::EncodingVersion _encoding; ServantInitializerPtr _initializer; SharedDbEnvPtr _dbEnv; std::string _filename; bool _createDb; Ice::Int _trace; Ice::Int _txTrace; bool _deadlockWarning; private: Ice::ObjectPtr _pingObject; }; typedef IceUtil::Handle EvictorIBasePtr; template class EvictorI : public EvictorIBase { public: virtual EvictorIteratorPtr getIterator(const std::string& facet, Ice::Int batchSize) { DeactivateController::Guard deactivateGuard(_deactivateController); TransactionIPtr tx = beforeQuery(); return new EvictorIteratorI(findStore(facet, false), tx, batchSize); } protected: EvictorI(const Ice::ObjectAdapterPtr& adapter, const std::string& envName, DbEnv* dbEnv, const std::string& filename, const FacetTypeMap& facetTypes, const ServantInitializerPtr& initializer, const std::vector& indices, bool createDb) : EvictorIBase(adapter, envName, dbEnv, filename, facetTypes, initializer, createDb) { std::string propertyPrefix = std::string("Freeze.Evictor.") + envName + '.' + filename; bool populateEmptyIndices = (_communicator->getProperties()-> getPropertyAsIntWithDefault(propertyPrefix + ".PopulateEmptyIndices", 0) != 0); // // Instantiate all Dbs in 2 steps: // (1) iterate over the indices and create ObjectStore with indices // (2) open ObjectStores without indices // std::vector dbs = allDbs(); // // Add default db in case it's not there // dbs.push_back(defaultDb); for(std::vector::const_iterator i = indices.begin(); i != indices.end(); ++i) { std::string facet = (*i)->facet(); typename StoreMap::iterator q = _storeMap.find(facet); if(q == _storeMap.end()) { // // New db // std::vector storeIndices; for(std::vector::const_iterator r = i; r != indices.end(); ++r) { if((*r)->facet() == facet) { storeIndices.push_back(*r); } } std::string facetType; FacetTypeMap::const_iterator ft = facetTypes.find(facet); if(ft != facetTypes.end()) { facetType = ft->second; } ObjectStore* store = new ObjectStore(facet, facetType,_createDb, this, storeIndices, populateEmptyIndices); _storeMap.insert(typename StoreMap::value_type(facet, store)); } } for(std::vector::iterator p = dbs.begin(); p != dbs.end(); ++p) { std::string facet = *p; if(facet == defaultDb) { facet = ""; } #if (defined(_MSC_VER) && (_MSC_VER >= 1600)) std::pair ir = _storeMap.insert(typename StoreMap::value_type(facet, static_cast*>(nullptr))); #else std::pair ir = _storeMap.insert(typename StoreMap::value_type(facet, 0)); #endif if(ir.second) { std::string facetType; FacetTypeMap::const_iterator ft = facetTypes.find(facet); if(ft != facetTypes.end()) { facetType = ft->second; } ir.first->second = new ObjectStore(facet, facetType, _createDb, this); } } } ObjectStore* findStore(const std::string& facet, bool createIt) { Lock sync(*this); ObjectStore* os = 0; typename StoreMap::const_iterator p = _storeMap.find(facet); if(p != _storeMap.end()) { os = (*p).second; } else if(createIt) { std::string facetType; typename FacetTypeMap::const_iterator q = _facetTypes.find(facet); if(q != _facetTypes.end()) { facetType = q->second; } os = new ObjectStore(facet, facetType, true, this); _storeMap.insert(typename StoreMap::value_type(facet, os)); } return os; } void closeDbEnv() { for(typename StoreMap::iterator p = _storeMap.begin(); p != _storeMap.end(); ++p) { delete (*p).second; } _dbEnv = 0; _initializer = 0; } typedef std::map*> StoreMap; StoreMap _storeMap; }; inline DeactivateController& EvictorIBase::deactivateController() { return _deactivateController; } inline const Ice::CommunicatorPtr& EvictorIBase::communicator() const { return _communicator; } inline const Ice::EncodingVersion& EvictorIBase::encoding() const { return _encoding; } inline const SharedDbEnvPtr& EvictorIBase::dbEnv() const { return _dbEnv; } inline bool EvictorIBase::deadlockWarning() const { return _deadlockWarning; } inline Ice::Int EvictorIBase::trace() const { return _trace; } // // Helper function // inline void checkIdentity(const Ice::Identity& ident) { if(ident.name.size() == 0) { throw Ice::IllegalIdentityException(__FILE__, __LINE__, ident); } } inline void checkServant(const Ice::ObjectPtr& servant) { if(servant == 0) { throw Ice::IllegalServantException(__FILE__, __LINE__, "cannot add null servant to Freeze Evictor"); } } } #endif