Beispiel #1
0
 void onPubSubMessage(
     const TcpConnectionPtr& connectionPtr,
     const MessagePtr& messagePtr,
     Timestamp) {
     const PubSubMessage& message
         = *dynamic_cast<PubSubMessage*>(messagePtr.get());
     counters_.incrementInBoundMessage();
     switch(message.op()) {
     case Op::PUB:
         distributePublish(
             string(message.topic().data()), string(message.content().data())
         );
         break;
     case Op::SUB:
         doSubscribe(connectionPtr, string(message.topic().data()));
         break;
     case Op::UNSUB:
         doUnsubscribe(connectionPtr, string(message.topic().data()));
         break;
     default:
         LOG(ERROR) << "Unsupported message op: " << message.op();
         connectionPtr->shutdown();
         break;
     }
 }
Beispiel #2
0
 void onConnection(const TcpConnectionPtr& conn) {
     if (conn->connected()) {
         connectionCount_.increment();
         conn->setContext(ConnectionContext());
         ConnectionContext* connectionContext
             = boost::any_cast<ConnectionContext>(conn->getMutableContext());
         EntryPtr entry(new Entry(conn));
         localConnectionBuckets_.get()->back().insert(entry);
         WeakEntryPtr weakEntry(entry);
         connectionContext->weakEntry_ = weakEntry;
     } else {
         connectionCount_.decrement();
         const ConnectionContext& connectionContext
             = boost::any_cast<const ConnectionContext&>(conn->getContext());
         const ConnectionSubscription& connSub = connectionContext.subscription_;
         // subtle: doUnsubscribe will erase *it, so increase before calling.
         for (auto it = connSub.begin(); it != connSub.end();) {
             doUnsubscribe(conn, *it++);
         }
     }
 }
void EventManager<T>::temporary_processEventQueue(AbsTime forceCompletionBy) {
	AbsTime startTime = AbsTime::now();
	SILOG(task,insane," >>> Processing events.");

	// swaps to allow people to keep adding new events
	typename EventList::NodeIterator processingList(mUnprocessed);

	// The events are swapped first to guarantee that listeners are at least as up-to-date as events.
	// Events can be delayed, but we cannot allow any lost subscriptions/unsubscriptions.

	{
		typename ListenerRequestList::NodeIterator procListeners(mListenerRequests);

		const ListenerRequest *req;
		while ((req = procListeners.next()) != NULL) {
			if (req->subscription) {
				SILOG(task,debug," >>>\tDoing subscription listener "<< req->listenerId << " for event " << req->eventId << " (" << req->onlyPrimary <<  ").");
				doSubscribeId(*req);
			} else {
				SILOGNOCR(task,debug," >>>\t");
				if (req->notifyListener) {
					SILOGNOCR(task,debug,"Notifying");
				}
				SILOG(task,debug,"UNSUBSCRIBED listener " << req->listenerId << ".");
				doUnsubscribe(req->listenerId, req->notifyListener);
			}
		}
	}

	if (SILOGP(task,insane)){
		SILOG(task,insane,"==== All Event Subscribers for " << (intptr_t)this << " ====");
		typename PrimaryListenerMap::const_iterator priIter =
			mListeners.begin();
		while (priIter != mListeners.end()) {
			SILOG(task,insane,"  ID " << (*priIter).first << ":");
			PartiallyOrderedListenerList *primaryLists =
				&((*priIter).second->first);
			SecondaryListenerMap *secondaryMap =
				&((*priIter).second->second);

			for (int i = 0; i < NUM_EVENTORDER; i++) {
				ListenerList *currentList = &(primaryLists->get(i));
				for (typename ListenerList::const_iterator iter = currentList->begin();
						iter != currentList->end(); ++iter) {
					SILOG(task,insane," \t"
						"[" << (i==MIDDLE?'=':i<MIDDLE?'*':'/') << "] " <<
						(*iter).second);
				}
			}

			typename SecondaryListenerMap::const_iterator secIter;
			secIter = secondaryMap->begin();
			while (secIter != secondaryMap->end()) {
				SILOG(task,insane,"\tSec ID " << (*secIter).first << ":");
				for (int i = 0; i < NUM_EVENTORDER; i++) {
					ListenerList *currentList = &((*secIter).second->get(i));
					for (typename ListenerList::const_iterator iter = currentList->begin();
							iter != currentList->end(); ++iter) {
						SILOG(task,insane," \t\t"
							"[" << (i==MIDDLE?'=':i<MIDDLE?'*':'/') << "] " <<
							(*iter).second);
					}
				}
				++secIter;
			}
			++priIter;
		}
		SILOG(task,insane,"==== ---------------------------------- ====");
	}

	EventPtr *evTemp;
	int numProcessed = 0;

	while ((evTemp = processingList.next())!=NULL) {
		EventPtr ev (*evTemp);
		++numProcessed;

		typename PrimaryListenerMap::iterator priIter =
			mListeners.find(ev->getId().mPriId);
		if (priIter == mListeners.end()) {
			// FIXME: Should this ever happen?
			SILOG(task,warning," >>>\tWARNING: No listeners for type " <<
                  "event type " << ev->getId().mPriId);
			continue;
		}

		PartiallyOrderedListenerList *primaryLists =
			&((*priIter).second->first);
		SecondaryListenerMap *secondaryMap =
			&((*priIter).second->second);

		typename SecondaryListenerMap::iterator secIter;
		secIter = secondaryMap->find(ev->getId().mSecId);

        bool cancel = false;
        EventHistory eventHistory=EVENT_UNHANDLED;
		// Call once per event order.
		for (int i = 0; i < NUM_EVENTORDER && cancel == false; i++) {
			SILOG(task,debug," >>>\tFiring " << ev << ": " << ev->getId() <<
                  " [order " << i << "]");
			ListenerList *currentList = &(primaryLists->get(i));
			if (!currentList->empty())
				eventHistory=EVENT_HANDLED;
			if (callAllListeners(ev, currentList, forceCompletionBy)) {
				cancel = cancel || true;
			}

			if (secIter != secondaryMap->end() &&
					!(*secIter).second->get(i).empty()) {
				currentList = &((*secIter).second->get(i));
				if (!currentList->empty())
					eventHistory=EVENT_HANDLED;

				if (callAllListeners(ev, currentList, forceCompletionBy)) {
					cancel = cancel || true;
				}
				// all listeners may have returned false.
				// cleanUp(secondaryMap, secIter);
				// secIter = secondaryMap->find(ev->getId().mSecId);
			}

			if (cancel) {
				SILOG(task,debug," >>>\tCancelling " << ev->getId());
			}
		}
		if (secIter != secondaryMap->end()) {
			cleanUp(secondaryMap, secIter);
		}

        if (cancel) eventHistory=EVENT_CANCELED;
        (*ev)(eventHistory);
		SILOG(task,debug," >>>\tFinished " << ev->getId());
	}

	if (mEventCV) {
		mPendingEvents -= numProcessed;
	}

	AbsTime finishTime = AbsTime::now();
	SILOG(task,insane, "**** Done processing events this round. " <<
          "Took " << (finishTime-startTime).toSeconds() <<
		" seconds.");
}