Difference between revisions of "CSC352 Homework 3 Solution 2013"

From dftwiki3
Jump to: navigation, search
Line 3: Line 3:
 
The solution to the optional problem is posted, as it applies also to the first part of the assignment.
 
The solution to the optional problem is posted, as it applies also to the first part of the assignment.
  
[352a@beowulf 352a-ac]$ for i in doHomework3_N_images.sh  workerN.c MasterN.java ; do echo "<br />==${i}==<br />"; echo "<source lang=\"java\">" ; cat $i; echo "</source><br />"; done
+
 
 
<br />
 
<br />
 
==doHomework3_N_images.sh==
 
==doHomework3_N_images.sh==
 
<br />
 
<br />
<source lang="shell">
+
<source lang="bash">
 
#!/bin/bash
 
#!/bin/bash
 
#
 
#

Revision as of 14:45, 25 October 2013

--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 previous pipes to avoid confusion
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);
    }
}