int main(void) { static const double tstep = 1.0/TICKRATE; double tlast, tnow, tsec, dt, ddt=0.0; int ticks=0, tps=0, frames=0; #if 0 { int i; for (i=0; i<100; ++i) { gx_init("demo", XRES, YRES); gx_delay(0.01); gx_exit(); } } #endif gx_init("demo", XRES, YRES); tlast = gx_time(); while (1) { tnow = gx_time(); dt = tnow - tlast; tlast = tnow; if (dt > 0.25) dt = 0.25; if (poll_events()) break; ddt += dt; while (ddt >= tstep) { ddt -= tstep; ++ticks; ++tps; } draw(tnow, ddt/dt); gx_paint(buf, XRES, YRES); ++frames; print_time(ticks, &tps, tnow, dt); if (limitfps && maxfps) { double tmax = 1.0 / maxfps; while (gx_time() - tnow < tmax-0.002) gx_delay(0.001); while (gx_time() - tnow < tmax); } } tsec = gx_time(); printf("--- timing report ---\n" "ticks : %d\n" "frames : %d\n" "time : %.2f\n" "tickrate : %.2f\n" "fps : %.2f\n", ticks, frames, tsec, ticks/tsec, frames/tsec); return 0; }
static void gx_accept(SOCKET sock, short event, void* arg) { SOCKET nsock; gp_smon_to_mmon_packet_t pkt; struct sockaddr_in a; socklen_t alen = sizeof(a); char* p; char* q; if (event & EV_TIMEOUT) { if (gx.tcp_sock) { /* start watching connect request again */ if (event_add(&gx.listen_event, 0)) { gpsmon_fatal(FLINE, "event_add failed"); } return; } gpmon_fatal(FLINE, "smon terminates due to no requests come after %" FMT64 " seconds\n", opt.terminate_timeout); } if (0 == (event & EV_READ)) return; if (-1 == (nsock = accept(sock, (void*) &a, &alen))) { gpmon_warningx(FLINE, APR_FROM_OS_ERROR(errno), "accept failed"); return; } TR1(("accepted\n")); /* we do this one at a time */ if (gx.tcp_sock) { gpmon_warning(FLINE, "cannot accept new connection before old one dies"); close(nsock); return; } p = (char*) &pkt; q = p + sizeof(pkt); while (p < q) { int n = recv(nsock, p, q - p, 0); if (n == -1) { gpmon_warningx(FLINE, APR_FROM_OS_ERROR(errno), "recv failed"); close(nsock); return; } p += n; } if (0 != gpmon_ntohpkt(pkt.header.magic, pkt.header.version, pkt.header.pkttype)) { close(nsock); return; } if (pkt.header.pkttype != GPMON_PKTTYPE_HELLO) { close(nsock); return; } if (pkt.u.hello.signature != gx.signature) { gx_exit("bad signature... maybe a new gpmmon has started"); } /* echo the hello */ pkt.u.hello.pid = getpid(); TR2(("accepted pkt.magic = %x\n", (int) pkt.header.magic)); send_smon_to_mon_pkt(nsock, &pkt); struct timeval tv; tv.tv_sec = opt.terminate_timeout; tv.tv_usec = 0; event_set(&gx.tcp_event, nsock, EV_READ | EV_PERSIST | EV_TIMEOUT, gx_gettcpcmd, 0); if (event_add(&gx.tcp_event, &tv)) { gpmon_warningx(FLINE, APR_FROM_OS_ERROR(errno), "event_add failed"); close(nsock); return; } gx.tcp_sock = nsock; TR1(("connection established --------------------- \n")); }
static void gx_gettcpcmd(SOCKET sock, short event, void* arg) { char dump; int n, e; apr_pool_t* oldpool; apr_hash_t* qetab; apr_hash_t* qdtab; apr_hash_t* pidtab; apr_hash_t* segtab; if (event & EV_TIMEOUT) // didn't get command from gpmmon, quit { if(gx.tcp_sock) { close(gx.tcp_sock); gx.tcp_sock=0; } return; } apr_hash_t* querysegtab; n = recv(sock, &dump, 1, 0); if (n == 0) gx_exit("peer closed"); if (n == -1) gx_exit("socket error"); if (dump != 'D') gx_exit("bad data"); TR1(("start dump %c\n", dump)); qetab = gx.qexectab; qdtab = gx.qlogtab; pidtab = gx.pidtab; segtab = gx.segmenttab; querysegtab = gx.querysegtab; oldpool = apr_hash_pool_get(qetab); /* make new hashtabs for next cycle */ { apr_pool_t* newpool; if (0 != (e = apr_pool_create_alloc(&newpool, gx.pool))) { gpsmon_fatalx(FLINE, e, "apr_pool_create_alloc failed"); } /* qexec hash table */ gx.qexectab = apr_hash_make(newpool); CHECKMEM(gx.qexectab); /* qlog hash table */ gx.qlogtab = apr_hash_make(newpool); CHECKMEM(gx.qlogtab); /* segment hash table */ gx.segmenttab = apr_hash_make(newpool); CHECKMEM(gx.segmenttab); /* queryseg hash table */ gx.querysegtab = apr_hash_make(newpool); CHECKMEM(gx.querysegtab); /* pidtab hash table */ gx.pidtab = apr_hash_make(newpool); CHECKMEM(gx.pidtab); } /* push out a metric of the machine */ send_machine_metrics(sock); send_fsinfo(sock); /* push out records */ { apr_hash_index_t* hi; gp_smon_to_mmon_packet_t* ppkt = 0; gp_smon_to_mmon_packet_t localPacketObject; pidrec_t* pidrec; int count = 0; apr_hash_t* query_cpu_table = NULL; for (hi = apr_hash_first(0, querysegtab); hi; hi = apr_hash_next(hi)) { void* vptr; apr_hash_this(hi, 0, 0, &vptr); ppkt = vptr; if (ppkt->header.pkttype != GPMON_PKTTYPE_QUERYSEG) continue; TR2(("sending magic %x, pkttype %d\n", ppkt->header.magic, ppkt->header.pkttype)); send_smon_to_mon_pkt(sock, ppkt); count++; } for (hi = apr_hash_first(0, segtab); hi; hi = apr_hash_next(hi)) { void* vptr; apr_hash_this(hi, 0, 0, &vptr); ppkt = vptr; if (ppkt->header.pkttype != GPMON_PKTTYPE_SEGINFO) continue; /* fill in hostname */ strncpy(ppkt->u.seginfo.hostname, gx.hostname, sizeof(ppkt->u.seginfo.hostname) - 1); ppkt->u.seginfo.hostname[sizeof(ppkt->u.seginfo.hostname) - 1] = 0; TR2(("sending magic %x, pkttype %d\n", ppkt->header.magic, ppkt->header.pkttype)); send_smon_to_mon_pkt(sock, ppkt); count++; } for (hi = apr_hash_first(0, qdtab); hi; hi = apr_hash_next(hi)) { void* vptr; apr_hash_this(hi, 0, 0, &vptr); ppkt = vptr; if (ppkt->header.pkttype != GPMON_PKTTYPE_QLOG) continue; TR2(("sending magic %x, pkttype %d\n", ppkt->header.magic, ppkt->header.pkttype)); send_smon_to_mon_pkt(sock, ppkt); count++; } for (hi = apr_hash_first(0, qetab); hi; hi = apr_hash_next(hi)) { gpmon_qexec_t* qexec; void *vptr; apr_hash_this(hi, 0, 0, &vptr); qexec = vptr; /* fill in _p_metrics */ pidrec = apr_hash_get(pidtab, &qexec->key.hash_key.pid, sizeof(qexec->key.hash_key.pid)); if (pidrec) { qexec->_p_metrics = pidrec->p_metrics; qexec->_cpu_elapsed = pidrec->cpu_elapsed; } else { memset(&qexec->_p_metrics, 0, sizeof(qexec->_p_metrics)); } /* fill in _hname */ strncpy(qexec->_hname, gx.hostname, sizeof(qexec->_hname) - 1); qexec->_hname[sizeof(qexec->_hname) - 1] = 0; if (0 == create_qexec_packet(qexec, &localPacketObject)) { break; } TR2(("sending qexec, pkttype %d\n", localPacketObject.header.pkttype)); send_smon_to_mon_pkt(sock, &localPacketObject); count++; } // calculate CPU utilization per query for this machine query_cpu_table = apr_hash_make(oldpool); CHECKMEM(query_cpu_table); // loop through PID's and add to Query CPU Hash Table for (hi = apr_hash_first(0, pidtab); hi; hi = apr_hash_next(hi)) { void* vptr; pidrec_t* lookup; apr_hash_this(hi, 0, 0, &vptr); pidrec = vptr; TR2(("tmid %d ssid %d ccnt %d pid %d (CPU elapsed %d CPU Percent %.2f)\n", pidrec->query_key.tmid, pidrec->query_key.ssid, pidrec->query_key.ccnt, pidrec->pid, pidrec->cpu_elapsed, pidrec->p_metrics.cpu_pct)); // table is keyed on query key lookup = apr_hash_get(query_cpu_table, &pidrec->query_key, sizeof(pidrec->query_key)); if (lookup) { // found other pids with same query key so add the metrics to that lookup->cpu_elapsed += pidrec->cpu_elapsed; lookup->p_metrics.cpu_pct += pidrec->p_metrics.cpu_pct; } else { // insert existing pid record into table keyed by query key apr_hash_set(query_cpu_table, &pidrec->query_key, sizeof(pidrec->query_key), pidrec); } } // reset packet to 0 ppkt = &localPacketObject; memset(ppkt, 0, sizeof(gp_smon_to_mmon_packet_t)); gp_smon_to_mmon_set_header(ppkt,GPMON_PKTTYPE_QUERY_HOST_METRICS); // add the hostname into the packet for DEBUGGING purposes only. This is not used strncpy(ppkt->u.qlog.user, gx.hostname, sizeof(ppkt->u.qlog.user) - 1); ppkt->u.qlog.user[sizeof(ppkt->u.qlog.user) - 1] = 0; // loop through the query per cpu table and send the metrics for (hi = apr_hash_first(0, query_cpu_table); hi; hi = apr_hash_next(hi)) { void* vptr; apr_hash_this(hi, 0, 0, &vptr); pidrec = vptr; ppkt->u.qlog.key.tmid = pidrec->query_key.tmid; ppkt->u.qlog.key.ssid = pidrec->query_key.ssid; ppkt->u.qlog.key.ccnt = pidrec->query_key.ccnt; ppkt->u.qlog.cpu_elapsed = pidrec->cpu_elapsed; ppkt->u.qlog.p_metrics.cpu_pct = pidrec->p_metrics.cpu_pct; TR2(("SEND tmid %d ssid %d ccnt %d (CPU elapsed %d CPU Percent %.2f)\n", ppkt->u.qlog.key.tmid, ppkt->u.qlog.key.ssid, ppkt->u.qlog.key.ccnt, ppkt->u.qlog.cpu_elapsed, ppkt->u.qlog.p_metrics.cpu_pct)); send_smon_to_mon_pkt(sock, ppkt); count++; } TR1(("end dump ... sent %d entries\n", count)); } /* get rid of the old pool */ { apr_pool_destroy(oldpool); } struct timeval tv; tv.tv_sec = opt.terminate_timeout; tv.tv_usec = 0; if (event_add(&gx.tcp_event, &tv)) //reset timeout { gpmon_warningx(FLINE, APR_FROM_OS_ERROR(errno), "event_add failed"); } return; }