summaryrefslogtreecommitdiff
path: root/src/libpcp_gui/src/timestate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libpcp_gui/src/timestate.c')
-rw-r--r--src/libpcp_gui/src/timestate.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/libpcp_gui/src/timestate.c b/src/libpcp_gui/src/timestate.c
new file mode 100644
index 0000000..7314183
--- /dev/null
+++ b/src/libpcp_gui/src/timestate.c
@@ -0,0 +1,307 @@
+/*
+ * Time control functions for pmval
+ *
+ * Copyright (c) 1995-2001 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2008-2009 Aconex. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pmtime.h"
+#include "pmapi.h"
+#include "impl.h"
+
+static enum {
+ START = -1,
+ STANDBY = 0,
+ FORW = 1,
+ BACK = 2,
+ MOVING = 3,
+ RESTART = 4,
+ ENDLOG = 5,
+} state;
+
+/*
+ * a : b for struct timevals ... <0 for a<b, ==0 for a==b, >0 for a>b
+ */
+static int
+__pmtimevalCmp(struct timeval *a, struct timeval *b)
+{
+ int res = (int)(a->tv_sec - b->tv_sec);
+
+ if (res == 0)
+ res = (int)(a->tv_usec - b->tv_usec);
+
+ return res;
+}
+
+static void timeControlExited()
+{
+ fprintf(stderr, "\n%s: Time Control dialog exited, goodbye.\n", pmProgname);
+}
+
+static void timeControlRewind()
+{
+ printf("\n[Time Control] Rewind/Reverse ...\n");
+}
+
+static void timeControlPosition(struct timeval position)
+{
+ printf("\n[Time Control] Repositioned in archive ...\n");
+}
+
+static void timeControlInterval(struct timeval delta)
+{
+ printf("new interval: %1.2f sec\n", __pmtimevalToReal(&delta));
+}
+
+static void timeControlResume()
+{
+ printf("\n[Time Control] Resume ...\n");
+}
+
+static void timeControlBounds()
+{
+ printf("\n[Time Control] End of Archive ...\n");
+}
+
+static void timeControlStepped(struct timeval delta)
+{
+}
+
+static void timeControlNewZone(char *timezone, char *label)
+{
+ int sts = pmNewZone(timezone);
+
+ if (sts < 0)
+ fprintf(stderr, "%s: Warning: cannot set timezone to \"%s\": %s\n",
+ pmProgname, timezone, pmErrStr(sts));
+ else
+ printf("new timezone: %s (%s)\n", timezone, label);
+}
+
+/*
+ * Get Extended Time Base interval and Units from a timeval
+ * in order to set archive mode.
+ */
+void
+pmTimeStateMode(int mode, struct timeval delta, struct timeval *position)
+{
+ const int SECS_IN_24_DAYS = 2073600;
+ int step, sts;
+
+ if (delta.tv_sec > SECS_IN_24_DAYS) {
+ step = delta.tv_sec;
+ mode |= PM_XTB_SET(PM_TIME_SEC);
+ } else {
+ step = delta.tv_sec * 1e3 + delta.tv_usec / 1e3;
+ mode |= PM_XTB_SET(PM_TIME_MSEC);
+ }
+
+ if ((sts = pmSetMode(mode, position, step)) < 0) {
+ fprintf(stderr, "%s: pmSetMode: %s\n", pmProgname, pmErrStr(sts));
+ exit(EXIT_FAILURE);
+ }
+}
+
+pmTime *
+pmTimeStateSetup(
+ pmTimeControls *timecontrols, int ctxt, int port,
+ struct timeval delta, struct timeval position,
+ struct timeval first, struct timeval last, char *tz, char *tz_label)
+{
+ pmTime *pmtime = malloc(sizeof(pmTime));
+ int fd, sts, tzlen;
+
+ pmtime->magic = PMTIME_MAGIC;
+ pmtime->length = sizeof(pmTime);
+ pmtime->command = PM_TCTL_SET;
+ pmtime->delta = delta;
+
+ if (ctxt == PM_CONTEXT_ARCHIVE) {
+ pmtime->source = PM_SOURCE_ARCHIVE;
+ pmtime->position = position;
+ pmtime->start = first;
+ pmtime->end = last;
+ } else {
+ pmtime->source = PM_SOURCE_HOST;
+ __pmtimevalNow(&pmtime->position);
+ }
+ if (tz == NULL) {
+ char tzbuf[PM_TZ_MAXLEN];
+ tz = __pmTimezone_r(tzbuf, sizeof(tzbuf));
+ if (ctxt == PM_CONTEXT_ARCHIVE) {
+ if ((sts = pmNewZone(tz)) < 0) {
+ fprintf(stderr, "%s: Cannot set timezone to \"%s\": %s\n",
+ pmProgname, tz, pmErrStr(sts));
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ tzlen = strlen(tz) + 1;
+ if (tz_label == NULL)
+ tz_label = "localhost";
+ pmtime->length += tzlen + strlen(tz_label) + 1;
+ pmtime = realloc(pmtime, pmtime->length);
+ if (!pmtime) {
+ fprintf(stderr, "%s: realloc: %s\n", pmProgname, osstrerror());
+ exit(EXIT_FAILURE);
+ }
+ strcpy(pmtime->data, tz);
+ strcpy(pmtime->data + tzlen, tz_label);
+ if ((fd = pmTimeConnect(port, pmtime)) < 0) {
+ fprintf(stderr, "%s: pmTimeConnect: %s\n", pmProgname, pmErrStr(fd));
+ exit(EXIT_FAILURE);
+ }
+
+ pmtime->length = sizeof(pmTime); /* reduce size to header only */
+ pmtime = realloc(pmtime, pmtime->length); /* cannot fail! */
+
+ /* setup default vectors */
+ timecontrols->resume = timeControlResume;
+ timecontrols->exited = timeControlExited;
+ timecontrols->rewind = timeControlRewind;
+ timecontrols->boundary = timeControlBounds;
+ timecontrols->position = timeControlPosition;
+ timecontrols->interval = timeControlInterval;
+ timecontrols->stepped = timeControlStepped;
+ timecontrols->newzone = timeControlNewZone;
+ timecontrols->context = ctxt;
+ timecontrols->showgui = 1;
+ timecontrols->delta = delta;
+ timecontrols->padding = 0;
+ timecontrols->fd = fd;
+ state = START;
+
+ return pmtime;
+}
+
+void
+pmTimeStateBounds(pmTimeControls *control, pmTime *pmtime)
+{
+ pmTimeStateAck(control, pmtime);
+ if (state != ENDLOG)
+ control->boundary();
+ state = ENDLOG;
+}
+
+void
+pmTimeStateAck(pmTimeControls *control, pmTime *pmtime)
+{
+ int sts = pmTimeSendAck(control->fd, &pmtime->position);
+
+ if (sts < 0) {
+ if (sts == -EPIPE)
+ control->exited();
+ else
+ fprintf(stderr, "\n%s: pmTimeSendAck: %s\n",
+ pmProgname, pmErrStr(sts));
+ exit(EXIT_FAILURE);
+ }
+}
+
+int
+pmTimeStateVector(pmTimeControls *control, pmTime *pmtime)
+{
+ int cmd, fetch = 0;
+
+ if (control->showgui) {
+ pmTimeShowDialog(control->fd, 1);
+ control->showgui = 0;
+ }
+
+ do {
+ cmd = pmTimeRecv(control->fd, &pmtime);
+ if (cmd < 0) {
+ control->exited();
+ exit(EXIT_FAILURE);
+ }
+
+ switch (pmtime->command) {
+ case PM_TCTL_SET:
+ if (state == ENDLOG)
+ state = STANDBY;
+ else if (state == FORW)
+ state = RESTART;
+ break;
+
+ case PM_TCTL_STEP:
+ if (pmtime->state == PM_STATE_BACKWARD) {
+ if (state != BACK) {
+ control->rewind();
+ state = BACK;
+ }
+ }
+ else if (state != FORW && state != ENDLOG) {
+ if (control->context == PM_CONTEXT_ARCHIVE) {
+ if (state == STANDBY)
+ control->resume();
+ else if (state != START)
+ control->position(pmtime->position);
+ }
+ else if (state != START)
+ control->resume();
+ if (state != START &&
+ __pmtimevalCmp(&pmtime->delta, &control->delta) != 0)
+ control->interval(pmtime->delta);
+
+ if (control->context == PM_CONTEXT_ARCHIVE)
+ pmTimeStateMode(PM_MODE_INTERP,
+ pmtime->delta, &pmtime->position);
+ control->delta = pmtime->delta;
+ control->stepped(pmtime->delta);
+ state = FORW;
+ }
+
+ if (state == BACK || state == ENDLOG) {
+ /*
+ * for EOL and reverse travel, no fetch, so ACK here
+ */
+ pmTimeStateAck(control, pmtime);
+ break;
+ }
+ fetch = 1;
+ break;
+
+ case PM_TCTL_TZ:
+ control->newzone(pmtime->data,
+ pmtime->data + strlen(pmtime->data) + 1);
+ break;
+
+ case PM_TCTL_VCRMODE:
+ case PM_TCTL_VCRMODE_DRAG:
+ /* something has changed ... suppress reporting */
+ if (pmtime->command == PM_TCTL_VCRMODE_DRAG)
+ state = MOVING;
+ else if (pmtime->state == PM_STATE_STOP)
+ state = STANDBY;
+ else
+ state = RESTART;
+ break;
+
+ /*
+ * safely and silently ignore these
+ */
+ case PM_TCTL_GUISHOW:
+ case PM_TCTL_GUIHIDE:
+ case PM_TCTL_BOUNDS:
+ case PM_TCTL_ACK:
+ break;
+
+ default:
+ if (pmDebug & DBG_TRACE_TIMECONTROL)
+ fprintf(stderr, "pmTimeRecv: cmd %x?\n", cmd);
+ break;
+ }
+ } while (!fetch);
+
+ return 0;
+}