summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/socketengine.h57
-rw-r--r--src/commands/cmd_stats.cpp15
-rw-r--r--src/socketengine.cpp32
-rw-r--r--src/socketengines/socketengine_epoll.cpp10
-rw-r--r--src/socketengines/socketengine_kqueue.cpp8
-rw-r--r--src/socketengines/socketengine_ports.cpp6
-rw-r--r--src/socketengines/socketengine_select.cpp6
7 files changed, 86 insertions, 48 deletions
diff --git a/include/socketengine.h b/include/socketengine.h
index d4d6c4c1c..6503ea293 100644
--- a/include/socketengine.h
+++ b/include/socketengine.h
@@ -230,6 +230,45 @@ class CoreExport EventHandler : public classbase
*/
class CoreExport SocketEngine
{
+ public:
+ /** Socket engine statistics: count of various events, bandwidth usage
+ */
+ class Statistics
+ {
+ mutable size_t indata;
+ mutable size_t outdata;
+ mutable time_t lastempty;
+
+ /** Reset the byte counters and lastempty if there wasn't a reset in this second.
+ */
+ void CheckFlush() const;
+
+ public:
+ /** Constructor, initializes member vars except indata and outdata because those are set to 0
+ * in CheckFlush() the first time Update() or GetBandwidth() is called.
+ */
+ Statistics() : lastempty(0), TotalEvents(0), ReadEvents(0), WriteEvents(0), ErrorEvents(0) { }
+
+ /** Increase the counters for bytes sent/received in this second.
+ * @param len_in Bytes received, 0 if updating number of bytes written.
+ * @param len_out Bytes sent, 0 if updating number of bytes read.
+ */
+ void Update(size_t len_in, size_t len_out);
+
+ /** Get data transfer statistics.
+ * @param kbitspersec_in Filled with incoming traffic in this second in kbit/s.
+ * @param kbitspersec_out Filled with outgoing traffic in this second in kbit/s.
+ * @param kbitspersec_total Filled with total traffic in this second in kbit/s.
+ */
+ void CoreExport GetBandwidth(float& kbitpersec_in, float& kbitpersec_out, float& kbitpersec_total) const;
+
+ unsigned long TotalEvents;
+ unsigned long ReadEvents;
+ unsigned long WriteEvents;
+ unsigned long ErrorEvents;
+ };
+
+ private:
/** Reference table, contains all current handlers
**/
std::vector<EventHandler*> ref;
@@ -244,11 +283,9 @@ class CoreExport SocketEngine
int MAX_DESCRIPTORS;
- size_t indata;
- size_t outdata;
- time_t lastempty;
-
- void UpdateStats(size_t len_in, size_t len_out);
+ /** Socket engine statistics: count of various events, bandwidth usage
+ */
+ Statistics stats;
virtual void OnSetEvent(EventHandler* eh, int old_mask, int new_mask) = 0;
void SetEventMask(EventHandler* eh, int value);
@@ -267,12 +304,6 @@ class CoreExport SocketEngine
}
public:
-
- unsigned long TotalEvents;
- unsigned long ReadEvents;
- unsigned long WriteEvents;
- unsigned long ErrorEvents;
-
/** Constructor.
* The constructor transparently initializes
* the socket engine which the ircd is using.
@@ -494,9 +525,9 @@ public:
*/
virtual void RecoverFromFork();
- /** Get data transfer statistics, kilobits per second in and out and total.
+ /** Get data transfer and event statistics
*/
- void GetStats(float &kbitpersec_in, float &kbitpersec_out, float &kbitpersec_total);
+ const Statistics& GetStats() const { return stats; }
/** Should we ignore the error in errno?
* Checks EAGAIN and WSAEWOULDBLOCK
diff --git a/src/commands/cmd_stats.cpp b/src/commands/cmd_stats.cpp
index 617f0a320..afcbe01e6 100644
--- a/src/commands/cmd_stats.cpp
+++ b/src/commands/cmd_stats.cpp
@@ -181,11 +181,14 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
ServerInstance->XLines->InvokeStats("E",223,user,results);
break;
case 'E':
- results.push_back("249 "+user->nick+" :Total events: "+ConvToStr(ServerInstance->SE->TotalEvents));
- results.push_back("249 "+user->nick+" :Read events: "+ConvToStr(ServerInstance->SE->ReadEvents));
- results.push_back("249 "+user->nick+" :Write events: "+ConvToStr(ServerInstance->SE->WriteEvents));
- results.push_back("249 "+user->nick+" :Error events: "+ConvToStr(ServerInstance->SE->ErrorEvents));
- break;
+ {
+ const SocketEngine::Statistics& stats = ServerInstance->SE->GetStats();
+ results.push_back("249 "+user->nick+" :Total events: "+ConvToStr(stats.TotalEvents));
+ results.push_back("249 "+user->nick+" :Read events: "+ConvToStr(stats.ReadEvents));
+ results.push_back("249 "+user->nick+" :Write events: "+ConvToStr(stats.WriteEvents));
+ results.push_back("249 "+user->nick+" :Error events: "+ConvToStr(stats.ErrorEvents));
+ break;
+ }
/* stats m (list number of times each command has been used, plus bytecount) */
case 'm':
@@ -209,7 +212,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
float kbitpersec_in, kbitpersec_out, kbitpersec_total;
char kbitpersec_in_s[30], kbitpersec_out_s[30], kbitpersec_total_s[30];
- ServerInstance->SE->GetStats(kbitpersec_in, kbitpersec_out, kbitpersec_total);
+ ServerInstance->SE->GetStats().GetBandwidth(kbitpersec_in, kbitpersec_out, kbitpersec_total);
snprintf(kbitpersec_total_s, 30, "%03.5f", kbitpersec_total);
snprintf(kbitpersec_out_s, 30, "%03.5f", kbitpersec_out);
diff --git a/src/socketengine.cpp b/src/socketengine.cpp
index 35fe5292f..ba3d84512 100644
--- a/src/socketengine.cpp
+++ b/src/socketengine.cpp
@@ -36,9 +36,6 @@ void EventHandler::SetFd(int FD)
SocketEngine::SocketEngine()
{
- TotalEvents = WriteEvents = ReadEvents = ErrorEvents = 0;
- lastempty = ServerInstance->Time();
- indata = outdata = 0;
CurrentSetSize = 0;
}
@@ -195,7 +192,7 @@ int SocketEngine::RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, s
{
int nbRecvd = recvfrom(fd->GetFd(), (char*)buf, len, flags, from, fromlen);
if (nbRecvd > 0)
- this->UpdateStats(nbRecvd, 0);
+ stats.Update(nbRecvd, 0);
return nbRecvd;
}
@@ -203,7 +200,7 @@ int SocketEngine::Send(EventHandler* fd, const void *buf, size_t len, int flags)
{
int nbSent = send(fd->GetFd(), (const char*)buf, len, flags);
if (nbSent > 0)
- this->UpdateStats(0, nbSent);
+ stats.Update(0, nbSent);
return nbSent;
}
@@ -211,7 +208,7 @@ int SocketEngine::Recv(EventHandler* fd, void *buf, size_t len, int flags)
{
int nbRecvd = recv(fd->GetFd(), (char*)buf, len, flags);
if (nbRecvd > 0)
- this->UpdateStats(nbRecvd, 0);
+ stats.Update(nbRecvd, 0);
return nbRecvd;
}
@@ -219,7 +216,7 @@ int SocketEngine::SendTo(EventHandler* fd, const void *buf, size_t len, int flag
{
int nbSent = sendto(fd->GetFd(), (const char*)buf, len, flags, to, tolen);
if (nbSent > 0)
- this->UpdateStats(0, nbSent);
+ stats.Update(0, nbSent);
return nbSent;
}
@@ -257,20 +254,27 @@ void SocketEngine::RecoverFromFork()
{
}
-void SocketEngine::UpdateStats(size_t len_in, size_t len_out)
+void SocketEngine::Statistics::Update(size_t len_in, size_t len_out)
{
- if (lastempty != ServerInstance->Time())
+ CheckFlush();
+ indata += len_in;
+ outdata += len_out;
+}
+
+void SocketEngine::Statistics::CheckFlush() const
+{
+ // Reset the in/out byte counters if it has been more than a second
+ time_t now = ServerInstance->Time();
+ if (lastempty != now)
{
- lastempty = ServerInstance->Time();
+ lastempty = now;
indata = outdata = 0;
}
- indata += len_in;
- outdata += len_out;
}
-void SocketEngine::GetStats(float &kbitpersec_in, float &kbitpersec_out, float &kbitpersec_total)
+void SocketEngine::Statistics::GetBandwidth(float& kbitpersec_in, float& kbitpersec_out, float& kbitpersec_total) const
{
- UpdateStats(0, 0); /* Forces emptying of the values if its been more than a second */
+ CheckFlush();
float in_kbit = indata * 8;
float out_kbit = outdata * 8;
kbitpersec_total = ((in_kbit + out_kbit) / 1024);
diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp
index 7ee01b2cc..39cc60606 100644
--- a/src/socketengines/socketengine_epoll.cpp
+++ b/src/socketengines/socketengine_epoll.cpp
@@ -185,7 +185,7 @@ int EPollEngine::DispatchEvents()
int i = epoll_wait(EngineHandle, &events[0], events.size(), 1000);
ServerInstance->UpdateTime();
- TotalEvents += i;
+ stats.TotalEvents += i;
for (int j = 0; j < i; j++)
{
@@ -202,14 +202,14 @@ int EPollEngine::DispatchEvents()
if (ev.events & EPOLLHUP)
{
- ErrorEvents++;
+ stats.ErrorEvents++;
eh->HandleEvent(EVENT_ERROR, 0);
continue;
}
if (ev.events & EPOLLERR)
{
- ErrorEvents++;
+ stats.ErrorEvents++;
/* Get error number */
socklen_t codesize = sizeof(int);
int errcode;
@@ -235,7 +235,7 @@ int EPollEngine::DispatchEvents()
SetEventMask(eh, mask);
if (ev.events & EPOLLIN)
{
- ReadEvents++;
+ stats.ReadEvents++;
eh->HandleEvent(EVENT_READ);
if (eh != GetRef(ev.data.fd))
// whoa! we got deleted, better not give out the write event
@@ -243,7 +243,7 @@ int EPollEngine::DispatchEvents()
}
if (ev.events & EPOLLOUT)
{
- WriteEvents++;
+ stats.WriteEvents++;
eh->HandleEvent(EVENT_WRITE);
}
}
diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp
index c51789b29..0a9a0a399 100644
--- a/src/socketengines/socketengine_kqueue.cpp
+++ b/src/socketengines/socketengine_kqueue.cpp
@@ -207,7 +207,7 @@ int KQueueEngine::DispatchEvents()
if (i < 0)
return i;
- TotalEvents += i;
+ stats.TotalEvents += i;
for (int j = 0; j < i; j++)
{
@@ -223,13 +223,13 @@ int KQueueEngine::DispatchEvents()
if (kev.flags & EV_EOF)
{
- ErrorEvents++;
+ stats.ErrorEvents++;
eh->HandleEvent(EVENT_ERROR, kev.fflags);
continue;
}
if (filter == EVFILT_WRITE)
{
- WriteEvents++;
+ stats.WriteEvents++;
/* When mask is FD_WANT_FAST_WRITE or FD_WANT_SINGLE_WRITE,
* we set a one-shot write, so we need to clear that bit
* to detect when it set again.
@@ -240,7 +240,7 @@ int KQueueEngine::DispatchEvents()
}
else if (filter == EVFILT_READ)
{
- ReadEvents++;
+ stats.ReadEvents++;
SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK);
eh->HandleEvent(EVENT_READ);
}
diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp
index 226f59f04..e1fcc0e6c 100644
--- a/src/socketengines/socketengine_ports.cpp
+++ b/src/socketengines/socketengine_ports.cpp
@@ -148,7 +148,7 @@ int PortsEngine::DispatchEvents()
if (ret == -1)
return -1;
- TotalEvents += nget;
+ stats.TotalEvents += nget;
unsigned int i;
for (i = 0; i < nget; i++)
@@ -175,14 +175,14 @@ int PortsEngine::DispatchEvents()
port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh);
if (portev_events & POLLRDNORM)
{
- ReadEvents++;
+ stats.ReadEvents++;
eh->HandleEvent(EVENT_READ);
if (eh != GetRef(fd))
continue;
}
if (portev_events & POLLWRNORM)
{
- WriteEvents++;
+ stats.WriteEvents++;
eh->HandleEvent(EVENT_WRITE);
}
}
diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp
index 7aaa7aaf7..be380cb46 100644
--- a/src/socketengines/socketengine_select.cpp
+++ b/src/socketengines/socketengine_select.cpp
@@ -135,7 +135,7 @@ int SelectEngine::DispatchEvents()
if (has_error)
{
- ErrorEvents++;
+ stats.ErrorEvents++;
socklen_t codesize = sizeof(int);
int errcode = 0;
@@ -148,7 +148,7 @@ int SelectEngine::DispatchEvents()
if (has_read)
{
- ReadEvents++;
+ stats.ReadEvents++;
SetEventMask(ev, ev->GetEventMask() & ~FD_READ_WILL_BLOCK);
ev->HandleEvent(EVENT_READ);
if (ev != GetRef(i))
@@ -157,7 +157,7 @@ int SelectEngine::DispatchEvents()
if (has_write)
{
- WriteEvents++;
+ stats.WriteEvents++;
int newmask = (ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE));
this->OnSetEvent(ev, ev->GetEventMask(), newmask);
SetEventMask(ev, newmask);