//
// Created by Carl on 2016-11-02.
//

#include “common.h”

#include

int fd;
int printerID;
SharedMemory* shared_mem;

//sets up a shared memory block
void setup_shared_memory(){
//First, we need to check if shared memory called MY_SHM has been created, if not create it
fd= shm_open(MY_SHM, O_RDWR | O_CREAT, S_IRWXU); //do read-only
//if the fd returns -1, there is an error, and we need to print that error and exit
if(fd == -1){
printf(“\n shm_open() failed\n”);
}
//ftruncate sets size of an object
ftruncate(fd, sizeof(SharedMemory));
}

void attach_shared_memory(){
//map the shared memory (MY_SHM) to this porcess, call it shared_mem.
shared_mem = (SharedMemory*) mmap(NULL, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
//if any error then print error and exit directly
if(shared_mem == MAP_FAILED){
printf(“mmap() failed\n”);
exit(1);
}
}

void init_shared_memory() {
//When a printer has initialized a shared memory, the second printer should not re-initialize anything
if(!shared_mem->initialized) {
printf(“No Shared Memory Has Yet Been Created, Creating It Now..\n”);
//set clientCount and printerCount two ints to 0
shared_mem->clientCount = 0;
shared_mem->printerCount = 1;
shared_mem->criticalPrinter = -1; // this is initialized to -1, only >=0 when certain Printer is taking a job from Shared Memory
shared_mem->activeServices = 1;
shared_mem->jobsLeft = 0;
shared_mem->initialized=1;
//initialize the semaphore MUTEX FILLED, and EMPTY as process sharing (pshared) semaphores with initial value 1.
sem_init(&(shared_mem->MUTEX), 1, 1);
sem_init(&(shared_mem->FILLED), 1, 0);
sem_init(&(shared_mem->EMPTY), 1, 10);
}
// if the shared memory has been created, we just need to increment printerCount by one to tell shared memory we have one more printer
else {
shared_mem->printerCount = shared_mem->printerCount+1;
shared_mem->activeServices = shared_mem->activeServices+1;
}
}

void handler(int signal){
int temp;
sem_getvalue(&shared_mem->MUTEX, &temp);
if(temp != 1&&shared_mem->criticalPrinter==printerID){
sem_post(&shared_mem->MUTEX);
}
close(fd);
shared_mem->printerCount=shared_mem->printerCount-1;
if(shared_mem->printerCount==0){
shm_unlink(MY_SHM);
}
}

void take_a_job(Job* job) {
sem_wait(&shared_mem->FILLED);
sem_wait(&shared_mem->MUTEX);
shared_mem->criticalPrinter=printerID;
if(shared_mem->jobsLeft>0){
memcpy(job, &(shared_mem->buffer[0]), sizeof(job));
//downshift jobs array
int i;
for(i = 1; i < shared_mem->jobsLeft; i++) {
memcpy(&(shared_mem->buffer[i-1]), &(shared_mem->buffer[i]), sizeof(job));
}
shared_mem->jobsLeft–;
}

sem_post(&shared_mem->MUTEX);
sem_post(&shared_mem->EMPTY);
shared_mem->criticalPrinter=-1;// if everything is successfully run, then set criticalPrinter to -1;

}

void print_a_msg(Job* job) {
// // Though it is very rare to have an extreme case of User Turning off a Printer when it was accessing the shared memory to get a job.
// // There will still be a probability of that happening. Warn the User something has gonne bad.
// if(shared_mem->criticalPrinter!=-1){
// printf(“!!! WARNING: YOUR PREVIOUS ACTION MIGHT HAVE CAUSED SERIOUS PROBLEMS !!!\n”);
// printf(“You Turned Off Your A Printer When It Was Accessing Shared Memory, You May Need To Re-print!”);
// }
//Then Print The Message
printf(“Now processing job submitted by client id %d. Total of %d page(s) to be printed. \n”,
job->clientID,
job->pageAmount);
}

void go_sleep(Job* job) {
int i;
for(i = 0; i < job->pageAmount; i++) {
printf(“.”);
sleep(1);
}
printf(“\n”);
printf(“Finished processing job submitted by client id %d. \n”, job->clientID);
}

int main() {
signal(SIGINT, handler);
setup_shared_memory();
attach_shared_memory();
init_shared_memory();

//printerID starts with 0 for first printer.
printerID=shared_mem->printerCount-1;

while (1) {
    Job job;
    take_a_job(&job);
    print_a_msg(&job);
    go_sleep(&job);
}

return 0;

}

//
// Created by Carl on 2016-11-02.
//

#include “common.h”

#include

int fd;
int printerID;
SharedMemory* shared_mem;

//sets up a shared memory block
void setup_shared_memory(){
//First, we need to check if shared memory called MY_SHM has been created, if not create it
fd= shm_open(MY_SHM, O_RDWR | O_CREAT, S_IRWXU); //do read-only
//if the fd returns -1, there is an error, and we need to print that error and exit
if(fd == -1){
printf(“\n shm_open() failed\n”);
}
//ftruncate sets size of an object
ftruncate(fd, sizeof(SharedMemory));
}

void attach_shared_memory(){
//map the shared memory (MY_SHM) to this porcess, call it shared_mem.
shared_mem = (SharedMemory*) mmap(NULL, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
//if any error then print error and exit directly
if(shared_mem == MAP_FAILED){
printf(“mmap() failed\n”);
exit(1);
}
}

void init_shared_memory() {
//When a printer has initialized a shared memory, the second printer should not re-initialize anything
if(!shared_mem->initialized) {
printf(“\n========================================================”);
printf(“\n== Carl’s Printer Service ==”);
printf(“\n== ID:260568761 ==”);
printf(“\n========================================================”);
printf(“\nNo Shared Memory Has Yet Been Created, Creating It Now..\n”);

    //set clientCount and printerCount two ints to 0
    shared_mem->clientCount = 0;
    shared_mem->printerCount = 1;
    shared_mem->criticalPrinter = -1; // this is initialized to -1, only >=0 when certain Printer is taking a job from Shared Memory
    shared_mem->activeServices = 1;
    shared_mem->jobsLeft = 0;
    shared_mem->initialized=1;
    //initialize the semaphore MUTEX FILLED, and EMPTY as process sharing (pshared) semaphores with initial value 1.
    sem_init(&(shared_mem->MUTEX), 1, 1);
    sem_init(&(shared_mem->FILLED), 1, 0);
    sem_init(&(shared_mem->EMPTY), 1, 10);
}
    // if the shared memory has been created, we just need to increment printerCount by one to tell shared memory we have one more printer
else {
    printf("Shared Memory is there");
    shared_mem->printerCount = shared_mem->printerCount+1;
    shared_mem->activeServices = shared_mem->activeServices+1;
}

}

void handler(int mysignal){
int temp;
shared_mem->initialized==0;
shared_mem->printerCount=shared_mem->printerCount-1;
sem_getvalue(&shared_mem->MUTEX, &temp);
if(temp != 1) {
sem_post(&shared_mem->MUTEX);
}
if(shared_mem->printerCount==0){
shared_mem->initialized==0;
printf(“Delete: printerLeft: %d”, shared_mem->printerCount);
if(munmap(shared_mem,sizeof(SharedMemory))==-1){
printf(“Delete: printerLeft: %d”, shared_mem->printerCount);
}
if(shm_unlink(MY_SHM)==-1){
perror(“error”);
}
signal(SIGTERM, handler);
}
}

void take_a_job(Job* job) {
sem_wait(&shared_mem->FILLED);
sem_wait(&shared_mem->MUTEX);
shared_mem->criticalPrinter=printerID;
if(shared_mem->jobsLeft>0){
memcpy(job, &(shared_mem->buffer[0]), sizeof(job));
//downshift jobs array
int i;
for(i = 1; i < shared_mem->jobsLeft; i++) {
memcpy(&(shared_mem->buffer[i-1]), &(shared_mem->buffer[i]), sizeof(job));
}
shared_mem->jobsLeft–;
}

sem_post(&shared_mem->MUTEX);
sem_post(&shared_mem->EMPTY);
shared_mem->criticalPrinter=-1;// if everything is successfully run, then set criticalPrinter to -1;

}

void print_a_msg(Job* job) {
// Though it is very rare to have an extreme case of User Turning off a Printer when it was accessing the shared memory to get a job.
// There will still be a probability of that happening. Warn the User something has gonne bad.
if(shared_mem->criticalPrinter!=-1){
printf(“!!! WARNING: YOUR PREVIOUS ACTION MIGHT HAVE CAUSED SERIOUS PROBLEMS !!!\n”);
printf(“You Turned Off Your A Printer When It Was Accessing Shared Memory, You May Need To Re-print!”);
}
//Then Print The Message
printf(“Now processing job submitted by client id %d. Total of %d page(s) to be printed. \n”,
job->clientID,
job->pageAmount);
}

void go_sleep(Job* job) {
int i;
for(i = 0; i < job->pageAmount; i++) {
printf(“.”);
sleep(1);
}
printf(“\n”);
printf(“Finished processing job submitted by client id %d. \n”, job->clientID);
}

int main() {
signal(SIGTERM, handler);
setup_shared_memory();
attach_shared_memory();
init_shared_memory();

//printerID starts with 0 for first printer.
printerID=shared_mem->printerCount-1;

while (1) {
    Job job;
    take_a_job(&job);
    print_a_msg(&job);
    go_sleep(&job);
}

return 0;

}