void TxnCtxt::jrnl_sync(JournalImpl* jc, timespec* timeout) { if (!jc || jc->is_txn_synced(getXid())) return; while (jc->get_wr_aio_evt_rem()) { if (jc->get_wr_events(timeout) == journal::jerrno::AIO_TIMEOUT && timeout) THROW_STORE_EXCEPTION(std::string("Error: timeout waiting for TxnCtxt::jrnl_sync()")); } }
/** * Record generic durable configuration */ void MessageStorePlugin::create(const broker::PersistableConfig& config) { if (config.getPersistenceId()) { THROW_STORE_EXCEPTION("Config item already created: " + config.getName()); } provider->second->create(config); }
/** * Record the existence of a durable exchange */ void MessageStorePlugin::create(const broker::PersistableExchange& exchange, const framing::FieldTable& args) { if (exchange.getPersistenceId()) { THROW_STORE_EXCEPTION("Exchange already created: " + exchange.getName()); } provider->second->create(exchange, args); }
/** * Enqueues a message, storing the message if it has not * been previously stored and recording that the given * message is on the given queue. * * Note: The operation is asynchronous so the return of this function does * not mean the operation is complete. */ void MessageStorePlugin::enqueue(broker::TransactionContext* ctxt, const boost::intrusive_ptr<broker::PersistableMessage>& msg, const broker::PersistableQueue& queue) { if (queue.getPersistenceId() == 0) { THROW_STORE_EXCEPTION("Queue not created: " + queue.getName()); } provider->second->enqueue(ctxt, msg, queue); }
/** * Appends content to a previously staged message */ void MessageStorePlugin::appendContent (const boost::intrusive_ptr<const broker::PersistableMessage>& msg, const std::string& data) { if (msg->getPersistenceId()) provider->second->appendContent(msg, data); else THROW_STORE_EXCEPTION("Cannot append content. Message not known to store!"); }
void TxnCtxt::begin(DbEnv* env, bool sync) { int err; try { err = env->txn_begin(0, &txn, 0); } catch (const DbException&) { txn = 0; throw; } if (err != 0) { std::ostringstream oss; oss << "Error: Env::txn_begin() returned error code: " << err; THROW_STORE_EXCEPTION(oss.str()); } if (sync) globalHolder = AutoScopedLock(new qpid::sys::Mutex::ScopedLock(globalSerialiser)); }
/** * Loads (a section) of content data for the specified * message (previously stored through a call to stage or * enqueue) into data. The offset refers to the content * only (i.e. an offset of 0 implies that the start of the * content should be loaded, not the headers or related * meta-data). */ void MessageStorePlugin::loadContent(const broker::PersistableQueue& queue, const boost::intrusive_ptr<const broker::PersistableMessage>& msg, std::string& data, uint64_t offset, uint32_t length) { if (msg->getPersistenceId()) provider->second->loadContent(queue, msg, data, offset, length); else THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!"); }
void TxnCtxt::sync() { if (loggedtx) { try { for (ipqItr i = impactedQueues.begin(); i != impactedQueues.end(); i++) jrnl_flush(static_cast<JournalImpl*>(*i)); if (preparedXidStorePtr) jrnl_flush(preparedXidStorePtr); for (ipqItr i = impactedQueues.begin(); i != impactedQueues.end(); i++) jrnl_sync(static_cast<JournalImpl*>(*i), &journal::jcntl::_aio_cmpl_timeout); if (preparedXidStorePtr) jrnl_sync(preparedXidStorePtr, &journal::jcntl::_aio_cmpl_timeout); } catch (const journal::jexception& e) { THROW_STORE_EXCEPTION(std::string("Error during txn sync: ") + e.what()); } } }
/** * Record the existence of a durable queue */ void MessageStorePlugin::create(broker::PersistableQueue& queue, const framing::FieldTable& args) { if (queue.getName().size() == 0) { QPID_LOG(error, "Cannot create store for empty (null) queue name - " "ignoring and attempting to continue."); return; } if (queue.getPersistenceId()) { THROW_STORE_EXCEPTION("Queue already created: " + queue.getName()); } provider->second->create(queue, args); }
void TxnCtxt::commitTxn(JournalImpl* jc, bool commit) { if (jc && loggedtx) { /* if using journal */ boost::intrusive_ptr<DataTokenImpl> dtokp(new DataTokenImpl); dtokp->addRef(); dtokp->set_external_rid(true); dtokp->set_rid(loggedtx->next()); try { if (commit) { jc->txn_commit(dtokp.get(), getXid()); sync(); } else { jc->txn_abort(dtokp.get(), getXid()); } } catch (const journal::jexception& e) { THROW_STORE_EXCEPTION(std::string("Error commit") + e.what()); } } }
/** * Request recovery of queue and message state; inherited from Recoverable */ void MessageStorePlugin::recover(broker::RecoveryManager& recoverer) { ExchangeMap exchanges; QueueMap queues; MessageMap messages; MessageQueueMap messageQueueMap; std::vector<std::string> xids; PreparedTransactionMap dtxMap; provider->second->recoverConfigs(recoverer); provider->second->recoverExchanges(recoverer, exchanges); provider->second->recoverQueues(recoverer, queues); provider->second->recoverBindings(recoverer, exchanges, queues); // Important to recover messages before transactions in the SQL-CLFS // case. If this becomes a problem, it may be possible to resolve it. // If in doubt please raise a jira and notify Steve Huston // <*****@*****.**>. provider->second->recoverMessages(recoverer, messages, messageQueueMap); provider->second->recoverTransactions(recoverer, dtxMap); // Enqueue msgs where needed. for (MessageQueueMap::const_iterator i = messageQueueMap.begin(); i != messageQueueMap.end(); ++i) { // Locate the message corresponding to the current message Id MessageMap::const_iterator iMsg = messages.find(i->first); if (iMsg == messages.end()) { std::ostringstream oss; oss << "No matching message trying to re-enqueue message " << i->first; THROW_STORE_EXCEPTION(oss.str()); } broker::RecoverableMessage::shared_ptr msg = iMsg->second; // Now for each queue referenced in the queue map, locate it // and re-enqueue the message. for (std::vector<QueueEntry>::const_iterator j = i->second.begin(); j != i->second.end(); ++j) { // Locate the queue corresponding to the current queue Id QueueMap::const_iterator iQ = queues.find(j->queueId); if (iQ == queues.end()) { std::ostringstream oss; oss << "No matching queue trying to re-enqueue message " << " on queue Id " << j->queueId; THROW_STORE_EXCEPTION(oss.str()); } // Messages involved in prepared transactions have their status // updated accordingly. First, though, restore a message that // is expected to be on a queue, including non-transacted // messages and those pending dequeue in a dtx. if (j->tplStatus != QueueEntry::ADDING) iQ->second->recover(msg); switch(j->tplStatus) { case QueueEntry::ADDING: dtxMap[j->xid]->enqueue(iQ->second, msg); break; case QueueEntry::REMOVING: dtxMap[j->xid]->dequeue(iQ->second, msg); break; default: break; } } } }