Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
elphel-apps-camogm
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
elphel-apps-camogm
Commits
0de5ece0
Commit
0de5ece0
authored
Jul 06, 2016
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update doxygen documentation, remove unused functions
parent
1ab4818a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
214 additions
and
200 deletions
+214
-200
camogm.c
camogm.c
+0
-2
camogm.h
camogm.h
+2
-0
camogm_read.c
camogm_read.c
+174
-197
camogm_read.h
camogm_read.h
+38
-1
No files found.
camogm.c
View file @
0de5ece0
...
@@ -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 */
...
...
camogm.h
View file @
0de5ece0
...
@@ -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
...
...
camogm_read.c
View file @
0de5ece0
/** @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
* @param[in] state a pointer to a structure containing current state
* SubSecTimeOriginal fields and assembles a file name in the following format:
* @param[in,out] idir pointer to disk index directory
*
* @return 0 if new node was successfully added and -1 otherwise
* 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[out] name resulting file name
* @return 0 if file name was successfully created and negative value 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 typ
e
* @return
non
e
*/
*/
//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
)
{
{
...
...
camogm_read.h
View file @
0de5ece0
...
@@ -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 */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment