Browse Source

Add code, Minor fixes

master
Apostolos Fanakis 6 years ago
parent
commit
0aa0fcc979
  1. 4
      LICENSE.md
  2. 38
      Makefile
  3. 2
      README.md
  4. 43
      test_sample.c
  5. 187
      test_sample_functions.c
  6. 65
      test_sample_functions.h

4
LICENSE.md

@ -1,7 +1,7 @@
"THE BEER-WARE LICENSE" "THE BEER-WARE LICENSE"
Copyright (c) 2018 Apostolof, charaldp, tsakonag Copyright (c) 2019 Apostolof
As long as you retain this notice you can do whatever you want with this stuff. As long as you retain this notice you can do whatever you want with this stuff.
If we meet some day, and you think this stuff is worth it, you can buy us a If we meet some day, and you think this stuff is worth it, you can buy me a
beer in return. beer in return.

38
Makefile

@ -0,0 +1,38 @@
SHELL := /bin/bash
# ============================================
# COMMANDS
CC = gcc -std=gnu99
RM = rm -f
CFLAGS_DEBUG=-O2 -ggdb3 -Wall -Werror -pedantic -D_FORTIFY_SOURCE=2 -fasynchronous-unwind-tables -grecord-gcc-switches -Werror=implicit-function-declaration -I.
CFLAGS=-O2 -Wall -Werror -pedantic -I.
OBJ=test_sample.o test_sample_functions.o
DEPS=test_sample_functions.h
# ==========================================
# TARGETS
EXECUTABLES = test_sample.out
.PHONY: all clean
all: $(EXECUTABLES)
# ==========================================
# DEPENDENCIES (HEADERS)
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
.PRECIOUS: $(EXECUTABLES) $(OBJ)
# ==========================================
# EXECUTABLE (MAIN)
$(EXECUTABLES): $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
clean:
$(RM) *.o *~ $(EXECUTABLES)

2
README.md

@ -15,7 +15,7 @@ make
``` ```
and then run using: and then run using:
```sh ```sh
./testSample [-t time] [-d delta] [-o output] ./test_sample [-t time] [-d delta] [-o output]
``` ```
where: where:

43
test_sample.c

@ -0,0 +1,43 @@
#include "test_sample_functions.h"
int main(int argc, char **argv) {
Parameters parameters;
parseArguments(argc, argv, &parameters);
//parameters.numberOfSamples = (parameters.time + parameters.delta - 1) / parameters.delta;
parameters.numberOfSamples = 1 + ((parameters.time - 1) / parameters.delta);
// Initialize a matrix to store the sample values
double **samplesMatrix = (double **) malloc(parameters.numberOfSamples * sizeof(double *));
for (int i=0; i<parameters.numberOfSamples; ++i) {
samplesMatrix[i] = (double *) malloc(3 * sizeof(double));
}
// Saves information about the experiment to the output file
{
FILE *outputFile;
outputFile = fopen(parameters.outputFilename, "w");
if (outputFile == NULL) {
printf("Error while opening the output file.\n");
exit(EXIT_FAILURE);
}
fprintf(outputFile, "Sampling experiment will run for %f seconds\n"\
"Sampling period is set to %f seconds.\n"\
"Number of samples should be %d.\n\n",
parameters.time, parameters.delta, parameters.numberOfSamples);
fclose(outputFile);
}
printf(ANSI_COLOR_BLUE "\n----- STARTING EXPERIMENT -----\n" ANSI_COLOR_RESET);
testSampling(&samplesMatrix, parameters);
printf(ANSI_COLOR_YELLOW "\n----- WRITING RESULTS TO OUTPUT FILE -----\n" ANSI_COLOR_RESET);
// Saves results to the output file
saveSamplesToFile(parameters.outputFilename, samplesMatrix, parameters.numberOfSamples);
printf(ANSI_COLOR_GREEN "\n----- DONE -----\n" ANSI_COLOR_RESET);
}

187
test_sample_functions.c

@ -0,0 +1,187 @@
/* ===== INCLUDES ===== */
#include "test_sample_functions.h"
/* ===== CONSTANTS ===== */
const char *ARGUMENT_TIME = "-t";
const char *ARGUMENT_DELTA = "-d";
const char *ARGUMENT_OUTPUT_FILENAME = "-o";
char *DEFAULT_OUTPUT_FILENAME = "sample_test_output";
/* ===== STRUCTURES ===== */
struct timeval startwtime, endwtime;
/* ===== OTHER ===== */
volatile sig_atomic_t sample_flag = false;
/* ===== FUNCTIONS ===== */
/*
* testSampling implements the sampling experiment. Three different ways of sampling are
* implemented. On the first one sleep is used. On the second sleep is used and the sleep times are
* corrected based on the previous error. On the third alarms are used.
*/
void testSampling(double ***samplesMatrix, Parameters parameters) {
printf(ANSI_COLOR_CYAN "\n----- RUNNING FIRST EXPERIMENT -----\n" ANSI_COLOR_RESET);
for (int i = 0; i < parameters.numberOfSamples; ++i) {
gettimeofday (&startwtime, NULL);
usleep(parameters.delta * 1000000);
gettimeofday (&endwtime, NULL);
(*samplesMatrix)[i][0] = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 +
endwtime.tv_sec - startwtime.tv_sec);
}
printf(ANSI_COLOR_CYAN "\n----- RUNNING SECOND EXPERIMENT -----\n" ANSI_COLOR_RESET);
double totalError = 0;
for (int i = 0; i < parameters.numberOfSamples; ++i) {
gettimeofday (&startwtime, NULL);
usleep((parameters.delta - (totalError / (i + 1))) * 1000000);
gettimeofday (&endwtime, NULL);
(*samplesMatrix)[i][1] = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 +
endwtime.tv_sec - startwtime.tv_sec);
totalError += (*samplesMatrix)[i][1] - parameters.delta;
}
printf(ANSI_COLOR_CYAN "\n----- RUNNING THIRD EXPERIMENT -----\n" ANSI_COLOR_RESET);
signal(SIGALRM, handle_alarm);
struct itimerval new;
new.it_interval.tv_usec = (int) ((parameters.delta - ((int) parameters.delta)) * 1000000);
new.it_interval.tv_sec = ((int) parameters.delta);
new.it_value.tv_usec = (int) ((parameters.delta - ((int) parameters.delta)) * 1000000);
new.it_value.tv_sec = ((int) parameters.delta);
if (setitimer (ITIMER_REAL, &new, NULL) == -1) {
perror("setitimer");
exit(EXIT_FAILURE);
}
gettimeofday (&startwtime, NULL);
int i = 0 ;
while(i < parameters.numberOfSamples) {
if (sample_flag) {
sample_flag = false;
gettimeofday (&endwtime, NULL);
(*samplesMatrix)[i][2] = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 +
endwtime.tv_sec - startwtime.tv_sec);
++i;
gettimeofday (&startwtime, NULL);
}
}
//alarm(0); Is this needed?
}
void handle_alarm(int sig) {
sample_flag = true;
}
// ==================== PROGRAM INPUT AND OUTPUT UTILS ====================
/*
* parseArguments parses the command line arguments given by the user.
*/
void parseArguments(int argumentCount, char **argumentVector, Parameters *parameters) {
if (argumentCount > 7) {
validUsage(argumentVector[0]);
}
(*parameters).time = 7200;
(*parameters).delta = 0.1;
(*parameters).outputFilename = DEFAULT_OUTPUT_FILENAME;
char *endPointer;
int argumentIndex = 1;
while (argumentIndex < argumentCount) {
if (!strcmp(argumentVector[argumentIndex], ARGUMENT_TIME)) {
argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]);
double timeInput = strtod(argumentVector[argumentIndex], &endPointer);
if ((timeInput <= 0) && endPointer) {
printf("Invalid time argument\n");
exit(EXIT_FAILURE);
}
(*parameters).time = timeInput;
} else if (!strcmp(argumentVector[argumentIndex], ARGUMENT_DELTA)) {
argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]);
double deltaInput = strtod(argumentVector[argumentIndex], &endPointer);
if ((deltaInput <= 0) && endPointer) {
printf("Invalid time argument\n");
exit(EXIT_FAILURE);
}
(*parameters).delta = deltaInput;
} else if (!strcmp(argumentVector[argumentIndex], ARGUMENT_OUTPUT_FILENAME)) {
argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]);
if (fopen(argumentVector[argumentIndex], "w") == NULL) {
printf("Invalid output filename. Reverting to default.\n");
continue;
}
(*parameters).outputFilename = argumentVector[argumentIndex];
} else {
validUsage(argumentVector[0]);
exit(EXIT_FAILURE);
}
++argumentIndex;
}
}
/*
* validUsage outputs a message to the console that informs the user of the
* correct (valid) way to use the program.
*/
void validUsage(char *programName) {
printf("%s [-t time] [-d delta] [-o output]" \
"\n-t time" \
"\n\ttotal duration of the sampling in seconds" \
"\n-d delta" \
"\n\tsampling period in seconds" \
"\n-o output" \
"\n\tfilename and path for the output" \
"\n", programName);
exit(EXIT_FAILURE);
}
/*
* checkIncrement is a helper function for parseArguments function.
*/
int checkIncrement(int previousIndex, int maxIndex, char *programName) {
if (previousIndex == maxIndex) {
validUsage(programName);
exit(EXIT_FAILURE);
}
return ++previousIndex;
}
void saveSamplesToFile(char *filename, double **samplesMatrix, int matrixRows) {
FILE *outputFile;
outputFile = fopen(filename, "a");
if (outputFile == NULL) {
printf("Error while opening the output file.\n");
return;
}
// Saves the samples matrix
for (int i=0; i<matrixRows; ++i) {
fprintf(outputFile, "%.10g\t%.10g\t%.10g\n",
samplesMatrix[i][0], samplesMatrix[i][1], samplesMatrix[i][2]);
}
fclose(outputFile);
}

65
test_sample_functions.h

@ -0,0 +1,65 @@
#ifndef TEST_SAMPLE_FUNCTIONS_H /* Include guard */
#define TEST_SAMPLE_FUNCTIONS_H
/* ===== INCLUDES ===== */
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <stdbool.h>
/* ===== DEFINITIONS ===== */
//Colors used for better console output formating.
#define ANSI_COLOR_RED "\x1B[31m"
#define ANSI_COLOR_GREEN "\x1B[32m"
#define ANSI_COLOR_YELLOW "\x1B[33m"
#define ANSI_COLOR_BLUE "\x1B[34m"
#define ANSI_COLOR_CYAN "\x1B[36m"
#define ANSI_COLOR_RESET "\x1B[0m"
/* ===== CONSTANTS DEFINITION ===== */
// Constant strings that store the command line options available.
extern const char *ARGUMENT_TIME;
extern const char *ARGUMENT_DELTA;
extern const char *ARGUMENT_OUTPUT_FILENAME;
// Default filename used for the output.
extern char *DEFAULT_OUTPUT_FILENAME;
/* ===== STRUCTURES ===== */
// Structures used in gettimeofday
extern struct timeval startwtime, endwtime;
// A data structure to conveniently hold the algorithm's parameters.
typedef struct parameters {
double time, delta;
char *outputFilename;
int numberOfSamples;
} Parameters;
/* ===== FUNCTION DEFINITIONS ===== */
// Function that implements the sampling experiment.
void testSampling(double ***samplesMatrix, Parameters parameters);
void handle_alarm(int sig);
// Function validUsage outputs the correct way to use the program with command line arguments.
void validUsage(char *programName);
// Function checkIncrement is a helper function used in parseArguments (see bellow).
int checkIncrement(int previousIndex, int maxIndex, char *programName);
// Function parseArguments parses command line arguments.
void parseArguments(int argumentCount, char **argumentVector, Parameters *parameters);
// Function saveSamplesToFile appends the sample matrix "samplesMatrix" to the file with the
// filename supplied in the arguments.
void saveSamplesToFile(char *filename, double **samplesMatrix, int matrixRows);
#endif // TEST_SAMPLE_FUNCTIONS_H
Loading…
Cancel
Save