1 | /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
---|
2 | /* |
---|
3 | * Copyright (C) 2013-2014 HUBzero Foundation, LLC |
---|
4 | * |
---|
5 | * Author: Leif Delgass <ldelgass@purdue.edu> |
---|
6 | */ |
---|
7 | |
---|
8 | #include <cstring> |
---|
9 | #include <errno.h> |
---|
10 | #include <sys/time.h> |
---|
11 | #include <sys/times.h> |
---|
12 | #include <sys/types.h> |
---|
13 | #include <sys/stat.h> |
---|
14 | #include <fcntl.h> |
---|
15 | #include <unistd.h> |
---|
16 | #include <md5.h> |
---|
17 | |
---|
18 | #include <iostream> |
---|
19 | #include <string> |
---|
20 | #include <sstream> |
---|
21 | |
---|
22 | #include "Stats.h" |
---|
23 | #include "RenderServer.h" |
---|
24 | #include "Trace.h" |
---|
25 | |
---|
26 | using namespace GeoVis; |
---|
27 | |
---|
28 | /* |
---|
29 | * Session information: |
---|
30 | * - Name of render server |
---|
31 | * - Process ID |
---|
32 | * - Hostname where server is running |
---|
33 | * - Stop date of session |
---|
34 | * - Stop date of session in seconds |
---|
35 | * - Number of data sets loaded from client |
---|
36 | * - Number of data bytes total loaded from client |
---|
37 | * - Number of frames returned |
---|
38 | * - Number of bytes total returned (in frames) |
---|
39 | * - Number of commands received |
---|
40 | * - Total elapsed time of all commands |
---|
41 | * - Total elapsed time of session |
---|
42 | * - Exit code of vizserver |
---|
43 | * - User time |
---|
44 | * - System time |
---|
45 | * - User time of children |
---|
46 | * - System time of children |
---|
47 | */ |
---|
48 | int |
---|
49 | GeoVis::serverStats(const Stats& stats, int code) |
---|
50 | { |
---|
51 | struct timeval now; |
---|
52 | /* Get ending time. */ |
---|
53 | gettimeofday(&now, NULL); |
---|
54 | double session_time = CVT2SECS(now) - CVT2SECS(stats.start); |
---|
55 | |
---|
56 | std::ostringstream oss; |
---|
57 | char buf[BUFSIZ]; |
---|
58 | gethostname(buf, BUFSIZ-1); |
---|
59 | buf[BUFSIZ-1] = '\0'; |
---|
60 | std::string hostname(buf); |
---|
61 | strcpy(buf, ctime(&now.tv_sec)); |
---|
62 | buf[strlen(buf) - 1] = '\0'; |
---|
63 | std::string date(buf); |
---|
64 | |
---|
65 | oss << "render_stop " |
---|
66 | << "renderer geovis " |
---|
67 | << "pid " << getpid() << " " |
---|
68 | << "host " << hostname << " " |
---|
69 | << "date {" << date << "} " |
---|
70 | << "date_secs " << now.tv_sec << " " |
---|
71 | << "num_data_sets " << stats.nDataSets << " " |
---|
72 | << "data_set_bytes " << stats.nDataBytes << " " |
---|
73 | << "num_frames " << stats.nFrames << " " |
---|
74 | << "frame_bytes " << stats.nFrameBytes << " " |
---|
75 | << "num_commands " << stats.nCommands << " " |
---|
76 | << "cmd_time " << stats.cmdTime << " " |
---|
77 | << "session_time " << session_time << " " |
---|
78 | << "status " << code << " "; |
---|
79 | |
---|
80 | { |
---|
81 | long clocksPerSec = sysconf(_SC_CLK_TCK); |
---|
82 | double clockRes = 1.0 / clocksPerSec; |
---|
83 | struct tms tms; |
---|
84 | |
---|
85 | memset(&tms, 0, sizeof(tms)); |
---|
86 | times(&tms); |
---|
87 | |
---|
88 | oss << "utime " << (tms.tms_utime * clockRes) << " " |
---|
89 | << "stime " << (tms.tms_stime * clockRes) << " " |
---|
90 | << "cutime " << (tms.tms_cutime * clockRes) << " " |
---|
91 | << "cstime " << (tms.tms_cstime * clockRes) << " "; |
---|
92 | } |
---|
93 | |
---|
94 | oss << std::endl; |
---|
95 | |
---|
96 | int fd = getStatsFile(); |
---|
97 | std::string ostr = oss.str(); |
---|
98 | int result = writeToStatsFile(fd, ostr.c_str(), ostr.length()); |
---|
99 | close(fd); |
---|
100 | return result; |
---|
101 | } |
---|
102 | |
---|
103 | int |
---|
104 | GeoVis::getStatsFile(const char *key) |
---|
105 | { |
---|
106 | char fileName[33]; |
---|
107 | md5_state_t state; |
---|
108 | md5_byte_t digest[16]; |
---|
109 | |
---|
110 | if (key == NULL || g_statsFile >= 0) { |
---|
111 | return g_statsFile; |
---|
112 | } |
---|
113 | |
---|
114 | std::ostringstream keyStream; |
---|
115 | keyStream << key << " " |
---|
116 | << getpid(); |
---|
117 | std::string keystr = keyStream.str(); |
---|
118 | TRACE("Stats file key: '%s'", keystr.c_str()); |
---|
119 | |
---|
120 | md5_init(&state); |
---|
121 | md5_append(&state, (const md5_byte_t *)keystr.c_str(), keystr.length()); |
---|
122 | md5_finish(&state, digest); |
---|
123 | for (int i = 0; i < 16; i++) { |
---|
124 | sprintf(fileName + i * 2, "%02x", digest[i]); |
---|
125 | } |
---|
126 | |
---|
127 | std::ostringstream oss; |
---|
128 | oss << STATSDIR << "/" << fileName; |
---|
129 | g_statsFile = open(oss.str().c_str(), O_EXCL | O_CREAT | O_WRONLY, 0600); |
---|
130 | if (g_statsFile < 0) { |
---|
131 | ERROR("can't open \"%s\": %s", fileName, strerror(errno)); |
---|
132 | return -1; |
---|
133 | } |
---|
134 | return g_statsFile; |
---|
135 | } |
---|
136 | |
---|
137 | int |
---|
138 | GeoVis::writeToStatsFile(int fd, const char *s, size_t length) |
---|
139 | { |
---|
140 | if (fd >= 0) { |
---|
141 | ssize_t numWritten; |
---|
142 | |
---|
143 | numWritten = write(fd, s, length); |
---|
144 | if (numWritten == (ssize_t)length) { |
---|
145 | close(dup(fd)); |
---|
146 | } |
---|
147 | } |
---|
148 | return 0; |
---|
149 | } |
---|