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 | * - Start date of session |
---|
34 | * - Start 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 | double start, finish; |
---|
52 | { |
---|
53 | struct timeval tv; |
---|
54 | |
---|
55 | /* Get ending time. */ |
---|
56 | gettimeofday(&tv, NULL); |
---|
57 | finish = CVT2SECS(tv); |
---|
58 | tv = stats.start; |
---|
59 | start = CVT2SECS(tv); |
---|
60 | } |
---|
61 | |
---|
62 | std::ostringstream oss; |
---|
63 | char buf[BUFSIZ]; |
---|
64 | gethostname(buf, BUFSIZ-1); |
---|
65 | buf[BUFSIZ-1] = '\0'; |
---|
66 | std::string hostname(buf); |
---|
67 | strcpy(buf, ctime(&stats.start.tv_sec)); |
---|
68 | buf[strlen(buf) - 1] = '\0'; |
---|
69 | std::string date(buf); |
---|
70 | |
---|
71 | oss << "render_stop " |
---|
72 | << "renderer geovis " |
---|
73 | << "pid " << getpid() << " " |
---|
74 | << "host " << hostname << " " |
---|
75 | << "date {" << date << "} " |
---|
76 | << "date_secs " << stats.start.tv_sec << " " |
---|
77 | << "num_data_sets " << stats.nDataSets << " " |
---|
78 | << "data_set_bytes " << stats.nDataBytes << " " |
---|
79 | << "num_frames " << stats.nFrames << " " |
---|
80 | << "frame_bytes " << stats.nFrameBytes << " " |
---|
81 | << "num_commands " << stats.nCommands << " " |
---|
82 | << "cmd_time " << stats.cmdTime << " " |
---|
83 | << "session_time " << (finish - start) << " " |
---|
84 | << "status " << code << " "; |
---|
85 | |
---|
86 | { |
---|
87 | long clocksPerSec = sysconf(_SC_CLK_TCK); |
---|
88 | double clockRes = 1.0 / clocksPerSec; |
---|
89 | struct tms tms; |
---|
90 | |
---|
91 | memset(&tms, 0, sizeof(tms)); |
---|
92 | times(&tms); |
---|
93 | |
---|
94 | oss << "utime " << (tms.tms_utime * clockRes) << " " |
---|
95 | << "stime " << (tms.tms_stime * clockRes) << " " |
---|
96 | << "cutime " << (tms.tms_cutime * clockRes) << " " |
---|
97 | << "cstime " << (tms.tms_cstime * clockRes) << " "; |
---|
98 | } |
---|
99 | |
---|
100 | oss << std::endl; |
---|
101 | |
---|
102 | int fd = getStatsFile(); |
---|
103 | std::string ostr = oss.str(); |
---|
104 | int result = writeToStatsFile(fd, ostr.c_str(), ostr.length()); |
---|
105 | close(fd); |
---|
106 | return result; |
---|
107 | } |
---|
108 | |
---|
109 | int |
---|
110 | GeoVis::getStatsFile(const char *key) |
---|
111 | { |
---|
112 | char fileName[33]; |
---|
113 | md5_state_t state; |
---|
114 | md5_byte_t digest[16]; |
---|
115 | |
---|
116 | if (key == NULL || g_statsFile >= 0) { |
---|
117 | return g_statsFile; |
---|
118 | } |
---|
119 | |
---|
120 | std::ostringstream keyStream; |
---|
121 | keyStream << key << " " |
---|
122 | << getpid(); |
---|
123 | std::string keystr = keyStream.str(); |
---|
124 | TRACE("Stats file key: '%s'", keystr.c_str()); |
---|
125 | |
---|
126 | md5_init(&state); |
---|
127 | md5_append(&state, (const md5_byte_t *)keystr.c_str(), keystr.length()); |
---|
128 | md5_finish(&state, digest); |
---|
129 | for (int i = 0; i < 16; i++) { |
---|
130 | sprintf(fileName + i * 2, "%02x", digest[i]); |
---|
131 | } |
---|
132 | |
---|
133 | std::ostringstream oss; |
---|
134 | oss << STATSDIR << "/" << fileName; |
---|
135 | g_statsFile = open(oss.str().c_str(), O_EXCL | O_CREAT | O_WRONLY, 0600); |
---|
136 | if (g_statsFile < 0) { |
---|
137 | ERROR("can't open \"%s\": %s", fileName, strerror(errno)); |
---|
138 | return -1; |
---|
139 | } |
---|
140 | return g_statsFile; |
---|
141 | } |
---|
142 | |
---|
143 | int |
---|
144 | GeoVis::writeToStatsFile(int fd, const char *s, size_t length) |
---|
145 | { |
---|
146 | if (fd >= 0) { |
---|
147 | ssize_t numWritten; |
---|
148 | |
---|
149 | numWritten = write(fd, s, length); |
---|
150 | if (numWritten == (ssize_t)length) { |
---|
151 | close(dup(fd)); |
---|
152 | } |
---|
153 | } |
---|
154 | return 0; |
---|
155 | } |
---|