forked from trygve-isaacson/code-vault
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvmessagehandler.cpp
More file actions
146 lines (115 loc) · 6.15 KB
/
vmessagehandler.cpp
File metadata and controls
146 lines (115 loc) · 6.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
Copyright c1997-2014 Trygve Isaacson. All rights reserved.
This file is part of the Code Vault version 4.1
http://www.bombaydigital.com/
License: MIT. See LICENSE.md in the Vault top level directory.
*/
#include "vmessagehandler.h"
#include "vexception.h"
#include "vsocketthread.h"
#include "vclientsession.h"
// VMessageHandler ------------------------------------------------------------
VMessageHandlerFactoryMap* VMessageHandler::gFactoryMap = NULL;
// static
VMessageHandler* VMessageHandler::get(VMessagePtr m, VServer* server, VClientSessionPtr session, VSocketThread* thread) {
VMessageHandlerFactory* factory = (*(VMessageHandler::mapInstance()))[m->getMessageID()];
if (factory == NULL)
return NULL;
else
return factory->createHandler(m, server, session, thread);
}
// static
void VMessageHandler::registerHandlerFactory(VMessageID messageID, VMessageHandlerFactory* factory) {
(*(VMessageHandler::mapInstance()))[messageID] = factory;
}
// static
VMessageHandlerFactoryMap* VMessageHandler::mapInstance() {
// We assume that creation occurs during static init, so we don't have to
// be concerned about multiple threads stepping on each other during create.
if (gFactoryMap == NULL)
gFactoryMap = new VMessageHandlerFactoryMap();
return gFactoryMap;
}
VMessageHandler::VMessageHandler(const VString& name, VMessagePtr m, VServer* server, VClientSessionPtr session, VSocketThread* thread, const VMessageFactory* messageFactory, VMutex* mutex)
: mName(name)
, mLoggerName(VSTRING_ARGS("vault.messages.VMessageHandler.%d", m->getMessageID()))
, mMessage(m)
, mServer(server)
, mSession(session)
, mThread(thread)
, mMessageFactory(messageFactory)
, mStartTime(/*now*/)
, mLocker(mutex, VSTRING_FORMAT("VMessageHandler(%s)", name.chars()))
, mUnblockTime(/*now*/) // Note that if we block locking the mutex, mUnblockTime - mStartTime will indicate how long we were blocked here.
, mSessionName() // initialized below if session or thread was supplied
{
if (session != nullptr) { // A message handler doesn't need to be related to a session object.
mSessionName = session->getName();
} else if (mThread != NULL) { // Thread may be null for test case or other purposes.
mSessionName = mThread->getName();
}
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()));
}
VMessageHandler::~VMessageHandler() {
try {
VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageHandlerLifecycleLevel, VSTRING_FORMAT("[%s] %s@0x%08X destructed.", mSessionName.chars(), mName.chars(), this));
} catch (...) {} // prevent exception from propagating
mServer = NULL;
mThread = NULL;
mMessageFactory = NULL;
}
VMessagePtr VMessageHandler::getMessage(VMessageID messageID) {
VMessagePtr message = mMessageFactory->instantiateNewMessage(messageID);
return message;
}
void VMessageHandler::logMessageContentRecord(const VString& details, VNamedLoggerPtr logger) const {
if (logger == nullptr)
logger = this->_getMessageContentRecordLogger();
if (logger != nullptr)
logger->log(VMessage::kMessageContentRecordingLevel, details);
}
void VMessageHandler::logMessageContentFields(const VString& details, VNamedLoggerPtr logger) const {
if (logger == nullptr)
logger = this->_getMessageContentFieldsLogger();
if (logger != nullptr)
logger->log(VMessage::kMessageContentFieldsLevel, details);
}
void VMessageHandler::logMessageDetailsFields(const VString& details, VNamedLoggerPtr logger) const {
if (logger == nullptr)
logger = VLogger::findNamedLoggerForLevel(mLoggerName, VMessage::kMessageTrafficDetailsLevel);
if (logger != nullptr)
logger->log(VMessage::kMessageTrafficDetailsLevel, details);
}
void VMessageHandler::logProcessMessageStart() const {
VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageHandlerDispatchLevel, VSTRING_FORMAT("%s start.", mName.chars()));
}
void VMessageHandler::logProcessMessageEnd() const {
VDuration elapsed = VInstant(/*now*/) - mStartTime;
if (mUnblockTime == mStartTime) {
VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageHandlerDispatchLevel, VSTRING_FORMAT("%s end. (Elapsed time: %s)", mName.chars(), elapsed.getDurationString().chars()));
} else {
// We were evidently blocked for at least 1ms during construction, waiting for the mutex to be released.
// If the duration of blocked time exceeded a certain amount, emit this at info level so it is even more visible.
VDuration blockedTime = mUnblockTime - mStartTime;
VLOGGER_NAMED_LEVEL(mLoggerName, (blockedTime > 25 * VDuration::MILLISECOND()) ? VLoggerLevel::INFO : (int)VMessage::kMessageHandlerDispatchLevel, // strangely, gcc gave linker error w/o int cast
VSTRING_FORMAT("%s end. (Elapsed time: %s. Blocked for: %s.)", mName.chars(), elapsed.getDurationString().chars(), blockedTime.getDurationString().chars()));
}
}
void VMessageHandler::_logDetailedDispatch(const VString& dispatchInfo) const {
VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageHandlerDetailLevel, dispatchInfo);
}
void VMessageHandler::_logMessageContentRecord(const VString& contentInfo) const {
VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageContentRecordingLevel, contentInfo);
}
void VMessageHandler::_logMessageContentFields(const VString& contentInfo) const {
VLOGGER_NAMED_LEVEL(mLoggerName, VMessage::kMessageContentFieldsLevel, contentInfo);
}
void VMessageHandler::_logMessageContentHexDump(const VString& info, const Vu8* buffer, Vs64 length) const {
VLOGGER_NAMED_HEXDUMP(mLoggerName, VMessage::kMessageContentHexDumpLevel, info, buffer, length);
}
VNamedLoggerPtr VMessageHandler::_getMessageContentRecordLogger() const {
return VLogger::findNamedLoggerForLevel(mLoggerName, VMessage::kMessageContentRecordingLevel);
}
VNamedLoggerPtr VMessageHandler::_getMessageContentFieldsLogger() const {
return VLogger::findNamedLoggerForLevel(mLoggerName, VMessage::kMessageContentFieldsLevel);
}