Commit 0de5ece0 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Update doxygen documentation, remove unused functions

parent 1ab4818a
...@@ -33,8 +33,6 @@ ...@@ -33,8 +33,6 @@
#include "camogm_kml.h" #include "camogm_kml.h"
#include "camogm_read.h" #include "camogm_read.h"
/** @brief Time interval (in microseconds) for processing commands */
#define COMMAND_LOOP_DELAY 500000 //0.5sec
/** @brief Default debug level */ /** @brief Default debug level */
#define DEFAULT_DEBUG_LVL 6 #define DEFAULT_DEBUG_LVL 6
/** @brief JPEG trailer syze in bytes */ /** @brief JPEG trailer syze in bytes */
......
...@@ -61,6 +61,8 @@ ...@@ -61,6 +61,8 @@
/** @brief Maximum length of file or raw device path */ /** @brief Maximum length of file or raw device path */
#define ELPHEL_PATH_MAX 300 #define ELPHEL_PATH_MAX 300
#define MMAP_CHUNK_SIZE 10485760 #define MMAP_CHUNK_SIZE 10485760
/** @brief Time interval (in microseconds) for processing commands */
#define COMMAND_LOOP_DELAY 500000
/** /**
* @enum state_flags * @enum state_flags
......
/** @file camogm_read.c /** @file camogm_read.c
* @brief Provides reading data written to raw device storage and saving the data to a device with file system. * @brief Provides reading data written to raw device storage and transmitting the data over a socket.
* @copyright Copyright (C) 2016 Elphel, Inc. * @copyright Copyright (C) 2016 Elphel, Inc.
* *
* @par <b>License</b> * @par <b>License</b>
...@@ -15,17 +15,24 @@ ...@@ -15,17 +15,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @brief This define is needed to use lseek64 and should be set before includes */ /**
* @addtogroup SPECIAL_INCLUDES Special includes
* These defines are needed to use lseek64, strptime and usleep and should be set before includes
* @{
*/
/** Needed for lseek64 */
#define _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE
/** Needed for strptime and usleep */
#define _XOPEN_SOURCE #define _XOPEN_SOURCE
/** Needed for usleep */
#define _XOPEN_SOURCE_EXTENDED #define _XOPEN_SOURCE_EXTENDED
/** @} */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <getopt.h>
#include <string.h> #include <string.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <netinet/in.h> #include <netinet/in.h>
...@@ -43,21 +50,22 @@ ...@@ -43,21 +50,22 @@
/** @brief Offset in Exif where TIFF header starts */ /** @brief Offset in Exif where TIFF header starts */
#define TIFF_HDR_OFFSET 12 #define TIFF_HDR_OFFSET 12
/** @brief Separator character between seconds and microseconds in JPEG file name */ /** @brief The date and time format of Exif field */
#define SUBSEC_SEPARATOR '.'
#define EXIF_DATE_TIME_FORMAT "%Y:%m:%d %H:%M:%S" #define EXIF_DATE_TIME_FORMAT "%Y:%m:%d %H:%M:%S"
/** @brief The delimiters used to separate several commands in one command string sent over socket */
#define CMD_DELIMITER "/?" #define CMD_DELIMITER "/?"
/** @brief The length of a buffer for command string */
#define CMD_BUFF_LEN 1024 #define CMD_BUFF_LEN 1024
/** @brief The length of a buffer for string formatting */
#define SMALL_BUFF_LEN 32 #define SMALL_BUFF_LEN 32
#define COMMAND_LOOP_DELAY 500000 /** @brief 64 bit mask to align offsets to 4 kb page boundary */
#define PAGE_BOUNDARY_MASK 0xffffffffffffe000 #define PAGE_BOUNDARY_MASK 0xffffffffffffe000
/** @brief The format string used for file parameters reporting. Time and port number are extracted from Exif */
#define INDEX_FORMAT_STR "port_number=%d;unix_time=%ld;usec_time=%06u;offset=0x%010llx;file_size=%u\n" #define INDEX_FORMAT_STR "port_number=%d;unix_time=%ld;usec_time=%06u;offset=0x%010llx;file_size=%u\n"
/** @brief The size of read buffer in bytes. The data will be read from disk in blocks of this size */ /** @brief The size of read buffer in bytes. The data will be read from disk in blocks of this size */
#define PHY_BLK_SZ 4096 #define PHY_BLK_SZ 4096
/** @brief Include or exclude file start and stop markers from resulting file. This must be set to 1 for JPEG files */ /** @brief Include or exclude file start and stop markers from resulting file. This must be set to 1 for JPEG files */
#define INCLUDE_MARKERS 1 #define INCLUDE_MARKERS 1
/** @brief The amount of free disk space in bytes that should be left on the device during copying from raw device buffer to this disk */
#define FREE_SIZE_LIMIT 10485760
/** @brief File starting marker on a raw device. It corresponds to SOI JPEG marker */ /** @brief File starting marker on a raw device. It corresponds to SOI JPEG marker */
static unsigned char elphelst[] = {0xff, 0xd8}; static unsigned char elphelst[] = {0xff, 0xd8};
/** @brief File ending marker on a raw device. It corresponds to EOI JPEG marker */ /** @brief File ending marker on a raw device. It corresponds to EOI JPEG marker */
...@@ -71,6 +79,9 @@ static const struct iovec elphel_en = { ...@@ -71,6 +79,9 @@ static const struct iovec elphel_en = {
.iov_len = sizeof(elphelen) .iov_len = sizeof(elphelen)
}; };
/** @brief X Macro for commands. Add new commands to @e COMMAND_TABLE
* @{
*/
#define COMMAND_TABLE \ #define COMMAND_TABLE \
X(CMD_BUILD_INDEX, "build_index") \ X(CMD_BUILD_INDEX, "build_index") \
X(CMD_GET_INDEX, "get_index") \ X(CMD_GET_INDEX, "get_index") \
...@@ -79,6 +90,7 @@ static const struct iovec elphel_en = { ...@@ -79,6 +90,7 @@ static const struct iovec elphel_en = {
X(CMD_READ_ALL_FILES, "read_all_files") \ X(CMD_READ_ALL_FILES, "read_all_files") \
X(CMD_STATUS, "status") X(CMD_STATUS, "status")
/** @enum socket_commands */
#define X(a, b) a, #define X(a, b) a,
enum socket_commands { enum socket_commands {
COMMAND_TABLE COMMAND_TABLE
...@@ -90,31 +102,7 @@ static const char *cmd_list[] = { ...@@ -90,31 +102,7 @@ static const char *cmd_list[] = {
COMMAND_TABLE COMMAND_TABLE
}; };
#undef X #undef X
/** @} */
/**
* @enum file_result
* @brief Return codes for file operations
* @var file_result::FILE_OK
* File operation has finished successfully
* @var file_result::FILE_WR_ERR
* An error occurred during file write
* @var file_result::FILE_RD_ERR
* An error occurred during file read
* @var file_result::FILE_OPEN_ERR
* Unable to open file
* @var file_result::FILE_CLOSE_ERR
* An error occurred during file close
* @var file_result::FILE_OPT_ERR
* Other file access errors
*/
enum file_result {
FILE_OK = 0,
FILE_WR_ERR = -1,
FILE_RD_ERR = -2,
FILE_OPEN_ERR = -3,
FILE_CLOSE_ERR = -4,
FILE_OPT_ERR = -5
};
/** /**
* @enum match_result * @enum match_result
...@@ -133,24 +121,15 @@ enum match_result { ...@@ -133,24 +121,15 @@ enum match_result {
}; };
/** /**
* @enum file_ops * @enum search_state
* @brief The states of file operations * @brief The state of the program during file search in raw device buffer
* @var file_ops::WRITE_START * @var search_state::SEARCH_SKIP
* Start writing data to a new file * Skip data in read buffer
* @var file_ops::WRITE_RUNNING * @var search_state::SEARCH_FILE_DATA
* Current data chunk will be written to already opened file * The data in read buffer is a file data with known start offset
* @var file_ops::WRITE_STOP
* Write current data chunk to a file and close it
*/ */
enum file_ops {
WRITE_START,
WRITE_RUNNING,
WRITE_STOP
};
enum search_state { enum search_state {
SEARCH_SKIP, SEARCH_SKIP,
SEARCH_FILE_START,
SEARCH_FILE_DATA SEARCH_FILE_DATA
}; };
...@@ -216,23 +195,6 @@ struct tiff_hdr { ...@@ -216,23 +195,6 @@ struct tiff_hdr {
unsigned long offset; unsigned long offset;
}; };
/**
* @struct file_opts
* @brief This structure holds data associated with currently opened file.
* @var file_opts::fh
* FILE pointer
* @var file_opts::file_cntr
* Indicates the number of files read from raw storage device
* @var file_opts::file_state
* Contains the state of current file operation which can be one from #file_ops enum
*/
struct file_opts {
FILE *fh;
unsigned int file_cntr;
int file_state;
camogm_state *state;
};
/** /**
* @struct crb_ptrs * @struct crb_ptrs
* @brief A set of vectors pointing to a file marker crossing read buffer boundary. * @brief A set of vectors pointing to a file marker crossing read buffer boundary.
...@@ -246,10 +208,22 @@ struct crb_ptrs { ...@@ -246,10 +208,22 @@ struct crb_ptrs {
struct iovec second_buff; struct iovec second_buff;
}; };
/**
* @struct exit_state
* @brief Container for the resources which should be freed before exit
* @var exit_state::state
* Pointer to #camogm_state structure containing current program state. This structure holds
* file descriptors and memory mapped regions which should be closed and unmapped accordingly
* @var exit_state::idir
* Pointer to disk index directory. The nodes of this directory are dynamically allocated and must be freed
* @var exit_state::sockfd_const
* Socket descriptor
* @var exit_state::sockfd_temp
* Socket descriptor
*/
struct exit_state { struct exit_state {
camogm_state *state; camogm_state *state;
struct disk_idir *idir; struct disk_idir *idir;
int ret_val;
int *sockfd_const; int *sockfd_const;
int *sockfd_temp; int *sockfd_temp;
}; };
...@@ -257,6 +231,11 @@ struct exit_state { ...@@ -257,6 +231,11 @@ struct exit_state {
static inline void exit_thread(void *arg); static inline void exit_thread(void *arg);
static void build_index(camogm_state *state, struct disk_idir *idir); static void build_index(camogm_state *state, struct disk_idir *idir);
/**
* @brief Debug function, prints the content of disk index directory
* @param[in] idir pointer to disk index directory to be printed
* @return none
*/
void dump_index_dir(const struct disk_idir *idir) void dump_index_dir(const struct disk_idir *idir)
{ {
struct disk_index *ind = idir->head; struct disk_index *ind = idir->head;
...@@ -268,6 +247,11 @@ void dump_index_dir(const struct disk_idir *idir) ...@@ -268,6 +247,11 @@ void dump_index_dir(const struct disk_idir *idir)
} }
} }
/**
* @brief Create a new node in a linked list of disk indexes
* @param[in,out] index pointer to a newly allocated structure
* @return 0 in case a new disk index structure was successfully created and -1 otherwise
*/
int create_node(struct disk_index **index) int create_node(struct disk_index **index)
{ {
if (*index != NULL) if (*index != NULL)
...@@ -282,6 +266,12 @@ int create_node(struct disk_index **index) ...@@ -282,6 +266,12 @@ int create_node(struct disk_index **index)
} }
} }
/**
* @brief Add a new index node to disk index directory
* @param[in,out] idir pointer to disk index directory
* @param[in] index pointer to index node to be added to disk index directory
* @return The number of entries in disk index directory
*/
int add_node(struct disk_idir *idir, struct disk_index *index) int add_node(struct disk_idir *idir, struct disk_index *index)
{ {
if (idir->head == NULL && idir->tail == NULL) { if (idir->head == NULL && idir->tail == NULL) {
...@@ -298,6 +288,12 @@ int add_node(struct disk_idir *idir, struct disk_index *index) ...@@ -298,6 +288,12 @@ int add_node(struct disk_idir *idir, struct disk_index *index)
return idir->size; return idir->size;
} }
/**
* @brief Find index node by its start offset
* @param[in] idir pointer to disk index directory
* @param[in] offset the offset of the file which should be found
* @return pointer to disk index node or NULL if the corresponding file was not found
*/
struct disk_index *find_by_offset(const struct disk_idir *idir, uint64_t offset) struct disk_index *find_by_offset(const struct disk_idir *idir, uint64_t offset)
{ {
struct disk_index *index = idir->head; struct disk_index *index = idir->head;
...@@ -311,6 +307,12 @@ struct disk_index *find_by_offset(const struct disk_idir *idir, uint64_t offset) ...@@ -311,6 +307,12 @@ struct disk_index *find_by_offset(const struct disk_idir *idir, uint64_t offset)
return index; return index;
} }
/**
* @brief Remove a single index node from disk index directory
* @param[in,out] idir pointer to disk index directory
* @param[in] node pointer to the index node which should be removed
* @return The number of entries in disk index directory
*/
int remove_node(struct disk_idir *idir, struct disk_index *node) int remove_node(struct disk_idir *idir, struct disk_index *node)
{ {
if (node == NULL) if (node == NULL)
...@@ -340,6 +342,11 @@ int remove_node(struct disk_idir *idir, struct disk_index *node) ...@@ -340,6 +342,11 @@ int remove_node(struct disk_idir *idir, struct disk_index *node)
return idir->size; return idir->size;
} }
/**
* Remove all entries from disk index directory an free memory
* @param[in] idir pointer to disk index directory
* @return 0 in case the directory was successfully deleted and -1 if the directory was empty
*/
int delete_idir(struct disk_idir *idir) int delete_idir(struct disk_idir *idir)
{ {
struct disk_index *curr_ind; struct disk_index *curr_ind;
...@@ -371,6 +378,7 @@ int delete_idir(struct disk_idir *idir) ...@@ -371,6 +378,7 @@ int delete_idir(struct disk_idir *idir)
* @param[in] buff_sz size of the data array * @param[in] buff_sz size of the data array
* @param[in] pattern pointer to an array of char values containing pattern * @param[in] pattern pointer to an array of char values containing pattern
* @param[in] pt_sz size of the pattern array * @param[in] pt_sz size of the pattern array
* @param[in] add_pattern include or exclude marker from resulting buffer offset
* @return the index in data buffer where pattern matches or error code from #match_result if it was not found * @return the index in data buffer where pattern matches or error code from #match_result if it was not found
*/ */
static int find_marker(const unsigned char * restrict buff_ptr, ssize_t buff_sz, const unsigned char * restrict pattern, ssize_t pt_sz, static int find_marker(const unsigned char * restrict buff_ptr, ssize_t buff_sz, const unsigned char * restrict pattern, ssize_t pt_sz,
...@@ -433,14 +441,11 @@ static void hdr_byte_order(struct tiff_hdr *hdr) ...@@ -433,14 +441,11 @@ static void hdr_byte_order(struct tiff_hdr *hdr)
} }
/** /**
* @brief Read a string from Exif for a given record. This function is intended for * @brief Read a string from Exif for a given record.
* reading date and time from Exif and it omits any non-digit symbols from resulting string.
* Spaces and tabs are converted to underscores. Terminating null byte is not added to the resulting string.
* @param[in] state a pointer to a structure containing current state * @param[in] state a pointer to a structure containing current state
* @param[in] ifd Exif image file directory record containing string offset * @param[in] tag Exif image file directory record containing string offset
* @param[out] buff buffer for the string * @param[out] buff buffer for the string to be read
* @return The number of bytes placed to the read buffer * @return The number of bytes placed to the read buffer
* @todo update description
*/ */
static size_t exif_get_text(camogm_state *state, struct ifd_entry *tag, char *buff) static size_t exif_get_text(camogm_state *state, struct ifd_entry *tag, char *buff)
{ {
...@@ -455,21 +460,11 @@ static size_t exif_get_text(camogm_state *state, struct ifd_entry *tag, char *bu ...@@ -455,21 +460,11 @@ static size_t exif_get_text(camogm_state *state, struct ifd_entry *tag, char *bu
} }
/** /**
* @brief Create JPEG file name from Exif data * @brief Read Exif data from the file starting from #rawdev_buffer::file_start offset and
* * create a new node in disk index directory
* This function reads Exif data from file, extracts PageNumber, DateTimeOriginal and
* SubSecTimeOriginal fields and assembles a file name in the following format:
*
* NN_YYYYMMDD_HHMMSS.UUUUUU.jpeg
*
* where NN is PageNumber; YYYY, MM and DD are year, month and date extracted from DateTimeOriginal
* field; HH, MM and SS are hours, minutes and seconds extracted from DateTimeOriginal field; UUUUUU is us
* value extracted from SubSecTimeOriginal field. The function assumes that @e name buffer is big enough
* to hold the file name in the format shown above including the terminating null byte.
* @param[in] state a pointer to a structure containing current state * @param[in] state a pointer to a structure containing current state
* @param[out] name resulting file name * @param[in,out] idir pointer to disk index directory
* @return 0 if file name was successfully created and negative value otherwise * @return 0 if new node was successfully added and -1 otherwise
* @todo update description
*/ */
static int save_index(camogm_state *state, struct disk_idir *idir) static int save_index(camogm_state *state, struct disk_idir *idir)
{ {
...@@ -486,7 +481,7 @@ static int save_index(camogm_state *state, struct disk_idir *idir) ...@@ -486,7 +481,7 @@ static int save_index(camogm_state *state, struct disk_idir *idir)
struct ifd_entry ifd_subsec = {0}; struct ifd_entry ifd_subsec = {0};
struct disk_index *node = NULL; struct disk_index *node = NULL;
unsigned char read_buff[TIFF_HDR_OFFSET] = {0}; unsigned char read_buff[TIFF_HDR_OFFSET] = {0};
char str_buff[32] = {0}; char str_buff[SMALL_BUFF_LEN] = {0};
uint64_t save_pos = lseek64(state->rawdev.rawdev_fd, 0, SEEK_CUR); uint64_t save_pos = lseek64(state->rawdev.rawdev_fd, 0, SEEK_CUR);
if (idir == NULL) if (idir == NULL)
...@@ -562,7 +557,14 @@ static int save_index(camogm_state *state, struct disk_idir *idir) ...@@ -562,7 +557,14 @@ static int save_index(camogm_state *state, struct disk_idir *idir)
return ret; return ret;
} }
/* pos_stop points to the last byte of pattern thus the size should be incremented by 1 */ /**
* @brief Calculate the size of current file and update the value in disk index directory
* @param[in,out] idir pointer to disk index directory
* @param[in] pos_stop the offset of the last byte of the current file
* @return 0 if the file size was successfully updated and -1 otherwise
* @note @e pos_stop points to the last byte of the file marker thus the size is incremented
* by 1
*/
int stop_index(struct disk_idir *idir, uint64_t pos_stop) int stop_index(struct disk_idir *idir, uint64_t pos_stop)
{ {
int ret = 0; int ret = 0;
...@@ -574,45 +576,6 @@ int stop_index(struct disk_idir *idir, uint64_t pos_stop) ...@@ -574,45 +576,6 @@ int stop_index(struct disk_idir *idir, uint64_t pos_stop)
return ret; return ret;
} }
/**
* @brief Create new file name, check free space on disk and open a file
* @param[in] f_op pointer to a structure holding information about currently opened file
* @return \e FILE_OK if file was successfully opened and negative error code otherwise
*/
//static int start_new_file(struct file_opts *f_op)
//{
// int ret;
// int err;
// struct statvfs vfs;
// uint64_t free_size = 0;
// char file_name[ELPHEL_PATH_MAX] = {0};
//
// memset(&vfs, 0, sizeof(struct statvfs));
// ret = statvfs(f_op->state->path_prefix, &vfs);
// if (ret != 0) {
// D0(fprintf(debug_file, "Unable to get free size on disk, statvfs() returned %d\n", ret));
// return -CAMOGM_FRAME_FILE_ERR;
// }
// free_size = (uint64_t)vfs.f_bsize * (uint64_t)vfs.f_bfree;
// // statvfs can return irrelevant values in some fields for unsupported file systems,
// // thus free_size is checked to be equal to non-zero value
// if (free_size > 0 && free_size < FREE_SIZE_LIMIT) {
// return -CAMOGM_NO_SPACE;
// }
//
//// make_fname(f_op->state, file_name);
// sprintf(f_op->state->path, "%s%s", f_op->state->path_prefix, file_name);
//
// if ((f_op->fh = fopen(f_op->state->path, "w")) == NULL) {
// err = errno;
// D0(fprintf(debug_file, "Error opening %s for writing\n", file_name));
// D0(fprintf(debug_file, "%s\n", strerror(err)));
// return -CAMOGM_FRAME_FILE_ERR;
// }
//
// return FILE_OK;
//}
/** /**
* @brief Detect cases when file marker crosses read buffer boundary * @brief Detect cases when file marker crosses read buffer boundary
* @param[in] from pointer to current read buffer which can hold the beginning of * @param[in] from pointer to current read buffer which can hold the beginning of
...@@ -669,61 +632,12 @@ static int check_edge_case(const struct iovec *from, const struct iovec *to, con ...@@ -669,61 +632,12 @@ static int check_edge_case(const struct iovec *from, const struct iovec *to, con
} }
/** /**
* @brief Perform file operation in accordance with current file state. * @brief Send mmaped buffer over opened socket
* @param[in] f_op pointer to a structure holding information about currently opened file * @param[in] sockfd opened socket descriptor
* @param[in] from start pointer to data buffer * @param[in] buff pointer to memory mapped buffer
* @param[in] to end pointer to data buffer * @param[in] sz the size of @e buff
* @return a constant of #file_result type * @return none
*/ */
//static int write_buffer(struct file_opts *f_op, unsigned char *from, unsigned char *to)
//{
// int ret = FILE_OK;
// int len;
// unsigned int sz;
//
// sz = to - from;
// switch (f_op->file_state) {
// case WRITE_RUNNING:
// len = fwrite(from, sz, 1, f_op->fh);
// if (len != 1) {
// perror(__func__);
// ret = FILE_WR_ERR;
// }
// break;
// case WRITE_START:
// if ((ret = start_new_file(f_op)) == FILE_OK) {
// len = fwrite(from, sz, 1, f_op->fh);
// if (len != 1) {
// perror(__func__);
// ret = FILE_WR_ERR;
// }
// } else {
// if (ret == -CAMOGM_NO_SPACE)
// D0(fprintf(debug_file, "No free space left on the disk\n"));
// f_op->fh = NULL;
// ret = FILE_OPEN_ERR;
// }
// break;
// case WRITE_STOP:
// len = fwrite(from, sz, 1, f_op->fh);
// if (len != 1) {
// perror(__func__);
// ret = FILE_WR_ERR;
// }
// if (fclose(f_op->fh) != 0) {
// perror(__func__);
// ret = FILE_CLOSE_ERR;
// } else {
// f_op->fh = NULL;
// f_op->file_cntr++;
// }
// break;
// default:
// ret = FILE_OPT_ERR;
// }
// return ret;
//}
void send_buffer(int sockfd, unsigned char *buff, size_t sz) void send_buffer(int sockfd, unsigned char *buff, size_t sz)
{ {
size_t bytes_left = sz; size_t bytes_left = sz;
...@@ -741,6 +655,14 @@ void send_buffer(int sockfd, unsigned char *buff, size_t sz) ...@@ -741,6 +655,14 @@ void send_buffer(int sockfd, unsigned char *buff, size_t sz)
} }
} }
/**
* @brief Map a piece of raw device buffer to memory
* @param[in,out] rawdev pointer to #rawdev_buffer structure containing
* the current state of raw device buffer
* @param[in] range pointer to #range structure holding the offsets of
* mmaped region
* @return 0 in case the region was mmaped successfully and -1 in case of an error
*/
int mmap_disk(rawdev_buffer *rawdev, const struct range *range) int mmap_disk(rawdev_buffer *rawdev, const struct range *range)
{ {
int ret = 0; int ret = 0;
...@@ -762,6 +684,12 @@ int mmap_disk(rawdev_buffer *rawdev, const struct range *range) ...@@ -762,6 +684,12 @@ int mmap_disk(rawdev_buffer *rawdev, const struct range *range)
return ret; return ret;
} }
/**
* @brief Unmap currently mapped raw device buffer
* @param[in,out] rawdev pointer to #rawdev_buffer structure containing
* the current state of raw device buffer
* @return 0 in case the region was unmapped successfully and -1 in case of an error
*/
int munmap_disk(rawdev_buffer *rawdev) int munmap_disk(rawdev_buffer *rawdev)
{ {
if (rawdev->disk_mmap == NULL) if (rawdev->disk_mmap == NULL)
...@@ -777,6 +705,14 @@ int munmap_disk(rawdev_buffer *rawdev) ...@@ -777,6 +705,14 @@ int munmap_disk(rawdev_buffer *rawdev)
return 0; return 0;
} }
/**
* @brief Check if the file pointed by disk index node is in the memory mapped region
* @param[in] range pointer to #range structure holding the offsets of
* memory mapped region
* @param[in] indx pointer to the disk index node which should be checked for
* presence in currently mapped region
* @return @b true if the file is the region and @b false otherwise
*/
bool is_in_range(struct range *range, struct disk_index *indx) bool is_in_range(struct range *range, struct disk_index *indx)
{ {
if (indx->f_offset >= range->from && if (indx->f_offset >= range->from &&
...@@ -788,6 +724,11 @@ bool is_in_range(struct range *range, struct disk_index *indx) ...@@ -788,6 +724,11 @@ bool is_in_range(struct range *range, struct disk_index *indx)
} }
#define PORT_NUMBER 3456 #define PORT_NUMBER 3456
/**
* @brief Prepare socket for communication
* @param[out] socket_fd pointer to socket descriptor
* @return none
*/
void prep_socket(int *socket_fd) void prep_socket(int *socket_fd)
{ {
int opt = 1; int opt = 1;
...@@ -803,10 +744,11 @@ void prep_socket(int *socket_fd) ...@@ -803,10 +744,11 @@ void prep_socket(int *socket_fd)
} }
/** /**
* * @brief Parse command line
* @param cmd * @param[in] cmd pointer to command line buffer, this pointer is
* cmd pointer is updated to point to current command * updated to point to current command
* @return -1 command not recognized, -2 end of buffer * @return Positive command number from #socket_commands, -1 if command not recognized and
* -2 to indicate that the command buffer has been fully processed
*/ */
int parse_command(char **cmd) int parse_command(char **cmd)
{ {
...@@ -838,6 +780,8 @@ int parse_command(char **cmd) ...@@ -838,6 +780,8 @@ int parse_command(char **cmd)
* @brief Break HTTP GET string after the command part as we do not need that part. The function * @brief Break HTTP GET string after the command part as we do not need that part. The function
* finds the first space character after the command part starts and replaces it with null. * finds the first space character after the command part starts and replaces it with null.
* @param[in,out] cmd pointer to HTTP GET string * @param[in,out] cmd pointer to HTTP GET string
* @param[in] cmd_len the length of the command in buffer
* @return none
*/ */
void trim_command(char *cmd, ssize_t cmd_len) void trim_command(char *cmd, ssize_t cmd_len)
{ {
...@@ -853,6 +797,14 @@ void trim_command(char *cmd, ssize_t cmd_len) ...@@ -853,6 +797,14 @@ void trim_command(char *cmd, ssize_t cmd_len)
} }
} }
/**
* @brief Send a file crossing raw device buffer boundary.
* Such a file is split into two parts, the one in the end of the buffer and the other
* in the beginning, and should be sent in two steps
* @param[in] rawdev pointer to #rawdev_buffer structure containing
* @param[in] indx pointer to the disk index node
* @param[in] sockfd opened socket descriptor
*/
void send_split_file(rawdev_buffer *rawdev, struct disk_index *indx, int sockfd) void send_split_file(rawdev_buffer *rawdev, struct disk_index *indx, int sockfd)
{ {
ssize_t rcntr = 0; ssize_t rcntr = 0;
...@@ -881,6 +833,12 @@ void send_split_file(rawdev_buffer *rawdev, struct disk_index *indx, int sockfd) ...@@ -881,6 +833,12 @@ void send_split_file(rawdev_buffer *rawdev, struct disk_index *indx, int sockfd)
lseek64(rawdev->rawdev_fd, curr_pos, SEEK_SET); lseek64(rawdev->rawdev_fd, curr_pos, SEEK_SET);
} }
/**
* @brief Send the number of files (or disk chunks) found over socket connection
* @param[in] sockfd opened socket descriptor
* @param[in] num the number to be sent
* @return none
*/
void send_fnum(int sockfd, size_t num) void send_fnum(int sockfd, size_t num)
{ {
char buff[SMALL_BUFF_LEN] = {0}; char buff[SMALL_BUFF_LEN] = {0};
...@@ -891,6 +849,12 @@ void send_fnum(int sockfd, size_t num) ...@@ -891,6 +849,12 @@ void send_fnum(int sockfd, size_t num)
write(sockfd, buff, len); write(sockfd, buff, len);
} }
/**
* @brief Read file parameters from a string and fill in disk index node structure
* @param[in] cmd pointer to a string with file parameters
* @param[out] indx pointer to disk index node structure
* @return the number of parameters extracted from the string or -1 in case of an error
*/
int get_indx_args(char *cmd, struct disk_index *indx) int get_indx_args(char *cmd, struct disk_index *indx)
{ {
char *cmd_start = strchr(cmd, ':'); char *cmd_start = strchr(cmd, ':');
...@@ -901,9 +865,15 @@ int get_indx_args(char *cmd, struct disk_index *indx) ...@@ -901,9 +865,15 @@ int get_indx_args(char *cmd, struct disk_index *indx)
} }
/** /**
* @brief Raw device buffer reading function.
* *
* @param arg * This function is started in a separated thread right after the application has started. It opens a
* @todo print unrecognized command * communication socket, waits for commands sent over the socket and process them.
* @param[in, out] arg pointer to #camogm_state structure
* @return none
* @warning The main processing loop of the function is enclosed in @e pthread_cleanup_push and @e pthread_cleanup_pop
* calls. The effect of use of normal @b return or @b break to prematurely leave this loop is undefined.
* @todo print unrecognized command to debug output file
*/ */
void *reader(void *arg) void *reader(void *arg)
{ {
...@@ -931,9 +901,7 @@ void *reader(void *arg) ...@@ -931,9 +901,7 @@ void *reader(void *arg)
.state = state, .state = state,
.idir = &index_dir, .idir = &index_dir,
.sockfd_const = &sockfd, .sockfd_const = &sockfd,
.sockfd_temp = &fd, .sockfd_temp = &fd
.ret_val = 0
}; };
prep_socket(&sockfd); prep_socket(&sockfd);
...@@ -1109,6 +1077,13 @@ void *reader(void *arg) ...@@ -1109,6 +1077,13 @@ void *reader(void *arg)
return (void *) 0; return (void *) 0;
} }
/**
* @brief Clean up after the reading thread is closed. This function is thread-cancellation handler and it is
* passed to @e pthread_cleanup_push() function.
* @param[in] arg pointer to #exit_state structure containing resources that
* should be closed
* @return none
*/
static inline void exit_thread(void *arg) static inline void exit_thread(void *arg)
{ {
struct exit_state *s = (struct exit_state *)arg; struct exit_state *s = (struct exit_state *)arg;
...@@ -1129,15 +1104,17 @@ static inline void exit_thread(void *arg) ...@@ -1129,15 +1104,17 @@ static inline void exit_thread(void *arg)
} }
/** /**
* @brief Extract JPEG files from raw device buffer * @brief Extract the position and parameters of JPEG files in raw device buffer and
* build disk index directory for further file extraction.
* *
* Data from raw device is read to a buffer in #PHY_BLK_SZ blocks. The buffer is * Data from raw device is read to a buffer in #PHY_BLK_SZ blocks. The buffer is
* analyzed for JPEG markers and then the data from buffer is written to a file. * then analyzed for JPEG markers stored in #elphelst and #elphelen arrays. The offsets and
* sizes of the files found in the buffer are recorded to disk index directory.
* @param[in] state a pointer to a structure containing current state * @param[in] state a pointer to a structure containing current state
* @return 0 if files were extracted successfully and negative error code otherwise * @param[out] idir a pointer to disk index directory. This directory will contain
* @warning The main processing loop of the function is enclosed in @e pthread_cleanup_push and @e pthread_cleanup_pop * offset of the files found in the raw device buffer.
* calls. The effect of use of normal @b return or @b break to prematurely leave this loop is undefined. * @return none
* @todo update description, reorder decision tree * @todo reorder decision tree
*/ */
void build_index(camogm_state *state, struct disk_idir *idir) void build_index(camogm_state *state, struct disk_idir *idir)
{ {
......
...@@ -19,6 +19,26 @@ ...@@ -19,6 +19,26 @@
#include "camogm.h" #include "camogm.h"
/**
* @struct disk_index
* @brief Contains a single entry into disk index directory. Each node in
* the disk index directory corresponds to a file in the raw device buffer and
* hold its starting offset, sensor port number, time stamp and file size.
* @var disk_index::next
* Pointer to the next index node
* @var disk_index::prev
* Pointer to the previous disk index node
* @var disk_index::rawtime
* Time stamp in UNIX format
* @var disk_index::usec
* The microsecond part of the time stamp
* @var disk_index::port
* The sensor port number this frame was captured from
* @var disk_index::f_size
* File size in bytes
* @var disk_index::f_offset
* The offset of the file start in the raw device buffer (in bytes)
*/
struct disk_index { struct disk_index {
struct disk_index *next; struct disk_index *next;
struct disk_index *prev; struct disk_index *prev;
...@@ -29,18 +49,35 @@ struct disk_index { ...@@ -29,18 +49,35 @@ struct disk_index {
uint64_t f_offset; uint64_t f_offset;
}; };
/**
* @struct disk_idir
* @brief Contains pointers to disk index directory
* @var disk_idir::head
* Pointer to the first node of disk index directory
* @var disk_idir::tail
* Pointer to the last node of disk index directory
* @var disk_idir::size
* The number of nodes in disk index directory
*/
struct disk_idir { struct disk_idir {
struct disk_index *head; struct disk_index *head;
struct disk_index *tail; struct disk_index *tail;
size_t size; size_t size;
}; };
/**
* @struct range
* @brief Container for offsets in raw device buffer
* @var range::from
* Starting offset
* @var range::to
* Ending offset
*/
struct range { struct range {
uint64_t from; uint64_t from;
uint64_t to; uint64_t to;
}; };
//void *build_index(void *arg);
void *reader(void *arg); void *reader(void *arg);
#endif /* _CAMOGM_READ_H */ #endif /* _CAMOGM_READ_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment