200 lines
3.8 KiB
C
200 lines
3.8 KiB
C
/**
|
|
* @file supervisor.c
|
|
* @date 2018-05-21
|
|
*
|
|
* @brief Server program which reads solutions and orders them.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include <limits.h>
|
|
|
|
static const char *pname;
|
|
|
|
struct circ_buf *shared;
|
|
|
|
static int shmfd;
|
|
|
|
static sem_t *sUsedSpace;
|
|
|
|
static sem_t *sFreeSpace;
|
|
|
|
static sem_t *sWriteEnd;
|
|
|
|
struct sigaction sa;
|
|
|
|
static int bestSolution[MAX_ITEMS];
|
|
|
|
static volatile sig_atomic_t quit = 0;
|
|
|
|
static void sig_handler(int signum)
|
|
{
|
|
quit = 1;
|
|
}
|
|
|
|
void usage(void)
|
|
{
|
|
fprintf(stderr, "SYNOPSIS\n"
|
|
"\tsupervisor\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
void cleanup()
|
|
{
|
|
shared->quit = 1;
|
|
|
|
if (munmap(shared, sizeof(*shared)) == -1) {
|
|
perror("munmap");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
close(shmfd);
|
|
if (shm_unlink(SHM_NAME) == -1) {
|
|
perror("shm_unlink");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
sem_close(sUsedSpace);
|
|
sem_close(sFreeSpace);
|
|
sem_close(sWriteEnd);
|
|
|
|
sem_unlink(SEM_USED_SPACE);
|
|
sem_unlink(SEM_FREE_SPACE);
|
|
sem_unlink(SEM_WRITE_END);
|
|
}
|
|
|
|
void initCircBuf()
|
|
{
|
|
shared->quit = 0;
|
|
for (int i = 0; i < MAX_ITEMS; i++) {
|
|
shared->data[i] = -1;
|
|
}
|
|
|
|
for (int i = 0; i < MAX_ITEMS; i++) {
|
|
bestSolution[i] = INT_MAX;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void wait_sem(sem_t *sem)
|
|
{
|
|
while (sem_wait(sem) == -1) { // interrupted by syscall?
|
|
if (errno == EINTR) {
|
|
if (quit == 1) {
|
|
cleanup();
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
else continue;
|
|
}
|
|
cleanup();
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void getSolution(sem_t *sUsedSpace, sem_t *sFreeSpace)
|
|
{
|
|
int solution[MAX_ITEMS];
|
|
for (int i = 0; i < MAX_ITEMS; i++) {
|
|
solution[i] = -1;
|
|
}
|
|
|
|
for (int i = 0; i < MAX_ITEMS; i++) {
|
|
wait_sem(sUsedSpace);
|
|
solution[i] = shared->data[shared->head];
|
|
shared->head = (shared->head + 1) % MAX_ITEMS;
|
|
sem_post(sFreeSpace);
|
|
}
|
|
|
|
// Code for testing if new solution is better than old
|
|
int bestSolutionLength = 0;
|
|
int newSolutionLength = 0;
|
|
|
|
// Compute length of current bestSolution
|
|
if ((bestSolution[0] != -1) && (bestSolution[0] != INT_MAX)) {
|
|
for (int i = 0; i < MAX_ITEMS; i++) {
|
|
if (bestSolution[i] == -1) {
|
|
bestSolutionLength = i;
|
|
break;
|
|
}
|
|
}
|
|
} else if (bestSolution[0] == INT_MAX) {
|
|
bestSolutionLength = 17;
|
|
}
|
|
|
|
// Compute length of newSolution
|
|
if (solution[0] != -1) {
|
|
for (int i = 0; i < MAX_ITEMS; i++) {
|
|
if (solution[i] == -1) {
|
|
newSolutionLength = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (newSolutionLength == 0) {
|
|
printf("[%s] The graph is acyclic!\n", pname);
|
|
quit = 1;
|
|
return;
|
|
}
|
|
|
|
if (newSolutionLength < bestSolutionLength) {
|
|
// Set all entries of bestSolution to -1
|
|
for (int i = 0; i < bestSolutionLength; i++) {
|
|
bestSolution[i] = -1;
|
|
}
|
|
// Copy all entries from solution to bestSolution
|
|
for (int i = 0; i < newSolutionLength; i++) {
|
|
bestSolution[i] = solution[i];
|
|
}
|
|
|
|
printf("[%s] Solution with %d edges:", pname, newSolutionLength/2);
|
|
for (int i = 0; i < newSolutionLength; i += 2) {
|
|
printf(" %d-%d", bestSolution[i], bestSolution[i+1]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if (argc != 1)
|
|
usage();
|
|
pname = argv[0];
|
|
|
|
struct sigaction sa;
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.sa_handler = &sig_handler;
|
|
sigaction(SIGINT, &sa, NULL);
|
|
sigaction(SIGTERM, &sa, NULL);
|
|
|
|
shmfd = shm_open(SHM_NAME, O_RDWR | O_CREAT, PERMISSION);
|
|
if (shmfd == -1) {
|
|
perror("[./supervisor] shm_open");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (ftruncate(shmfd, sizeof(*shared)) == -1) {
|
|
perror("[./supervisor] ftruncate");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
shared = mmap(NULL, sizeof(*shared), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
|
|
if (shared == MAP_FAILED) {
|
|
perror("[./supervisor] mmap");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
sFreeSpace = sem_open(SEM_FREE_SPACE, O_CREAT | O_EXCL, PERMISSION, MAX_ITEMS);
|
|
sUsedSpace = sem_open(SEM_USED_SPACE, O_CREAT | O_EXCL, PERMISSION, 0);
|
|
sWriteEnd = sem_open(SEM_WRITE_END, O_CREAT | O_EXCL, PERMISSION, 1);
|
|
|
|
initCircBuf();
|
|
|
|
while (quit == 0) {
|
|
wait_sem(sUsedSpace);
|
|
getSolution(sUsedSpace, sFreeSpace);
|
|
|
|
}
|
|
|
|
cleanup();
|
|
|
|
return 0;
|
|
}
|