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

Update doxygen documentation, remove unused functions

parent 1ab4818a
Loading
Loading
Loading
Loading
+0 −2
Original line number Original line Diff line number Diff line
@@ -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 */
+2 −0
Original line number Original line Diff line number Diff line
@@ -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
+174 −197
Original line number Original line Diff line number Diff line
/** @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 @@
 * 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 @@


/** @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 = {
		.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 = {
	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[] = {
	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 {
};
};


/**
/**
 * @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 {
	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 {
	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 {
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)
	}
	}
}
}


/**
 * @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)
	}
	}
}
}


/**
 * @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)
	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)
	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)
	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)
 * @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)
}
}


/**
/**
 * @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
}
}


/**
/**
 * @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)
	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)
	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)
	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
}
}


/**
/**
 * @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)
	}
	}
}
}


/**
 * @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)
	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)
	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)
}
}


#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)
}
}


/**
/**
 *
 * @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)
 * @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)
	}
	}
}
}


/**
 * @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)
	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)
	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)
}
}


/**
/**
 * @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)
			.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)
	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)
}
}


/**
/**
 * @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)
{
{
+38 −1
Original line number Original line Diff line number Diff line
@@ -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 {
	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 */