Vault
4.1
|
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