Vault  4.1
vmessagehandler.cpp
00001 /*
00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved.
00003 This file is part of the Code Vault version 4.1
00004 http://www.bombaydigital.com/
00005 License: MIT. See LICENSE.md in the Vault top level directory.
00006 */
00007 
00008 #include "vmessagehandler.h"
00009 
00010 #include "vexception.h"
00011 #include "vsocketthread.h"
00012 #include "vclientsession.h"
00013 
00014 // VMessageHandler ------------------------------------------------------------
00015 
00016 VMessageHandlerFactoryMap* VMessageHandler::gFactoryMap = NULL;
00017 
00018 // static
00019 VMessageHandler* VMessageHandler::get(VMessagePtr m, VServer* server, VClientSessionPtr session, VSocketThread* thread) {
00020     VMessageHandlerFactory* factory = (*(VMessageHandler::mapInstance()))[m->getMessageID()];
00021 
00022     if (factory == NULL)
00023         return NULL;
00024     else
00025         return factory->createHandler(m, server, session, thread);
00026 }
00027 
00028 // static
00029 void VMessageHandler::registerHandlerFactory(VMessageID messageID, VMessageHandlerFactory* factory) {
00030     (*(VMessageHandler::mapInstance()))[messageID] = factory;
00031 }
00032 
00033 // static
00034 VMessageHandlerFactoryMap* VMessageHandler::mapInstance() {
00035     // We assume that creation occurs during static init, so we don't have to
00036     // be concerned about multiple threads stepping on each other during create.
00037 
00038     if (gFactoryMap == NULL)
00039         gFactoryMap = new VMessageHandlerFactoryMap();
00040 
00041     return gFactoryMap;
00042 }
00043 
00044 VMessageHandler::VMessageHandler(const VString& name, VMessagePtr m, VServer* server, VClientSessionPtr session, VSocketThread* thread, const VMessageFactory* messageFactory, VMutex* mutex)
00045     : mName(name)
00046     , mLoggerName(VSTRING_ARGS("vault.messages.VMessageHandler.%d", m->getMessageID()))
00047     , mMessage(m)
00048     , mServer(server)
00049     , mSession(session)
00050     , mThread(thread)
00051     , mMessageFactory(messageFactory)
00052     , mStartTime(/*now*/)
00053     , mLocker(mutex, VSTRING_FORMAT("VMessageHandler(%s)", name.chars()))
00054     , mUnblockTime(/*now*/) // Note that if we block locking the mutex, mUnblockTime - mStartTime will indicate how long we were blocked here.
00055     , mSessionName() // initialized below if session or thread was supplied
00056     {
00057 
00058     if (session != nullptr) { // A message handler doesn't need to be related to a session object.
00059         mSessionName = session->getName();
00060     } else if (mThread != NULL) { // Thread may be null for test case or other purposes.
00061         mSessionName = mThread->getName();
00062     }
00063 
00064     VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageHandlerLifecycleLevel, VSTRING_FORMAT("[%s] %s@0x%08X for message ID=%d constructed.", mSessionName.chars(), mName.chars(), this, (int) m->getMessageID()));
00065 }
00066 
00067 VMessageHandler::~VMessageHandler() {
00068     try {
00069         VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageHandlerLifecycleLevel, VSTRING_FORMAT("[%s] %s@0x%08X destructed.", mSessionName.chars(), mName.chars(), this));
00070     } catch (...) {} // prevent exception from propagating
00071 
00072     mServer = NULL;
00073     mThread = NULL;
00074     mMessageFactory = NULL;
00075 }
00076 
00077 VMessagePtr VMessageHandler::getMessage(VMessageID messageID) {
00078     VMessagePtr message = mMessageFactory->instantiateNewMessage(messageID);
00079     return message;
00080 }
00081 
00082 void VMessageHandler::logMessageContentRecord(const VString& details, VNamedLoggerPtr logger) const {
00083     if (logger == nullptr)
00084         logger = this->_getMessageContentRecordLogger();
00085 
00086     if (logger != nullptr)
00087         logger->log(VMessage::kMessageContentRecordingLevel, details);
00088 }
00089 
00090 void VMessageHandler::logMessageContentFields(const VString& details, VNamedLoggerPtr logger) const {
00091     if (logger == nullptr)
00092         logger = this->_getMessageContentFieldsLogger();
00093 
00094     if (logger != nullptr)
00095         logger->log(VMessage::kMessageContentFieldsLevel, details);
00096 }
00097 
00098 void VMessageHandler::logMessageDetailsFields(const VString& details, VNamedLoggerPtr logger) const {
00099     if (logger == nullptr)
00100         logger = VLogger::findNamedLoggerForLevel(mLoggerName, VMessage::kMessageTrafficDetailsLevel);
00101 
00102     if (logger != nullptr)
00103         logger->log(VMessage::kMessageTrafficDetailsLevel, details);
00104 }
00105 
00106 void VMessageHandler::logProcessMessageStart() const {
00107     VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageHandlerDispatchLevel, VSTRING_FORMAT("%s start.", mName.chars()));
00108 }
00109 
00110 void VMessageHandler::logProcessMessageEnd() const {
00111     VDuration elapsed = VInstant(/*now*/) - mStartTime;
00112     if (mUnblockTime == mStartTime) {
00113         VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageHandlerDispatchLevel, VSTRING_FORMAT("%s end. (Elapsed time: %s)", mName.chars(), elapsed.getDurationString().chars()));
00114     } else {
00115         // We were evidently blocked for at least 1ms during construction, waiting for the mutex to be released.
00116         // If the duration of blocked time exceeded a certain amount, emit this at info level so it is even more visible.
00117         VDuration blockedTime = mUnblockTime - mStartTime;
00118         VLOGGER_NAMED_LEVEL(mLoggerName, (blockedTime > 25 * VDuration::MILLISECOND()) ? VLoggerLevel::INFO : (int)VMessage::kMessageHandlerDispatchLevel, // strangely, gcc gave linker error w/o int cast
00119                               VSTRING_FORMAT("%s end. (Elapsed time: %s. Blocked for: %s.)", mName.chars(), elapsed.getDurationString().chars(), blockedTime.getDurationString().chars()));
00120     }
00121 }
00122 
00123 void VMessageHandler::_logDetailedDispatch(const VString& dispatchInfo) const {
00124     VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageHandlerDetailLevel, dispatchInfo);
00125 }
00126 
00127 void VMessageHandler::_logMessageContentRecord(const VString& contentInfo) const {
00128     VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageContentRecordingLevel, contentInfo);
00129 }
00130 
00131 void VMessageHandler::_logMessageContentFields(const VString& contentInfo) const {
00132     VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageContentFieldsLevel, contentInfo);
00133 }
00134 
00135 void VMessageHandler::_logMessageContentHexDump(const VString& info, const Vu8* buffer, Vs64 length) const {
00136     VLOGGER_NAMED_HEXDUMP(mLoggerName, VMessage::kMessageContentHexDumpLevel, info, buffer, length);
00137 }
00138 
00139 VNamedLoggerPtr VMessageHandler::_getMessageContentRecordLogger() const {
00140     return VLogger::findNamedLoggerForLevel(mLoggerName, VMessage::kMessageContentRecordingLevel);
00141 }
00142 
00143 VNamedLoggerPtr VMessageHandler::_getMessageContentFieldsLogger() const {
00144     return VLogger::findNamedLoggerForLevel(mLoggerName, VMessage::kMessageContentFieldsLevel);
00145 }
00146 

Copyright ©1997-2014 Trygve Isaacson. All rights reserved. This documentation was generated with Doxygen.