CSC352 Homework 3 Solution 2013

From dftwiki3
Jump to: navigation, search

--D. Thiebaut (talk) 14:44, 25 October 2013 (EDT)


The solution to the optional problem is posted, as it applies also to the first part of the assignment.



doHomework3_N_images.sh


#!/bin/bash
#
# doHomework3_N_images.sh
# Emily Flynn
# CSC 352
# 10/23/2013
#
# Script that runs master/worker routine for image resizing with N
# images and N workers. It receives a list of images as parameters and
# creates a worker (workerN) to receive each. An in and output pipe is
# created for each image/worker, and is canoncially named by the
# proper prefix and an index for the image/worker. The image names are
# passed to a java program (MasterN) that will communicate with all
# the workers.
#
# Note: in the future this program should be re-worked so that there
# can be a user specified number of workers not necessarily equal to
# the number of images. I did not get a chance to do this, but I left
# in functionality for the workers to process multiple images for when
# this is fixed.
#
# To run:
#   ./doHomework3_N_images.sh <image1> <image2> ... <imageN>


N="$#" # number of args is number of images, workers

TO_WORKER_PREFIX="temp_toWorker"
TO_MASTER_PREFIX="temp_toMaster"


# remove resized images - uncomment this if you are running multiple
# times for testing purposes, will get rid of previous resized images
# so that there is no confusion
#rm -f *_resized*

# compile programs
javac MasterN.java
gcc -o workerN workerN.c


# create N canonically named worker,master pipes 
for ((i=0; i<$N;i++))
do
    # create a worker pipe
    worker_pipe=${TO_WORKER_PREFIX}${i}
    mkfifo $worker_pipe

    # create a master pipe
    master_pipe=${TO_MASTER_PREFIX}${i}
    mkfifo $master_pipe
done



# run the MasterN program with the images as parameters
java MasterN $@ &

# invoke N workers with the proper pipes
for ((i=0; i<$N;i++))
do
    # run workerN.c with the worker and master pipes as parameters
    ./workerN ${TO_WORKER_PREFIX}${i} ${TO_MASTER_PREFIX}${i} &
done

# remove pipes to clean up directory
rm -f temp_* 

exit 0;


workerN.c


/*
 * workerN.c 
 * Emily Flynn
 * CSC 352
 * 10/23/2013
 *
 * This program receives names of image(s) from a fifo from the java
 * MasterN program, resizes each by 50% using ImageMagick, and runs
 * identify on each. It names the resized images by the original name
 * followed by the suffix "_resized". It then sends back identify
 * information through a fifo to the MasterN program. The parameters
 * for this program are the name of the inPipe, followed by the name
 * of the outPipe:
 *   ./workerN <inPipe> <outPipe> 
 *
 * This program is the same as worker1.c except it receives the in and
 * out pipe names as parameters instead of having them hard-coded. 
 *
 * Use the script doHomework3_N_images.sh to compile and run this
 * program.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXDIM 1000

/**
 * Function to generate a new name for an image by appending
 * "_resized" after the original image name before the file extension.
 *
 *  newName - pointer to the new name
 *  origName - pointer to the original name
 */
void generateNewName(char* newName, char* origName){
  char *p;
  
  // find the period character in the original name
  p = strchr(origName, '.');

  // error message if there is no period
  if (p == NULL){
    printf("Error! Image names are not formatted correctly.\n"); 
    exit(-1);
  }

  // temporarily replace the period character with an end of string
  *p = '\0'; 
  
  // copy in the first part of the image name (before the period)
  strcpy(newName, origName);
  strcat(newName, "_resized"); // add resized to the image name
  
  // restore the period character
  *p = '.';
  
  // append the rest of the image name to the new name
  strcat(newName, p);
  return;
}

/**
 * Main method for running worker program. Parameters specify names
 * for in and out pipes. Reads in image names from a pipe, resizes them
 * and and runs identify on them. Then writes the output to another
 * pipe for the master program to read.
 *
 *  parameters: inPipe, outPipe
 */
int main(int argc, const char** argv){
  int i, numFiles;
  FILE *fp_in, *fp_out, *pf; // pipes for in, out, and command line 
  char imageArray[10][40]; // an array for holding the images (names
			   // are ltd to 40 char, and ltd to 10 images
			   // total)
  char newname[47]; // new name of a particular image
  char command[120]; // ImageMagick Command
  char result[MAXDIM];  // output of running identify

  const char* inFile; // in pipe name
  const char* outFile; // out pipe name


  // in/out pipe names come from the parameters
  inFile = argv[1];
  outFile = argv[2];

  
 
  // open the pipe for reading in the image names
  fp_in = fopen(inFile, "r");    

  i=0; // counter 
  // read in the image names and put them in an array
  while (!feof(fp_in)){ 
    fscanf(fp_in, "%s", imageArray[i]);
    i++;
  }
  fclose(fp_in); // close the input pipe
  numFiles = i; // keep track of the number of files
    

  // open the pipe for writing out the image names
  fp_out = fopen(outFile, "w+");

  // loop through all the images
  for (i=0; i<numFiles; i++){ 
  
    // generate a new name for the current image
    generateNewName(newname, imageArray[i]);
    
    // construct the command to resize the image
    strcpy( command, "convert ");
    strcat( command, imageArray[i]);
    strcat( command, " -resize 50% ");
    strcat( command, newname);
    strcat( command, " && "); // execute next command if this one succeeds
    
    // add the command to run identify
    strcat( command, "identify " );
    strcat( command, newname);

    // run the command
    pf = popen(command, "r");
    if (!pf){
      fprintf(stderr, "Could not open pipe for command line output.\n");
    }

    // grab the data from running identify
    fgets(result, MAXDIM, pf);
    
    // write out the output of running identify to the out pipe
    fprintf(fp_out, "%s", result);
  }

  // close the out pipe
  fclose(fp_out);

 
  return(0);
}


MasterN.java


/*
 * MasterN.java
 * Emily Flynn
 * CSC 352
 * 10/23/2013
 *
 * This program sends the name of each image it is passed as a
 * parameter to a different worker through a fifo and then receives
 * information on the resized images from a fifo from each of the
 * workers and prints this information to the screen. Fifos are
 * canonically named with indices, and match those created by the
 * script doHomework3_N_workers.sh.
 *
 */

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.FileReader;
import java.io.File;

public class MasterN {

    // prefixes for worker and master pipe names
    private static final String PREFIX_FIFO_OUT = "temp_toWorker";
    private static final String PREFIX_FIFO_IN = "temp_toMaster";
    
    /**
     * Main method for the Master program. Writes out the names of the
     * images into out pipes, then reads in response from in pipes.
     *
     * @param args - the list of images
     */
    public static void main(String[] args){

	// keep track of the number of images
	int numImages = args.length; 
	
	// holders for names for in and out pipes
	String outName;
	String inName;

	// write out the names of all of the images into the outpipes
	// one per out pipe, with each named with the prefix followed
	// by an index
	for (int i=0; i<numImages; i++){
	   
	    outName = PREFIX_FIFO_OUT + Integer.toString(i);
	    try {
		BufferedWriter out = new BufferedWriter(new FileWriter(outName));  
		out.write(args[i]);
		out.close();
	    } catch (IOException e){
		System.out.println("IO Exception at buffered write index "+i+".");
		System.exit(-1);
	    }
	}


	// create an array of bufferedReaders, one for reading information
	// from each worker
	BufferedReader in[] = new BufferedReader[numImages];
   
	// also create an array of booleans to keep track of whether
	// Master is done reading from the fifos
	boolean finish[] = new boolean[numImages];
	for (int i=0; i < numImages; i++){
	    finish[i] = false;
	    inName = PREFIX_FIFO_IN + Integer.toString(i);
	    try {
		in[i] = new BufferedReader(new FileReader(inName));
	    } catch (IOException e){
		System.out.println("Error creating buffered reader");
		System.exit(-1);
	    }
	}

	int numFinish = 0; // count the number that are finished
	
	try {
	    // loop until all of the pipes have been read (1 per image)
	    while (numFinish != numImages){

		// loop through all the pipes
		for (int i=0; i<numImages; i++){	

		    // if this particular pipe is not finished
		    if (!finish[i]){
			
			// check if it is ready
			if (in[i].ready()){
			
			    // if it is, read in the information in the pipe
			    String line = in[i].readLine();
			    while (line != null){
				System.out.println(line);
				line = in[i].readLine();
			    }
			
			    // indicate the pipe has been read from, 
			    // close it, and increment the number of pipes finished
			    finish[i] = true;
			    in[i].close();
			    numFinish++;
			} 		   
		    }
		}
	    
	    }
	} catch (IOException e){
	    System.out.println("Error in reading from pipes.");
	    System.exit(-1);
	}

	System.exit(0);
    }
}