#include "config.h"
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include "types.h"
#include "distcc.h"
#include "rpc.h"
#include "trace.h"
#include "exitcode.h"
#include "snprintf.h"
#include "util.h"
const char *dcc_state_prefix = "binstate_";
struct dcc_task_state my_state;
static int dcc_get_state_filename(char **fname)
{
int ret;
char *dir;
if ((ret = dcc_get_state_dir(&dir)))
return ret;
if (asprintf(fname, "%s/%s%ld",
dir, dcc_state_prefix, (long) getpid()) == -1) {
return EXIT_OUT_OF_MEMORY;
}
return 0;
}
const char *dcc_get_phase_name(enum dcc_phase phase)
{
switch (phase) {
case DCC_PHASE_STARTUP:
return "Startup";
case DCC_PHASE_BLOCKED:
return "Blocked";
case DCC_PHASE_COMPILE:
return "Compile";
case DCC_PHASE_CPP:
return "Preprocess";
case DCC_PHASE_CONNECT:
return "Connect";
case DCC_PHASE_SEND:
return "Send";
case DCC_PHASE_RECEIVE:
return "Receive";
case DCC_PHASE_DONE:
return "Done";
default:
return "Unknown";
}
}
static int dcc_open_state(int *p_fd,
const char *fname)
{
int fd;
fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 0666);
if (fd == -1) {
rs_log_error("failed to open %s: %s", fname, strerror(errno));
return EXIT_IO_ERROR;
}
dcc_set_owner(fname);
*p_fd = fd;
return 0;
}
void dcc_remove_state_file (void)
{
char *fname;
int ret;
if ((ret = dcc_get_state_filename(&fname)))
return;
if (unlink(fname) == -1) {
if (errno != ENOENT) {
rs_log_warning("failed to unlink %s: %s", fname, strerror(errno));
ret = EXIT_IO_ERROR;
}
}
free(fname);
(void) ret;
}
static int dcc_write_state(int fd)
{
int ret;
if ((ret = dcc_writex(fd, &my_state, sizeof my_state)))
return ret;
return 0;
}
int dcc_note_state(enum dcc_phase state,
const char *source_file,
const char *host)
{
int fd;
int ret;
char *fname;
struct timeval tv;
my_state.struct_size = sizeof my_state;
my_state.magic = DCC_STATE_MAGIC;
my_state.cpid = (unsigned long) getpid();
if ((ret = dcc_get_state_filename(&fname)))
return ret;
source_file = dcc_find_basename(source_file);
if (source_file) {
strlcpy(my_state.file, source_file, sizeof my_state.file);
}
if (host) {
strlcpy(my_state.host, host, sizeof my_state.host);
}
if (gettimeofday(&tv, NULL) == -1) {
rs_log_error("gettimeofday failed: %s", strerror(errno));
return EXIT_DISTCC_FAILED;
}
my_state.curr_phase = state;
rs_trace("note state %d, file \"%s\", host \"%s\"",
state,
source_file ? source_file : "(NULL)",
host ? host : "(NULL)");
if ((ret = dcc_open_state(&fd, fname))) {
free(fname);
return ret;
}
if ((ret = dcc_write_state(fd))) {
dcc_close(fd);
free(fname);
return ret;
}
dcc_close(fd);
free(fname);
return 0;
}
void dcc_note_state_slot(int slot)
{
my_state.slot = slot;
}