blob: aa3536656498eba12c358a697c78866d683c0a1a [file]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
extern int errno;
#include <string.h>
#include <dirent.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <stdlib.h>
#include <poll.h>
#include "fileops.h"
/* Slurm portability */
#define SLURM_SUCCESS 0
#define SLURM_ERROR 1
/* TODO: fix */
#define FILENAME_PREFIX "pmix_addr"
typedef struct {
int jobid, stepid;
} local_records_t;
int my_jobid = -1;
int my_stepid = -1;
int sfd = -1, lockfd = -1;
char linkname[FILENAME_MAX];
char usockname[FILENAME_MAX], lockname[FILENAME_MAX];
int prepare_srv_socket(char *path);
void establish_listen_sock(int jobid, int stepid);
int pid_from_usockname(char *us_name, int jobid);
int run_discovery(int jobid, int stepid, int *is_leader);
int main(int argc, char **argv)
{
int is_leader;
if (argc < 3) {
fprintf(stderr,"Not enough arguments\n");
exit(0);
}
my_jobid = atoi(argv[1]);
my_stepid = atoi(argv[2]);
snprintf(linkname, FILENAME_MAX, "%s.%d", FILENAME_PREFIX, my_jobid);
snprintf(usockname, FILENAME_MAX, "%s.%d", linkname, my_stepid);
snprintf(lockname, FILENAME_MAX, "%s.lock",usockname);
if (0 > (lockfd = pmix_create_locked(lockname))) {
fprintf(stderr,"Can't create lock file %s\n", lockname);
exit(0);
}
sfd = prepare_srv_socket(usockname);
int i = 0;
while(1) {
int fd = run_discovery(my_jobid, my_stepid, &is_leader);
if (is_leader) {
fprintf("Iteration %d. I am the leader\n", i);
service_requests(fd);
} else {
monitor_leader(fd);
printf("server closed connection. Repeat resolution\n");
}
i++;
}
}
int run_discovery(int jobid, int my_stepid, int *is_leader)
{
char lname[FILENAME_MAX], fname[FILENAME_MAX], fname1[FILENAME_MAX];
*is_leader = 0;
if (!pmix_leader_is_alive(linkname)) {
pmix_remove_leader_symlink(linkname);
if (!symlink(usockname, linkname)) {
*is_leader = 1;
return sfd;
}
}
return connect_to_server(linkname);
}
int prepare_srv_socket(char *path)
{
static struct sockaddr_un sa;
int ret = 0;
if (strlen(path) >= sizeof(sa.sun_path)) {
/*PMIXP_ERROR_STD*/
printf("UNIX socket path is too long: %lu, max %lu",
(unsigned long)strlen(path),
(unsigned long)sizeof(sa.sun_path)-1);
return SLURM_ERROR;
}
/* Make sure that socket file doesn't exists */
if (0 == access(path, F_OK)) {
/* remove old file */
if (0 != unlink(path)) {
/*PMIXP_ERROR_STD*/
printf("Cannot delete outdated socket fine: %s",
path);
return SLURM_ERROR;
}
}
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
/*PMIXP_ERROR_STD*/
printf("Cannot create UNIX socket");
return SLURM_ERROR;
}
memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_UNIX;
strcpy(sa.sun_path, path);
if (ret = bind(fd, (struct sockaddr*)&sa, SUN_LEN(&sa))) {
/*PMIXP_ERROR_STD*/
printf("Cannot bind() UNIX socket %s", path);
goto err_fd;
}
if ((ret = listen(fd, 64))) {
/*PMIXP_ERROR_STD*/
printf("Cannot listen(%d, 64) UNIX socket %s", fd, path);
goto err_bind;
}
return fd;
err_bind:
unlink(path);
err_fd:
close(fd);
return ret;
}
int connect_to_server(char *path)
{
static struct sockaddr_un sa;
if (strlen(path) >= sizeof(sa.sun_path)) {
/*PMIXP_ERROR_STD*/
printf("UNIX socket path is too long: %lu, max %lu",
(unsigned long)strlen(path),
(unsigned long)sizeof(sa.sun_path)-1);
return -1;
}
memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_UNIX;
strcpy(sa.sun_path, path);
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
fprintf(stderr,"Cannot create UNIX socket");
return -1;
}
if (connect(fd, &sa, SUN_LEN(&sa))) {
close(fd);
return -1;
}
local_records_t rec;
rec.jobid = my_jobid;
rec.stepid = my_stepid;
int ret = write(fd, &rec, sizeof(rec));
if (sizeof(rec) != ret) {
close(fd);
return -1;
}
return fd;
}
void service_requests(int fd)
{
while(1) {
int cfd;
if (0 < (cfd = accept(fd, NULL, 0))) {
local_records_t rec;
int ret = read(cfd, &rec, sizeof(rec));
if (ret != sizeof(rec)) {
fprintf("%s:%d: read mismatch: %d vs %d\n",
__FILE__, __LINE__, ret, sizeof(rec));
exit(0);
}
fprintf(stderr,"New client connected: jobid=%d, stepid=%d, fd = %d\n",
rec.jobid, rec.stepid, fd);
}
}
}
void monitor_leader(int fd)
{
struct pollfd fds;
fds.fd = fd;
fds.events = 0;
/* Drop shutdown before the check */
int rc = poll(&fds, 1, -1);
if (rc < 0) {
fprintf(stderr,"Get poll error %d: %s", errno, strerror(errno));
exit(1);
}
if (fds.revents != POLLHUP) {
fprintf(stderr,"revents = %x", fds.revents);
}
}