diff --git a/documents/references.md b/documents/references.md index f0f8b861129839781f6fe260ea3cdd25473e7fa8..dd34e5e015dcfd221a802c74a470d388bfb26d49 100644 --- a/documents/references.md +++ b/documents/references.md @@ -32,6 +32,7 @@ Various references used in project. * Getting File/LineNum: ** <https://stackoverflow.com/a/42135375> ** <https://stackoverflow.com/a/8884408> +* Append variables to strings - <https://stackoverflow.com/a/10219339> <https://stackoverflow.com/a/18997915> #### C++ Classes * General Class Syntax - <https://www.w3schools.com/cpp/cpp_classes.asp> diff --git a/part_1/image.cu b/part_1/image.cu index 779e780b736099284a40b42522b1127914daca27..d776917eb0db90f58c4a93cab142b412916c15e3 100644 --- a/part_1/image.cu +++ b/part_1/image.cu @@ -10,8 +10,17 @@ #include "utility.h" #endif +#ifndef user_headers_logging + #define user_headers_logging + #include "logging.h" +#endif + // Global Variables. +#ifndef LOGGING_CLASS_INIT + #define LOGGING_CLASS_INIT + extern Logging logger; +#endif const Image::Rgb Image::pixelBlack = Image::Rgb(0); const Image::Rgb Image::pixelWhite = Image::Rgb(1); const Image::Rgb Image::pixelRed = Image::Rgb(1,0,0); @@ -28,8 +37,9 @@ const Image::Rgb Image::pixelLiBlue = Image::Rgb(0,1,1); * :param image_path: Path to an image on the system. */ void Image::calculate_paths(std::string image_path) { - // std::cout << "\n\n\n\n\nCalculating input/output paths..." << std::endl; - // std::cout << "image_path: " << image_path << std::endl; + logger.debug("Image::calculate_paths():"); + logger.debug(" image_path: " + image_path); + logger.debug(""); // // Calculate output path location. output_path = "../output/"; @@ -42,7 +52,6 @@ void Image::calculate_paths(std::string image_path) { // Pull current substring value from input path. token = image_path.substr(0, image_path.find("/")); - // std::cout << " " << token << std::endl; image_path.erase(0, pos + 1); // Check if directory value is value we care about. @@ -60,9 +69,6 @@ void Image::calculate_paths(std::string image_path) { } output_path += base_filename; - // std::cout << "output_path: " << output_path << std::endl; - - // std::cout << "Input/output paths calculated.\n\n\n\n\n" << std::endl; } @@ -70,13 +76,16 @@ void Image::calculate_paths(std::string image_path) { * Imports image file data, using class variable data. */ void Image::import_image_file() { + logger.debug("Image::import_image_file():"); + logger.debug(""); + // Open input file. std::ifstream input_file; input_file.open(input_path, std::ios::binary | std::ios::in); if (! input_file.good()) { // Failed to open file. - std::cerr << "Failed to open file \"" + input_path + "\"." << std::endl; + logger.error("Failed to open file \"" + input_path + "\""); } else { // File opened. Grab data. std::string header; @@ -89,7 +98,6 @@ void Image::import_image_file() { input_file >> width >> height >> bit_depth; // Create and populate image. - // std::cout << "Parsing input image" << std::endl; pixel_arr = new Rgb[width * height]; // Skip empty lines in necessary until we get to the binary data. @@ -116,8 +124,10 @@ void Image::import_image_file() { * Base constructor. */ Image::Image() { + logger.debug("Image::Image Constructor():"); + logger.debug(""); + // Currently test logic. - std::cout << "\nConstructing Image class." << std::endl; // Essentially creates a 10x10 pixel test image. input_path = "../input/pbm/400x300/hallway_00.pbm"; @@ -132,8 +142,6 @@ Image::Image() { for (int index = 0; index < (width * height); index++) { pixel_arr[index] = c; } - - std::cout << "Image class populated." << std::endl; } /** @@ -141,15 +149,15 @@ Image::Image() { * Output path is determined based on parsing input path. */ Image::Image(std::string user_path) { - std::cout << "\nConstructing Image class." << std::endl; - - std::cout << "user_path: " << user_path << std::endl; + logger.debug("Image::Image Constructor():"); + logger.debug(" user_path: " + user_path); + logger.debug(""); // Re-validate path for saving to class.. path_validator_struct* return_struct = validate_path(user_path); int path_type = return_struct->file_type; if (return_struct->err_code) { - std::cerr << "Error verifying file type: " << return_struct->err_code.message() << std::endl; + logger.error("Error verifying file type: " + return_struct->err_code.message()); return; } free_path_validator_struct(return_struct); @@ -158,11 +166,9 @@ Image::Image(std::string user_path) { calculate_paths(user_path); import_image_file(); } else { - std::cerr << "Provided path is not to image file. Class initialization failed." << std::endl; + logger.error("Provided path is not to image file. Class initialization failed."); return; } - - std::cout << "Image class populated." << std::endl; } //endregion Constructors. @@ -174,13 +180,16 @@ Image::Image(std::string user_path) { * Displays general properties of image held in class. */ void Image::display_properties() { - std::cout << std::endl; - std::cout << "input file path: " << input_path << std::endl; - std::cout << "output file path: " << output_path << std::endl; - std::cout << "width: " << width << std::endl; - std::cout << "height: " << height << std::endl; - std::cout << "bit depth: " << bit_depth << std::endl; - std::cout << std::endl; + logger.debug("Image::display_properties():"); + logger.debug(""); + + logger.info(""); + logger.info("input file path: " + input_path); + logger.info("output file path: " + output_path); + logger.info("width: " + width); + logger.info("height: " + height); + logger.info("bit depth: " + bit_depth); + logger.info(""); } @@ -188,7 +197,10 @@ void Image::display_properties() { * Saves class image data to output file. */ void Image::save() { - std::cout << "Attempting to save image to \"" << output_path << "\"." << std::endl; + logger.debug("Image::save():"); + logger.debug(""); + + logger.debug("Attempting to save image to \"" + output_path + "\"."); // Open output file stream. std::ofstream output_file; @@ -201,7 +213,7 @@ void Image::save() { // Check if opened successfully. if (output_file.fail()) { // Failed to open. - std::cout << "Failed to open file \"" + output_path + "\".\n"; + logger.error("Failed to open file \"" + output_path + "\""); } else { // Opened successfully. @@ -221,10 +233,10 @@ void Image::save() { // Close file stream. output_file.close(); - std::cout << "Image saved." << std::endl; + logger.info("Image saved."); } catch (const char* err) { - fprintf(stderr, "%s\n", err); + logger.error("Failed to save image: " + std::string(err)); output_file.close(); } } diff --git a/part_1/logging.cu b/part_1/logging.cu index 74ce6a06ec0cb4fedfa65aff755e39aa27d07858..5fb3771f7cbb3a9eeef3df3ed9157c0cabcae9b3 100644 --- a/part_1/logging.cu +++ b/part_1/logging.cu @@ -7,6 +7,7 @@ // User Import Headers. #ifndef user_headers #define user_headers + #define user_headers_logging #include "logging.h" #endif @@ -15,15 +16,21 @@ * Class constructor. */ Logging::Logging() { - std::cout << "Initializing logger." << std::endl; std::filesystem::path cwd = std::filesystem::current_path(); core_logging_folder = cwd.string() + "/log/"; - std::cout << "logging_folder: " << core_logging_folder << std::endl; + + // Check if logging directory exists. + struct stat info; + if ( (stat(core_logging_folder.c_str(), &info) != 0) || (! info.st_mode & S_IFDIR)) { + // Directory does not exist. + mkdir(core_logging_folder.c_str(), 0777); + } // Open file descriptors. - error_stream.open(core_logging_folder + "error.log", std::ios::binary | std::ios::out); - warn_stream.open(core_logging_folder + "warn.log", std::ios::binary | std::ios::out); - info_stream.open(core_logging_folder + "info.log", std::ios::binary | std::ios::out); + error_stream.open(core_logging_folder + "error.log", std::ios::app | std::ios::out); + warn_stream.open(core_logging_folder + "warn.log", std::ios::app | std::ios::out); + info_stream.open(core_logging_folder + "info.log", std::ios::app | std::ios::out); + debug_stream.open(core_logging_folder + "debug.log", std::ios::app | std::ios::out); } /** @@ -31,6 +38,17 @@ Logging::Logging() { * Closes file descriptors, if open. */ Logging::~Logging() { + close_log_files(); +} + + +/** + * Closes all open logging file descriptors. + */ +void Logging::close_log_files() { + if (debug_stream.is_open()) { + debug_stream.close(); + } if (info_stream.is_open()) { info_stream.close(); } @@ -42,29 +60,82 @@ Logging::~Logging() { } } + +/** + * Writes message to info log file. + */ +void Logging::debug(std::string msg, std::string log_type, const char* file, long line_num) { + // Build and write logging message. + std::string log_prefix = " [" + log_type + "] [ " + std::string(file) + " | " + std::to_string(line_num) + " ] "; + debug_stream << log_prefix << msg << std::endl; +} + + /** * Writes message to info log file. */ -void Logging::info(char const* file, long line_num, std::string msg) { - info_stream << msg << std::endl; +void Logging::info(std::string msg, std::string log_type, const char* file, long line_num) { + // Build and write logging message. + std::string log_prefix = " [" + log_type + "] [ " + std::string(file) + " | " + std::to_string(line_num) + " ] "; + info_stream << log_prefix << msg << std::endl; + + // Write to console. + std::cout << log_prefix << msg << std::endl; + + // Also write to lower level loggers. + debug(msg, log_type, file, line_num); } /** * Writes message to warning log file. */ -void Logging::warn(char const* file, long line_num, std::string msg) { - warn_stream << msg << std::endl; +void Logging::warn(std::string msg, std::string log_type, const char* file, long line_num) { + // Build and write logging message. + std::string log_prefix = " [" + log_type + "] [ " + std::string(file) + " | " + std::to_string(line_num) + " ] "; + warn_stream << log_prefix << msg << std::endl; // Also write to lower level loggers. - info(file, line_num, msg); + info(msg, log_type, file, line_num); } /** * Writes message to error log file. */ -void Logging::error(char const* file, long line_num, std::string msg) { - error_stream << msg << std::endl; +void Logging::error(std::string msg, std::string log_type, const char* file, long line_num) { + // Build and write logging message. + std::string log_prefix = " [" + log_type + "] [ " + std::string(file) + " | " + std::to_string(line_num) + " ] "; + error_stream << log_prefix << msg << std::endl; // Also write to lower level loggers. - warn(file, line_num, msg); + warn(msg, log_type, file, line_num); +} + + +/** + * Prints out logging location to console. + */ +void Logging::display_logging_folder() { + std::cout << "Logging folder: " << core_logging_folder << std::endl; +} + + +/** + * Resets contents of logging files. + */ +void Logging::clear_log_files() { + // First close any open logging file descriptors. + close_log_files(); + + // Open log files in "write mode", which will override any present data. + error_stream.open(core_logging_folder + "error.log", std::ios::out); + warn_stream.open(core_logging_folder + "warn.log", std::ios::out); + info_stream.open(core_logging_folder + "info.log", std::ios::out); + debug_stream.open(core_logging_folder + "debug.log", std::ios::out); + + // Close log files and reopen in "append mode". Probably not necessary but here to be safe. + close_log_files(); + error_stream.open(core_logging_folder + "error.log", std::ios::app | std::ios::out); + warn_stream.open(core_logging_folder + "warn.log", std::ios::app | std::ios::out); + info_stream.open(core_logging_folder + "info.log", std::ios::app | std::ios::out); + debug_stream.open(core_logging_folder + "debug.log", std::ios::out); } diff --git a/part_1/logging.h b/part_1/logging.h index b21751935af5c6b1080d18ac9256f68be8897a02..2d7d38e524853c5a70cc70755ea97f1afa869525 100644 --- a/part_1/logging.h +++ b/part_1/logging.h @@ -7,6 +7,7 @@ #include <cstdio> #include <cstdlib> #include <cctype> +#include <execinfo.h> #include <iostream> #include <filesystem> #include <fstream> @@ -22,6 +23,7 @@ class Logging { private: std::string core_logging_folder; + std::ofstream debug_stream; std::ofstream info_stream; std::ofstream warn_stream; std::ofstream error_stream; @@ -38,19 +40,38 @@ class Logging { */ ~Logging(); + /** + * Closes all open logging file descriptors. + */ + void close_log_files(); + + /** + * Writes message to info log file. + */ + void debug(std::string msg, std::string log_type = "DEBUG", const char* file = __builtin_FILE(), long line_num = __builtin_LINE()); + /** * Writes message to info log file. */ - void info(char const* file, long line_num, std::string msg); + void info(std::string msg, std::string log_type = "INFO", const char* file = __builtin_FILE(), long line_num = __builtin_LINE()); /** * Writes message to warning log file. */ - void warn(char const* file, long line_num, std::string msg); + void warn(std::string msg, std::string log_type = "WARN", const char* file = __builtin_FILE(), long line_num = __builtin_LINE()); /** * Writes message to error log file. */ - void error(char const* file, long line_num, std::string msg); -}; + void error(std::string msg, std::string log_type = "ERROR", const char* file = __builtin_FILE(), long line_num = __builtin_LINE()); + + /** + * Prints out logging location to console. + */ + void display_logging_folder(); + /** + * Resets contents of logging files. + */ + void clear_log_files(); +}; diff --git a/part_1/main.cu b/part_1/main.cu index d7950db864d917b5aa43c1217e476c4814f36953..5710a71bc3c0e8245b861e94e368f4b8712af91a 100644 --- a/part_1/main.cu +++ b/part_1/main.cu @@ -17,11 +17,15 @@ // User Import Headers. #ifndef user_headers #define user_headers - #include "logging.h" #include "image.h" #include "utility.h" #endif +#ifndef user_headers_logging + #define user_headers_logging + #include "logging.h" +#endif + // Method Declaration. void process_dir(std::string path_str); @@ -32,6 +36,10 @@ void process_file(std::string path_str); // Global Variables. +#ifndef LOGGING_CLASS_INIT + #define LOGGING_CLASS_INIT + Logging logger; +#endif /* @@ -42,36 +50,37 @@ int main(int argc, char* argv[]) { printf("\n"); printf("\n"); - Logging logger; + // Initialize logging and clear any existing log contents for new program run. + logger.clear_log_files(); + + // Check provided number of args. + if (argc < 2) { + // No args provided. + printf("Provided too few program args. Expected one arg."); + } else if (argc > 2) { + // More than one arg provided. + printf("Provided too many program args. Expected one arg."); + } else { + // Correct number of args provided. Pass to image class for processing. + + // Check data type. + std::string path_str = argv[1]; + path_validator_struct* return_struct = validate_path(path_str); + int path_type = return_struct->file_type; + if (return_struct->err_code) { + std::cerr << "Error verifying file type: " << return_struct->err_code.message() << std::endl; + } + free_path_validator_struct(return_struct); - // // Check provided number of args. - // if (argc < 2) { - // // No args provided. - // printf("Provided too few program args. Expected one arg."); - // } else if (argc > 2) { - // // More than one arg provided. - // printf("Provided too many program args. Expected one arg."); - // } else { - // // Correct number of args provided. Pass to image class for processing. - - // // Check data type. - // std::string path_str = argv[1]; - // path_validator_struct* return_struct = validate_path(path_str); - // int path_type = return_struct->file_type; - // if (return_struct->err_code) { - // std::cerr << "Error verifying file type: " << return_struct->err_code.message() << std::endl; - // } - // free_path_validator_struct(return_struct); - - // // Handle based on provided type. - // if (path_type == TYPE_DIR) { - // // Process dir. - // process_dir(path_str); - // } else if (path_type == TYPE_FILE) { - // // Process file. - // process_file(path_str); - // } - // } + // Handle based on provided type. + if (path_type == TYPE_DIR) { + // Process dir. + process_dir(path_str); + } else if (path_type == TYPE_FILE) { + // Process file. + process_file(path_str); + } + } printf("\n"); printf("\n"); @@ -85,7 +94,11 @@ int main(int argc, char* argv[]) { * Assumes directory is full of image files. */ void process_dir(std::string path_str) { - std::cout << "Handling dir." << std::endl; + logger.debug("process_dir():"); + logger.debug(" path_str: " + path_str); + logger.debug(""); + + logger.info("Handling dir."); // Process all files in directory. for (const auto & entry : std::filesystem::directory_iterator(path_str)) { @@ -120,7 +133,11 @@ void process_dir(std::string path_str) { * Processes a single image file. */ void process_file(std::string path_str) { - std::cout << "Handling file." << std::endl; + logger.debug("process_file():"); + logger.debug(" path_str: " + path_str); + logger.debug(""); + + logger.info("Handling file."); Image image(path_str); image.display_properties(); diff --git a/part_1/utility.cu b/part_1/utility.cu index ec66384d93d8fced1de670a5e73984a8bf4df0ff..d585b055a8e974d7e07d506485e8a842cd35839c 100644 --- a/part_1/utility.cu +++ b/part_1/utility.cu @@ -8,8 +8,17 @@ #include "utility.h" #endif +#ifndef user_headers_logging + #define user_headers_logging + #include "logging.h" +#endif + // Global Variables. +#ifndef LOGGING_CLASS_INIT + #define LOGGING_CLASS_INIT + extern Logging logger; +#endif const int TYPE_DIR = 0; const int TYPE_FILE = 1; const int TYPE_OTHER = 2; @@ -20,16 +29,10 @@ path_validator_struct* path_validator_ptr; * Initializes a "path_validator" object. */ path_validator_struct* initialize_path_validator_struct(int file_type, std::error_code err_code) { - - // printf("\n"); - // printf("initialize_path_validator_struct:\n"); - // printf(" file_type: %i\n", file_type); - // if (err_code) { - // std::cerr << " err_code: " << err_code.message(); - // } else { - // printf(" err_code: null\n"); - // } - // printf("\n"); + logger.debug("initialize_path_validator_struct():"); + logger.debug(" file_type: " + std::to_string(file_type)); + // logger.debug(" err_code: " + err_code); + logger.debug(""); // Create struct. path_validator_ptr = (path_validator_struct*) calloc(1, sizeof(path_validator_struct)); @@ -46,6 +49,10 @@ path_validator_struct* initialize_path_validator_struct(int file_type, std::erro * Destroyes passed "path_validator" object and all associated fields. */ void free_path_validator_struct(path_validator_struct* path_validator_ptr) { + logger.debug("free_path_validator_struct():"); + // logger.debug(" path_validator_ptr: " + path_validator_ptr); + logger.debug(""); + free(path_validator_ptr); } @@ -55,11 +62,13 @@ void free_path_validator_struct(path_validator_struct* path_validator_ptr) { * Returns struct of data. */ path_validator_struct* validate_path(std::string path_str) { + logger.debug("validate_path():"); + logger.debug(" path_str: " + path_str); + logger.debug(""); + int type_value = TYPE_OTHER; std::error_code ec; - std::cout << "path_str: \"" + path_str + "\"\n"; - // Check if provided path exists. std::ifstream test_path_exists(path_str); if (test_path_exists) {