void Freeze::TransactionI::postCompletion(bool committed, bool deadlock) { // The order of assignment in this method is very important as // calling both the post completion callback and // Connection::clearTransaction may alter the transaction // reference count which checks _txn. { // // We synchronize here as _txn is checked (read) in the refcounting code // IceUtil::Mutex::Lock sync(_refCountMutex->mutex); _txn = 0; } if(_postCompletionCallback != 0) { PostCompletionCallbackPtr cb = _postCompletionCallback; _postCompletionCallback = 0; cb->postCompletion(committed, deadlock, _connection->dbEnv()); } ConnectionIPtr connection = _connection; _connection = 0; connection->clearTransaction(); // may release the last _refCount }
ConnectionIPtr IceInternal::DirectReference::getConnection(bool& comp) const { vector<EndpointIPtr> endpts = RoutableReference::getRoutedEndpoints(); applyOverrides(endpts); if(endpts.empty()) { endpts = _endpoints; // Endpoint overrides are already applied on these endpoints. } ConnectionIPtr connection = createConnection(endpts, comp); // // If we have a router, set the object adapter for this router // (if any) to the new connection, so that callbacks from the // router can be received over this new connection. // if(getRouterInfo()) { connection->setAdapter(getRouterInfo()->getAdapter()); } assert(connection); return connection; }
Freeze::MapHelperI::MapHelperI(const ConnectionIPtr& connection, const string& dbName, const string& key, const string& value, const KeyCompareBasePtr& keyCompare, const vector<MapIndexBasePtr>& indices, bool createDb) : _connection(connection), _db(connection->dbEnv()->getSharedMapDb(dbName, key, value, keyCompare, indices, createDb)), _dbName(dbName), _trace(connection->trace()) { for(vector<MapIndexBasePtr>::const_iterator p = indices.begin(); p != indices.end(); ++p) { const MapIndexBasePtr& indexBase = *p; assert(indexBase->_impl != 0); assert(indexBase->_communicator == _connection->communicator()); assert(indexBase->_map == 0); #ifdef NDEBUG _indices.insert(IndexMap::value_type(indexBase->name(), indexBase)); #else bool inserted = _indices.insert(IndexMap::value_type(indexBase->name(), indexBase)).second; assert(inserted); #endif indexBase->_map = this; } _connection->registerMap(this); }
ConnectionIPtr IceInternal::FixedReference::getConnection(bool& compress) const { vector<ConnectionIPtr> filteredConns = filterConnections(_fixedConnections); if(filteredConns.empty()) { NoEndpointException ex(__FILE__, __LINE__); ex.proxy = ""; // No stringified representation for fixed proxies throw ex; } ConnectionIPtr connection = filteredConns[0]; assert(connection); connection->throwException(); // Throw in case our connection is already destroyed. compress = connection->endpoint()->compress(); return connection; }
void CommunicatorFlushBatch::flushConnection(const ConnectionIPtr& con) { class FlushBatch : public OutgoingAsyncBase { public: FlushBatch(const CommunicatorFlushBatchPtr& outAsync, const InstancePtr& instance, InvocationObserver& observer) : OutgoingAsyncBase(outAsync->getCommunicator(), instance, outAsync->getOperation(), __dummyCallback, 0), _outAsync(outAsync), _observer(observer) { } virtual bool sent() { _childObserver.detach(); _outAsync->check(false); return false; } virtual bool completed(const Exception& ex) { _childObserver.failed(ex.ice_name()); _childObserver.detach(); _outAsync->check(false); return false; } private: virtual InvocationObserver& getObserver() { return _observer; } const CommunicatorFlushBatchPtr _outAsync; InvocationObserver& _observer; }; { IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor); ++_useCount; } try { con->flushAsyncBatchRequests(new FlushBatch(this, _instance, _observer)); } catch(const LocalException&) { check(false); throw; } }
// // Methods from ConnectionI.StartCallback // void IceInternal::OutgoingConnectionFactory::ConnectCallback::connectionStartCompleted(const ConnectionIPtr& connection) { if(_observer) { _observer->detach(); } connection->activate(); _factory->finishGetConnection(_connectors, *_iter, connection, this); }
AsyncStatus ProxyFlushBatchAsync::invokeRemote(const ConnectionIPtr& connection, bool compress, bool) { if(_batchRequestNum == 0) { if(sent()) { return static_cast<AsyncStatus>(AsyncStatusSent | AsyncStatusInvokeSentCallback); } else { return AsyncStatusSent; } } _cachedConnection = connection; return connection->sendAsyncRequest(ICE_SHARED_FROM_THIS, compress, false, _batchRequestNum); }
bool operator()(ConnectionIPtr p) const { return p->endpoint()->secure(); }
bool operator()(ConnectionIPtr p) const { return p->endpoint()->datagram(); }
ConnectionIPtr IceInternal::IndirectReference::getConnection(bool& comp) const { ConnectionIPtr connection; while(true) { vector<EndpointIPtr> endpts = RoutableReference::getRoutedEndpoints(); bool cached = false; if(endpts.empty() && _locatorInfo) { const IndirectReferencePtr self = const_cast<IndirectReference*>(this); endpts = _locatorInfo->getEndpoints(self, _locatorCacheTimeout, cached); } applyOverrides(endpts); try { connection = createConnection(endpts, comp); assert(connection); } catch(const NoEndpointException& ex) { throw ex; // No need to retry if there's no endpoints. } catch(const LocalException& ex) { if(!getRouterInfo()) { assert(_locatorInfo); // COMPILERFIX: Braces needed to prevent BCB from causing Reference refCount from // being decremented twice when loop continues. { const IndirectReferencePtr self = const_cast<IndirectReference*>(this); _locatorInfo->clearCache(self); } if(cached) { // COMPILERFIX: Braces needed to prevent BCB from causing TraceLevels refCount from // being decremented twice when loop continues. { TraceLevelsPtr traceLevels = getInstance()->traceLevels(); if(traceLevels->retry >= 2) { Trace out(getInstance()->initializationData().logger, traceLevels->retryCat); out << "connection to cached endpoints failed\n" << "removing endpoints from cache and trying one more time\n" << ex; } } continue; } } throw; } break; } // // If we have a router, set the object adapter for this router // (if any) to the new connection, so that callbacks from the // router can be received over this new connection. // if(getRouterInfo()) { connection->setAdapter(getRouterInfo()->getAdapter()); } assert(connection); return connection; }
int Freeze::MapIndexI::untypedCount(const Key& k, const ConnectionIPtr& connection) const { Dbt dbKey; initializeInDbt(k, dbKey); #if (DB_VERSION_MAJOR <= 4) // // When we have a custom-comparison function, Berkeley DB returns // the key on-disk (when it finds one). We disable this behavior: // (ref Oracle SR 5925672.992) // dbKey.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); #else // // In DB 5.x we can not set DB_DBT_PARTIAL in the key Dbt, // when using DB_SET, we must resize the Dbt key param to hold enought // space or Dbc::get fails with DB_BUFFER_SMALL. // dbKey.set_flags(DB_DBT_USERMEM); dbKey.set_ulen(static_cast<u_int32_t>(k.size())); #endif Dbt dbValue; dbValue.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); int result = 0; DbTxn* txn = connection->dbTxn(); try { for(;;) { Dbc* dbc = 0; try { // // Move to the first record // _db->cursor(txn, &dbc, 0); bool found = (dbc->get(&dbKey, &dbValue, DB_SET) == 0); if(found) { db_recno_t count = 0; dbc->count(&count, 0); result = static_cast<int>(count); } Dbc* toClose = dbc; dbc = 0; toClose->close(); break; // for (;;) } catch(const DbDeadlockException&) { if(dbc != 0) { try { dbc->close(); } catch(const DbDeadlockException&) { if(txn != 0) { throw; } else { // // Ignored // } } } if(connection->deadlockWarning()) { Warning out(connection->communicator()->getLogger()); out << "Deadlock in Freeze::MapIndexI::untypedCount while searching \"" << _dbName << "\""; } if(txn != 0) { throw; } // // Otherwise retry // } catch(...) { if(dbc != 0) { try { dbc->close(); } catch(const DbDeadlockException&) { if(txn != 0) { throw; } else { // // Ignored // } } } throw; } } } catch(const DbDeadlockException& dx) { throw DeadlockException(__FILE__, __LINE__, dx.what(), connection->currentTransaction()); } catch(const DbException& dx) { throw DatabaseException(__FILE__, __LINE__, dx.what()); } return result; }
AsyncStatus ProxyFlushBatch::send(const ConnectionIPtr& connection, bool, bool) { _cachedConnection = connection; return connection->flushAsyncBatchRequests(this); }
AsyncStatus OutgoingAsync::send(const ConnectionIPtr& connection, bool compress, bool response) { _cachedConnection = connection; return connection->sendAsyncRequest(this, compress, response); }
void CommunicatorFlushBatchAsync::flushConnection(const ConnectionIPtr& con) { class FlushBatch : public OutgoingAsyncBase { public: FlushBatch(const CommunicatorFlushBatchAsyncPtr& outAsync, const InstancePtr& instance, InvocationObserver& observer) : OutgoingAsyncBase(instance), _outAsync(outAsync), _observer(observer) { } virtual bool sent() { _childObserver.detach(); _outAsync->check(false); return false; } virtual bool exception(const Exception& ex) { _childObserver.failed(ex.ice_id()); _childObserver.detach(); _outAsync->check(false); return false; } virtual InvocationObserver& getObserver() { return _observer; } virtual bool handleSent(bool, bool) { return false; } virtual bool handleException(const Ice::Exception&) { return false; } virtual bool handleResponse(bool) { return false; } virtual void handleInvokeSent(bool, OutgoingAsyncBase*) const { assert(false); } virtual void handleInvokeException(const Ice::Exception&, OutgoingAsyncBase*) const { assert(false); } virtual void handleInvokeResponse(bool, OutgoingAsyncBase*) const { assert(false); } private: const CommunicatorFlushBatchAsyncPtr _outAsync; InvocationObserver& _observer; }; { Lock sync(_m); ++_useCount; } try { OutgoingAsyncBasePtr flushBatch = ICE_MAKE_SHARED(FlushBatch, ICE_SHARED_FROM_THIS, _instance, _observer); int batchRequestNum = con->getBatchRequestQueue()->swap(flushBatch->getOs()); if(batchRequestNum == 0) { flushBatch->sent(); } else { con->sendAsyncRequest(flushBatch, false, false, batchRequestNum); } } catch(const LocalException&) { check(false); throw; } }
Freeze::MapIndexI::MapIndexI(const ConnectionIPtr& connection, MapDb& db, DbTxn* txn, bool createDb, const MapIndexBasePtr& index) : _index(index) { assert(txn != 0); _db.reset(new Db(connection->dbEnv()->getEnv(), 0)); _db->set_flags(DB_DUP | DB_DUPSORT); u_int32_t flags = 0; if(createDb) { flags = DB_CREATE; } _dbName = db.dbName() + "." + _index->name(); _db->set_app_private(this); if(index->compareEnabled()) { _db->set_bt_compare(&customIndexCompare); } Ice::PropertiesPtr properties = connection->communicator()->getProperties(); string propPrefix = "Freeze.Map." + _dbName + "."; int btreeMinKey = properties->getPropertyAsInt(propPrefix + "BtreeMinKey"); if(btreeMinKey > 2) { if(connection->trace() >= 1) { Trace out(connection->communicator()->getLogger(), "Freeze.Map"); out << "Setting \"" << _dbName << "\"'s btree minkey to " << btreeMinKey; } _db->set_bt_minkey(btreeMinKey); } bool checksum = properties->getPropertyAsInt(propPrefix + "Checksum") > 0; if(checksum) { if(connection->trace() >= 1) { Trace out(connection->communicator()->getLogger(), "Freeze.Map"); out << "Turning checksum on for \"" << _dbName << "\""; } _db->set_flags(DB_CHKSUM); } int pageSize = properties->getPropertyAsInt(propPrefix + "PageSize"); if(pageSize > 0) { if(connection->trace() >= 1) { Trace out(connection->communicator()->getLogger(), "Freeze.Map"); out << "Setting \"" << _dbName << "\"'s pagesize to " << pageSize; } _db->set_pagesize(pageSize); } if(connection->trace() >= 1) { Trace out(connection->communicator()->getLogger(), "Freeze.Map"); out << "Opening index \"" << _dbName << "\""; } // // Berkeley DB expects file paths to be UTF8 encoded. // _db->open(txn, nativeToUTF8(_dbName, getProcessStringConverter()).c_str(), 0, DB_BTREE, flags, FREEZE_DB_MODE); // // To populate empty indices // flags = DB_CREATE; db.associate(txn, _db.get(), callback, flags); // // Note: caller catch and translates exceptions // }
AsyncStatus OutgoingAsync::invokeRemote(const ConnectionIPtr& connection, bool compress, bool response) { _cachedConnection = connection; return connection->sendAsyncRequest(ICE_SHARED_FROM_THIS, compress, response, 0); }
Freeze::MapDb::MapDb(const ConnectionIPtr& connection, const string& dbName, const string& key, const string& value, const KeyCompareBasePtr& keyCompare, const vector<MapIndexBasePtr>& indices, bool createDb) : Db(connection->dbEnv()->getEnv(), 0), _communicator(connection->communicator()), _dbName(dbName), _trace(connection->trace()), _keyCompare(keyCompare) { if(_trace >= 1) { Trace out(_communicator->getLogger(), "Freeze.Map"); out << "opening Db \"" << _dbName << "\""; } Catalog catalog(connection, _catalogName); TransactionPtr tx = connection->currentTransaction(); bool ownTx = (tx == 0); for(;;) { try { if(ownTx) { tx = 0; tx = connection->beginTransaction(); } Catalog::iterator ci = catalog.find(_dbName); if(ci != catalog.end()) { if(ci->second.evictor) { throw DatabaseException(__FILE__, __LINE__, _dbName + " is an evictor database"); } _key = ci->second.key; _value = ci->second.value; checkTypes(key, value); } else { _key = key; _value = value; } set_app_private(this); if(_keyCompare->compareEnabled()) { set_bt_compare(&customCompare); } PropertiesPtr properties = _communicator->getProperties(); string propPrefix = "Freeze.Map." + _dbName + "."; int btreeMinKey = properties->getPropertyAsInt(propPrefix + "BtreeMinKey"); if(btreeMinKey > 2) { if(_trace >= 1) { Trace out(_communicator->getLogger(), "Freeze.Map"); out << "Setting \"" << _dbName << "\"'s btree minkey to " << btreeMinKey; } set_bt_minkey(btreeMinKey); } bool checksum = properties->getPropertyAsInt(propPrefix + "Checksum") > 0; if(checksum) { if(_trace >= 1) { Trace out(_communicator->getLogger(), "Freeze.Map"); out << "Turning checksum on for \"" << _dbName << "\""; } set_flags(DB_CHKSUM); } int pageSize = properties->getPropertyAsInt(propPrefix + "PageSize"); if(pageSize > 0) { if(_trace >= 1) { Trace out(_communicator->getLogger(), "Freeze.Map"); out << "Setting \"" << _dbName << "\"'s pagesize to " << pageSize; } set_pagesize(pageSize); } DbTxn* txn = getTxn(tx); u_int32_t flags = DB_THREAD; if(createDb) { flags |= DB_CREATE; } open(txn, Ice::nativeToUTF8(_communicator, _dbName).c_str(), 0, DB_BTREE, flags, FREEZE_DB_MODE); StringSeq oldIndices; StringSeq newIndices; size_t oldSize = 0; CatalogIndexList catalogIndexList(connection, _catalogIndexListName); if(createDb) { CatalogIndexList::iterator cil = catalogIndexList.find(_dbName); if(cil != catalogIndexList.end()) { oldIndices = cil->second; oldSize = oldIndices.size(); } } for(vector<MapIndexBasePtr>::const_iterator p = indices.begin(); p != indices.end(); ++p) { const MapIndexBasePtr& indexBase = *p; assert(indexBase->_impl == 0); assert(indexBase->_communicator == 0); indexBase->_communicator = connection->communicator(); auto_ptr<MapIndexI> indexI; try { indexI.reset(new MapIndexI(connection, *this, txn, createDb, indexBase)); } catch(const DbDeadlockException&) { throw; } catch(const DbException& dx) { string message = "Error while opening index \"" + _dbName + "." + indexBase->name() + "\": " + dx.what(); throw DatabaseException(__FILE__, __LINE__, message); } #ifndef NDEBUG bool inserted = #endif _indices.insert(IndexMap::value_type(indexBase->name(), indexI.get())).second; assert(inserted); indexBase->_impl = indexI.release(); if(createDb) { newIndices.push_back(indexBase->name()); oldIndices.erase(std::remove(oldIndices.begin(), oldIndices.end(), indexBase->name()), oldIndices.end()); } } if(ci == catalog.end()) { CatalogData catalogData; catalogData.evictor = false; catalogData.key = key; catalogData.value = value; catalog.put(Catalog::value_type(_dbName, catalogData)); } if(createDb) { // // Remove old indices and write the new ones // bool indexRemoved = false; for(StringSeq::const_iterator q = oldIndices.begin(); q != oldIndices.end(); ++q) { const string& index = *q; if(_trace >= 1) { Trace out(_communicator->getLogger(), "Freeze.Map"); out << "removing old index \"" << index << "\" on Db \"" << _dbName << "\""; } try { connection->removeMapIndex(_dbName, *q); indexRemoved = true; } catch(const IndexNotFoundException&) { // Ignored if(_trace >= 1) { Trace out(_communicator->getLogger(), "Freeze.Map"); out << "index \"" << index << "\" on Db \"" << _dbName << "\" does not exist"; } } } if(indexRemoved || oldSize != newIndices.size()) { if(newIndices.size() == 0) { catalogIndexList.erase(_dbName); if(_trace >= 1) { Trace out(_communicator->getLogger(), "Freeze.Map"); out << "Removed catalogIndexList entry for Db \"" << _dbName << "\""; } } else { catalogIndexList.put(CatalogIndexList::value_type(_dbName, newIndices)); if(_trace >= 1) { Trace out(_communicator->getLogger(), "Freeze.Map"); out << "Updated catalogIndexList entry for Db \"" << _dbName << "\""; } } } } if(ownTx) { tx->commit(); } break; // for(;;) } catch(const DbDeadlockException& dx) { if(ownTx) { if(connection->deadlockWarning()) { Warning out(connection->communicator()->getLogger()); out << "Deadlock in Freeze::MapDb::MapDb on Map \"" << _dbName << "\"; retrying ..."; } // // Ignored, try again // } else { throw DeadlockException(__FILE__, __LINE__, dx.what(), tx); } } catch(const DbException& dx) { if(ownTx) { try { tx->rollback(); } catch(...) { } } string message = "Error while opening Db \"" + _dbName + "\": " + dx.what(); throw DatabaseException(__FILE__, __LINE__, message); } catch(...) { if(ownTx && tx != 0) { try { tx->rollback(); } catch(...) { } } throw; } } }
void IceInternal::IncomingConnectionFactory::initialize(const string& oaName) { if(_instance->defaultsAndOverrides()->overrideTimeout) { const_cast<EndpointIPtr&>(_endpoint) = _endpoint->timeout(_instance->defaultsAndOverrides()->overrideTimeoutValue); } if(_instance->defaultsAndOverrides()->overrideCompress) { const_cast<EndpointIPtr&>(_endpoint) = _endpoint->compress(_instance->defaultsAndOverrides()->overrideCompressValue); } try { const_cast<TransceiverPtr&>(_transceiver) = _endpoint->transceiver(const_cast<EndpointIPtr&>(_endpoint)); if(_transceiver) { ConnectionIPtr connection = new ConnectionI(_adapter->getCommunicator(), _instance, _reaper, _transceiver, 0, _endpoint, _adapter); connection->start(0); _connections.insert(connection); } else { const_cast<AcceptorPtr&>(_acceptor) = _endpoint->acceptor(const_cast<EndpointIPtr&>(_endpoint), oaName); assert(_acceptor); _acceptor->listen(); dynamic_cast<ObjectAdapterI*>(_adapter.get())->getThreadPool()->initialize(this); } } catch(const Ice::Exception&) { if(_transceiver) { try { _transceiver->close(); } catch(const Ice::LocalException&) { // Ignore } } if(_acceptor) { try { _acceptor->close(); } catch(const Ice::LocalException&) { // Ignore } } _state = StateFinished; _connections.clear(); throw; } }
void IceInternal::IncomingConnectionFactory::message(ThreadPoolCurrent& current) { ConnectionIPtr connection; ThreadPoolMessage<IncomingConnectionFactory> msg(current, *this); { IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); ThreadPoolMessage<IncomingConnectionFactory>::IOScope io(msg); if(!io) { return; } if(_state >= StateClosed) { return; } else if(_state == StateHolding) { IceUtil::ThreadControl::yield(); return; } // // Reap closed connections // vector<Ice::ConnectionIPtr> cons; _reaper->swapConnections(cons); for(vector<Ice::ConnectionIPtr>::const_iterator p = cons.begin(); p != cons.end(); ++p) { _connections.erase(*p); } // // Now accept a new connection. // TransceiverPtr transceiver; try { transceiver = _acceptor->accept(); } catch(const SocketException& ex) { if(noMoreFds(ex.error)) { { Error out(_instance->initializationData().logger); out << "fatal error: can't accept more connections:\n" << ex << '\n' << _acceptor->toString(); } abort(); } // Ignore socket exceptions. return; } catch(const LocalException& ex) { // Warn about other Ice local exceptions. if(_warn) { Warning out(_instance->initializationData().logger); out << "connection exception:\n" << ex << '\n' << _acceptor->toString(); } return; } assert(transceiver); try { connection = new ConnectionI(_adapter->getCommunicator(), _instance, _reaper, transceiver, 0, _endpoint, _adapter); } catch(const LocalException& ex) { try { transceiver->close(); } catch(const Ice::LocalException&) { // Ignore. } if(_warn) { Warning out(_instance->initializationData().logger); out << "connection exception:\n" << ex << '\n' << _acceptor->toString(); } return; } _connections.insert(connection); } assert(connection); connection->start(this); }