Add OVNI_TRACEDIR envar to change trace directory
This commit introduces the OVNI_TRACEDIR environment variable to change the directory where traces are generated. By default, when the envar is not defined, the trace is still generated in the ovni directory. The envar can take a trace directory name, a relative path to the directory, or its absolute path. In the first case, the directory is created in the current path $PWD. Both libovni (rt) and ovnisync read this environment variable.
This commit is contained in:
parent
24252ebbb3
commit
7b4ebca002
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add `OVNI_TRACEDIR` envar to change the trace directory (default is `ovni`).
|
||||||
|
|
||||||
## [1.3.0] - 2023-09-07
|
## [1.3.0] - 2023-09-07
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -24,9 +24,11 @@ If you are using SLURM, you may want to use something like:
|
|||||||
you must invoke srun twice.
|
you must invoke srun twice.
|
||||||
|
|
||||||
By default, it will generate the `ovni/clock-offsets.txt` file, with the
|
By default, it will generate the `ovni/clock-offsets.txt` file, with the
|
||||||
relative offsets to the rank 0 of MPI. The emulator will automatically pick the
|
relative offsets to the rank 0 of MPI. If the `OVNI_TRACEDIR` environment
|
||||||
offsets when processing the trace. Use the ovnisync `-o` option to select a
|
variable is defined, the default file is `$OVNI_TRACEDIR/clock-offsets.txt`.
|
||||||
different output path (see the `-c` option in ovniemu to load the file).
|
The emulator will automatically pick the offsets when processing the trace.
|
||||||
|
Use the ovnisync `-o` option to select a different output path (see the `-c`
|
||||||
|
option in ovniemu to load the file).
|
||||||
|
|
||||||
Here is an example table with three nodes, all units are in nanoseconds. The
|
Here is an example table with three nodes, all units are in nanoseconds. The
|
||||||
standard deviation is less than 1 us:
|
standard deviation is less than 1 us:
|
||||||
|
@ -25,6 +25,12 @@ Compile and link with libovni. When you run your program, a new
|
|||||||
directory ovni will be created in the current directory `$PWD/ovni`
|
directory ovni will be created in the current directory `$PWD/ovni`
|
||||||
which contains the execution trace.
|
which contains the execution trace.
|
||||||
|
|
||||||
|
You can change the trace directory by defining the `OVNI_TRACEDIR`
|
||||||
|
environment variable. The envar accepts a trace directory name, a
|
||||||
|
relative path to the trace directory, or its absolute path. In the
|
||||||
|
first case, the trace directory will be created in the current
|
||||||
|
directory `$PWD`.
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
Follow these rules to avoid losing events:
|
Follow these rules to avoid losing events:
|
||||||
|
55
src/common.c
55
src/common.c
@ -8,6 +8,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
char *progname = NULL;
|
char *progname = NULL;
|
||||||
int is_debug_enabled = 0;
|
int is_debug_enabled = 0;
|
||||||
@ -73,3 +74,57 @@ vdie(const char *prefix, const char *func, const char *errstr, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mkdir_if_need(const char *path, mode_t mode)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
if (mkdir(path, mode) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (errno == EEXIST) {
|
||||||
|
struct stat st;
|
||||||
|
if (stat(path, &st) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (S_ISDIR(st.st_mode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
errno = ENOTDIR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mkpath(const char *path, mode_t mode, int is_dir)
|
||||||
|
{
|
||||||
|
char *copypath = strdup(path);
|
||||||
|
|
||||||
|
/* Remove trailing slash */
|
||||||
|
int last = strlen(path) - 1;
|
||||||
|
while (last > 0 && copypath[last] == '/')
|
||||||
|
copypath[last--] = '\0';
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
char *pp = copypath;
|
||||||
|
char *sp;
|
||||||
|
while (status == 0 && (sp = strchr(pp, '/')) != 0) {
|
||||||
|
if (sp != pp) {
|
||||||
|
/* Neither root nor double slash in path */
|
||||||
|
*sp = '\0';
|
||||||
|
status = mkdir_if_need(copypath, mode);
|
||||||
|
*sp = '/';
|
||||||
|
}
|
||||||
|
pp = sp + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create last component if it is a directory */
|
||||||
|
if (is_dir && status == 0)
|
||||||
|
status = mkdir_if_need(copypath, mode);
|
||||||
|
|
||||||
|
free(copypath);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -5,9 +5,14 @@
|
|||||||
#define COMMON_H
|
#define COMMON_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
extern int is_debug_enabled;
|
extern int is_debug_enabled;
|
||||||
|
|
||||||
|
/* Path and file utilities */
|
||||||
|
|
||||||
|
int mkpath(const char *path, mode_t mode, int is_dir);
|
||||||
|
|
||||||
/* Debug macros */
|
/* Debug macros */
|
||||||
|
|
||||||
void progname_set(char *name);
|
void progname_set(char *name);
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -48,7 +47,7 @@ struct options {
|
|||||||
int ndrift_samples;
|
int ndrift_samples;
|
||||||
int drift_wait; /* in seconds */
|
int drift_wait; /* in seconds */
|
||||||
int verbose;
|
int verbose;
|
||||||
char *outpath;
|
char outpath[PATH_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
static double
|
static double
|
||||||
@ -83,65 +82,31 @@ cmp_double(const void *pa, const void *pb)
|
|||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: clock synchronization utility\n", progname);
|
fprintf(stderr, "%s: clock synchronization utility\n", progname_get());
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "Usage: %s [-o outfile] [-d ndrift_samples] [-v] [-n nsamples] [-w drift_delay]\n",
|
fprintf(stderr, "Usage: %s [-o outfile] [-d ndrift_samples] [-v] [-n nsamples] [-w drift_delay]\n",
|
||||||
progname);
|
progname_get());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
try_mkdir(const char *path, mode_t mode)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (stat(path, &st) != 0) {
|
|
||||||
/* Directory does not exist */
|
|
||||||
return mkdir(path, mode);
|
|
||||||
} else if (!S_ISDIR(st.st_mode)) {
|
|
||||||
errno = ENOTDIR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
mkpath(const char *path, mode_t mode)
|
|
||||||
{
|
|
||||||
char *copypath = strdup(path);
|
|
||||||
|
|
||||||
/* Remove trailing slash */
|
|
||||||
int last = strlen(path) - 1;
|
|
||||||
while (last > 0 && copypath[last] == '/')
|
|
||||||
copypath[last--] = '\0';
|
|
||||||
|
|
||||||
int status = 0;
|
|
||||||
char *pp = copypath;
|
|
||||||
char *sp;
|
|
||||||
while (status == 0 && (sp = strchr(pp, '/')) != 0) {
|
|
||||||
if (sp != pp) {
|
|
||||||
/* Neither root nor double slash in path */
|
|
||||||
*sp = '\0';
|
|
||||||
status = try_mkdir(copypath, mode);
|
|
||||||
*sp = '/';
|
|
||||||
}
|
|
||||||
pp = sp + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(copypath);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_options(struct options *options, int argc, char *argv[])
|
parse_options(struct options *options, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
char *filename = "clock-offsets.txt";
|
||||||
|
char *tracedir = getenv("OVNI_TRACEDIR");
|
||||||
|
if (tracedir == NULL)
|
||||||
|
tracedir = OVNI_TRACEDIR;
|
||||||
|
|
||||||
/* Default options */
|
/* Default options */
|
||||||
options->ndrift_samples = 1;
|
options->ndrift_samples = 1;
|
||||||
options->nsamples = 100;
|
options->nsamples = 100;
|
||||||
options->verbose = 0;
|
options->verbose = 0;
|
||||||
options->drift_wait = 5;
|
options->drift_wait = 5;
|
||||||
options->outpath = "ovni/clock-offsets.txt";
|
|
||||||
|
if (snprintf(options->outpath, PATH_MAX, "%s/%s", tracedir, filename) >= PATH_MAX) {
|
||||||
|
fprintf(stderr, "output path too long: %s/%s\n", tracedir, filename);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
while ((opt = getopt(argc, argv, "d:vn:w:o:h")) != -1) {
|
while ((opt = getopt(argc, argv, "d:vn:w:o:h")) != -1) {
|
||||||
@ -159,7 +124,11 @@ parse_options(struct options *options, int argc, char *argv[])
|
|||||||
options->nsamples = atoi(optarg);
|
options->nsamples = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
options->outpath = optarg;
|
if (strlen(optarg) >= PATH_MAX - 1) {
|
||||||
|
fprintf(stderr, "output path too long: %s\n", optarg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
strcpy(options->outpath, optarg);
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
default: /* '?' */
|
default: /* '?' */
|
||||||
@ -396,7 +365,7 @@ do_work(struct options *options, int rank)
|
|||||||
int drift_mode = options->ndrift_samples > 1 ? 1 : 0;
|
int drift_mode = options->ndrift_samples > 1 ? 1 : 0;
|
||||||
|
|
||||||
if (rank == 0) {
|
if (rank == 0) {
|
||||||
if (mkpath(options->outpath, 0755) != 0) {
|
if (mkpath(options->outpath, 0755, /* not subdir */ 0) != 0) {
|
||||||
fprintf(stderr, "mkpath(%s) failed: %s\n",
|
fprintf(stderr, "mkpath(%s) failed: %s\n",
|
||||||
options->outpath, strerror(errno));
|
options->outpath, strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -216,20 +216,10 @@ ovni_proc_set_rank(int rank, int nranks)
|
|||||||
static void
|
static void
|
||||||
mkdir_proc(char *path, const char *tracedir, const char *loom, int pid)
|
mkdir_proc(char *path, const char *tracedir, const char *loom, int pid)
|
||||||
{
|
{
|
||||||
snprintf(path, PATH_MAX, "%s", tracedir);
|
snprintf(path, PATH_MAX, "%s/loom.%s/proc.%d/", tracedir, loom, pid);
|
||||||
|
|
||||||
/* May fail if another loom created the directory already */
|
|
||||||
mkdir(path, 0755);
|
|
||||||
|
|
||||||
snprintf(path, PATH_MAX, "%s/loom.%s", tracedir, loom);
|
|
||||||
|
|
||||||
/* Also may fail */
|
|
||||||
mkdir(path, 0755);
|
|
||||||
|
|
||||||
snprintf(path, PATH_MAX, "%s/loom.%s/proc.%d", tracedir, loom, pid);
|
|
||||||
|
|
||||||
/* But this one shall not fail */
|
/* But this one shall not fail */
|
||||||
if (mkdir(path, 0755))
|
if (mkpath(path, 0755, /* subdir */ 1))
|
||||||
die("mkdir %s failed:", path);
|
die("mkdir %s failed:", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,14 +227,19 @@ static void
|
|||||||
create_proc_dir(const char *loom, int pid)
|
create_proc_dir(const char *loom, int pid)
|
||||||
{
|
{
|
||||||
char *tmpdir = getenv("OVNI_TMPDIR");
|
char *tmpdir = getenv("OVNI_TMPDIR");
|
||||||
|
char *tracedir = getenv("OVNI_TRACEDIR");
|
||||||
|
|
||||||
|
/* Use default tracedir if user did not request any */
|
||||||
|
if (tracedir == NULL)
|
||||||
|
tracedir = OVNI_TRACEDIR;
|
||||||
|
|
||||||
if (tmpdir != NULL) {
|
if (tmpdir != NULL) {
|
||||||
rproc.move_to_final = 1;
|
rproc.move_to_final = 1;
|
||||||
mkdir_proc(rproc.procdir, tmpdir, loom, pid);
|
mkdir_proc(rproc.procdir, tmpdir, loom, pid);
|
||||||
mkdir_proc(rproc.procdir_final, OVNI_TRACEDIR, loom, pid);
|
mkdir_proc(rproc.procdir_final, tracedir, loom, pid);
|
||||||
} else {
|
} else {
|
||||||
rproc.move_to_final = 0;
|
rproc.move_to_final = 0;
|
||||||
mkdir_proc(rproc.procdir, OVNI_TRACEDIR, loom, pid);
|
mkdir_proc(rproc.procdir, tracedir, loom, pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user