Added TS_SAVELIST.
--- a/Changelog Tue Apr 10 17:16:25 2007 +0200
+++ b/Changelog Tue Apr 10 23:31:21 2007 +0200
@@ -13,7 +13,7 @@
v0.4:
-* Allow killing 'ts' in a nice way.
- It's good, because a spawner of 'ts' may want to kill it.
- - If the server is horribly killed (it may happen as this is software), store
+ -* If the server is horribly killed (it may happen as this is software), store
the task queue in a file, so it can be recovered.
- Allow inspecting the environment for a command queued: env, pwd., together
with other job queuing options (gzip, ...)
--- a/Makefile Tue Apr 10 17:16:25 2007 +0200
+++ b/Makefile Tue Apr 10 23:31:21 2007 +0200
@@ -1,6 +1,6 @@
PREFIX?=/usr/local
-GCCFLAGS=-D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED -D__STRICT_ANSI__
-CFLAGS=-pedantic -ansi -Wall -g -O0 ${GCCFLAGS}
+GLIBCFLAGS=-D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED -D__STRICT_ANSI__
+CFLAGS=-pedantic -ansi -Wall -g -O0 ${GLIBCFLAGS}
OBJECTS=main.o \
server.o \
server_start.o \
--- a/jobs.c Tue Apr 10 17:16:25 2007 +0200
+++ b/jobs.c Tue Apr 10 23:31:21 2007 +0200
@@ -64,7 +64,7 @@
send_msg(s, &m);
}
-static struct Job * find_previous_job(struct Job *final)
+static struct Job * find_previous_job(const struct Job *final)
{
struct Job *p;
@@ -119,7 +119,7 @@
const char * jstate2string(enum Jobstate s)
{
- char * jobstate;
+ const char * jobstate;
switch(s)
{
case QUEUED:
@@ -140,8 +140,6 @@
struct Job *p;
char *buffer;
- /* We limit to 100 bytes for output and 200 for the command.
- * We also put spaces between the data, for assuring parseability. */
/* Times: 0.00/0.00/0.00 - 4+4+4+2 = 14*/
buffer = joblist_headers();
send_list_line(s,buffer);
@@ -159,16 +157,13 @@
p = first_finished_job;
- if (p != 0)
+ /* Show Finished jobs */
+ while(p != 0)
{
- /* Show Finished jobs */
- while(p != 0)
- {
- buffer = joblist_line(p);
- send_list_line(s,buffer);
- free(buffer);
- p = p->next;
- }
+ buffer = joblist_line(p);
+ send_list_line(s,buffer);
+ free(buffer);
+ p = p->next;
}
}
@@ -812,3 +807,41 @@
p = p->next;
}
}
+
+void joblist_dump(int fd)
+{
+ struct Job *p;
+ char *buffer;
+
+ buffer = joblistdump_headers();
+ write(fd,buffer, strlen(buffer));
+ free(buffer);
+
+ /* We reuse the headers from the list */
+ buffer = joblist_headers();
+ write(fd, "# ", 2);
+ write(fd, buffer, strlen(buffer));
+
+ /* Show Finished jobs */
+ p = first_finished_job;
+ while(p != 0)
+ {
+ buffer = joblist_line(p);
+ write(fd, "# ", 2);
+ write(fd,buffer, strlen(buffer));
+ free(buffer);
+ p = p->next;
+ }
+
+ write(fd, "\n", 1);
+
+ /* Show Queued or Running jobs */
+ p = firstjob;
+ while(p != 0)
+ {
+ buffer = joblistdump_torun(p);
+ write(fd,buffer,strlen(buffer));
+ free(buffer);
+ p = p->next;
+ }
+}
--- a/list.c Tue Apr 10 17:16:25 2007 +0200
+++ b/list.c Tue Apr 10 23:31:21 2007 +0200
@@ -3,15 +3,28 @@
#include <string.h>
#include "main.h"
+char * joblistdump_headers()
+{
+ char * line;
+
+ line = malloc(600);
+ sprintf(line, "#!/bin/sh\n# - task spooler (ts) job dump\n"
+ "# This file has been created because a SIGTERM killed\n"
+ "# your queue server.\n"
+ "# The finished commands are listed first.\n"
+ "# The commands running or to be run are stored as you would\n"
+ "# probably run them. Take care - some quotes may have got"
+ " broken\n\n");
+
+ return line;
+}
+
char * joblist_headers()
{
char * line;
line = malloc(100);
- /* We limit to 100 bytes for output and 200 for the command.
- * We also put spaces between the data, for assuring parseability. */
- /* Times: 0.00/0.00/0.00 - 4+4+4+2 = 14*/
- sprintf(line, "%-4s %-10s %-20.100s %-8s %-14s %.200s\n",
+ sprintf(line, "%-4s %-10s %-20s %-8s %-14s %s\n",
"ID",
"State",
"Output",
@@ -122,3 +135,19 @@
return line;
}
+
+char * joblistdump_torun(const struct Job *p)
+{
+ int maxlen;
+ char * line;
+
+ maxlen = 10 + strlen(p->command) + 20; /* 20 is the margin for errors */
+
+ line = (char *) malloc(maxlen);
+ if (line == NULL)
+ error("Malloc for %i failed.\n", maxlen);
+
+ sprintf(line, "ts %s", p->command);
+
+ return line;
+}
--- a/main.h Tue Apr 10 17:16:25 2007 +0200
+++ b/main.h Tue Apr 10 23:31:21 2007 +0200
@@ -167,6 +167,8 @@
void s_send_state(int s, int jobid);
void s_swap_jobs(int s, int jobid1, int jobid2);
void dump_jobs_struct(FILE *out);
+void joblist_dump(int fd);
+const char * jstate2string(enum Jobstate s);
/* server.c */
void server_main(int notify_fd, char *_path);
@@ -205,9 +207,6 @@
void send_msg(const int fd, const struct msg *m);
int recv_msg(const int fd, struct msg *m);
-/* jobs.c */
-const char * jstate2string(enum Jobstate s);
-
/* msgdump.c */
void msgdump(FILE *, const struct msg *m);
@@ -218,3 +217,5 @@
/* list.c */
char * joblist_headers();
char * joblist_line(const struct Job *p);
+char * joblistdump_torun(const struct Job *p);
+char * joblistdump_headers();
--- a/server.c Tue Apr 10 17:16:25 2007 +0200
+++ b/server.c Tue Apr 10 23:31:21 2007 +0200
@@ -16,6 +16,7 @@
#include <unistd.h>
#include <limits.h>
#include <signal.h>
+#include <fcntl.h>
#include <stdio.h>
@@ -53,9 +54,25 @@
static char *path;
static int max_descriptors;
-
static void sigterm_handler(int n)
{
+ const char *dumpfilename;
+ int fd;
+
+ /* Dump the job list if we should to */
+ dumpfilename = getenv("TS_SAVELIST");
+ if (dumpfilename != NULL)
+ {
+ fd = open(dumpfilename, O_WRONLY | O_APPEND | O_CREAT, 0600);
+ if (fd != -1)
+ {
+ joblist_dump(fd);
+ close(fd);
+ } else
+ warning("The TS_SAVELIST file \"%s\" cannot be opened",
+ dumpfilename);
+ }
+
/* path will be initialized for sure, before installing the handler */
unlink(path);
exit(1);
--- a/ts.1 Tue Apr 10 17:16:25 2007 +0200
+++ b/ts.1 Tue Apr 10 23:31:21 2007 +0200
@@ -182,6 +182,12 @@
As seen above, it's used for the mail destination if
.B TS_MAILTO
is not specified.
+.TP
+.B "TS_SAVELIST"
+If it's defined when starting the queue server (probably the first
+.B ts
+command run), on SIGTERM the queue status will be saved to the file pointed
+by this environment variable - for example, at system shutdown.
.SH BUGS
If you want to run complex commands, you may want to run them through
.B sh -c 'commands...'