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
63bf56d0
Commit
63bf56d0
authored
Jun 29, 2016
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Process commands in a thread
parent
73ecbfc7
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
293 additions
and
83 deletions
+293
-83
camogm.c
camogm.c
+9
-5
camogm.h
camogm.h
+3
-0
camogm_read.c
camogm_read.c
+279
-77
camogm_read.h
camogm_read.h
+2
-1
No files found.
camogm.c
View file @
63bf56d0
...
...
@@ -231,6 +231,7 @@ void camogm_init(camogm_state *state, char *pipe_name)
state
->
rawdev
.
curr_pos_w
=
state
->
rawdev
.
start_pos
;
state
->
rawdev
.
curr_pos_r
=
state
->
rawdev
.
start_pos
;
state
->
active_chn
=
ALL_CHN_ACTIVE
;
state
->
rawdev
.
mmap_size
=
MMAP_CHUNK_SIZE
;
}
/**
...
...
@@ -802,7 +803,7 @@ void camogm_set_prefix(camogm_state *state, const char * p, path_type type)
D0
(
fprintf
(
debug_file
,
"WARNING: raw device write initiated
\n
"
));
state
->
rawdev_op
=
1
;
/* debug code follows */
//
state->rawdev.end_pos = 10485760; // 10 Mib
state
->
rawdev
.
end_pos
=
10485760
;
// 10 Mib
/* end of debug code */
}
}
...
...
@@ -954,6 +955,8 @@ void camogm_status(camogm_state *state, char * fn, int xml)
case
STATE_READING
:
_state
=
"reading"
;
break
;
default:
_state
=
"stopped"
;
}
_output_format
=
state
->
format
?
((
state
->
format
==
CAMOGM_FORMAT_OGM
)
?
"ogm"
:
((
state
->
format
==
CAMOGM_FORMAT_JPEG
)
?
"jpeg"
:
...
...
@@ -1006,7 +1009,7 @@ void camogm_status(camogm_state *state, char * fn, int xml)
" <raw_device_path>
\"
%s
\"
</raw_device_path>
\n
"
\
" <raw_device_overruns>%d</raw_device_overruns>
\n
"
\
" <raw_device_pos_write>0x%llx</raw_dev_pos_write>
\n
"
\
" <raw_device_pos_read>0x%llx (%d
\
% done)</raw_device_pos_read>
\n
"
,
" <raw_device_pos_read>0x%llx (%d
%
% done)</raw_device_pos_read>
\n
"
,
_state
,
state
->
path
,
state
->
frameno
,
state
->
start_after_timestamp
,
_dur
,
_udur
,
_len
,
\
_frames_skip
,
_sec_skip
,
\
state
->
width
,
state
->
height
,
_output_format
,
_using_exif
,
\
...
...
@@ -1067,7 +1070,7 @@ void camogm_status(camogm_state *state, char * fn, int xml)
fprintf
(
f
,
"raw device overruns
\t
%d
\n
"
,
state
->
rawdev
.
overrun
);
fprintf
(
f
,
"raw write position
\t
0x%llx
\n
"
,
state
->
rawdev
.
curr_pos_w
);
fprintf
(
f
,
"raw read position
\t
0x%llx
\n
"
,
state
->
rawdev
.
curr_pos_r
);
fprintf
(
f
,
" percent done
\t
%d
\
%
\n
"
,
_percent_done
);
fprintf
(
f
,
" percent done
\t
%d
%
%
\n
"
,
_percent_done
);
fprintf
(
f
,
"max file duration
\t
%d sec
\n
"
,
state
->
segment_duration
);
fprintf
(
f
,
"max file length
\t
%d B
\n
"
,
state
->
segment_length
);
fprintf
(
f
,
"max frames
\t
%d
\n
"
,
state
->
max_frames
);
...
...
@@ -1498,7 +1501,7 @@ int listener_loop(camogm_state *state)
state
->
rawdev
.
thread_finished
=
false
;
state
->
prog_state
=
STATE_STOPPED
;
pthread_join
(
state
->
rawdev
.
tid
,
&
tret
);
if
((
int
)
tret
!=
0
&&
(
int
)
tret
!=
PTHREAD_CANCELED
)
{
if
((
int
)
tret
!=
0
&&
(
int
)
tret
!=
(
int
)
PTHREAD_CANCELED
)
{
D0
(
fprintf
(
debug_file
,
"Reading thread returned error %d
\n
"
,
(
int
)
tret
));
}
else
{
D3
(
fprintf
(
debug_file
,
"Reading thread stopped
\n
"
));
...
...
@@ -1509,7 +1512,8 @@ int listener_loop(camogm_state *state)
}
else
if
(
state
->
rawdev
.
thread_state
==
STATE_STOPPED
)
{
state
->
rawdev
.
thread_state
=
STATE_RUNNING
;
state
->
rawdev
.
thread_finished
=
false
;
if
(
pthread_create
(
&
state
->
rawdev
.
tid
,
NULL
,
build_index
,
state
)
!=
0
)
{
// if (pthread_create(&state->rawdev.tid, NULL, build_index, state) != 0) {
if
(
pthread_create
(
&
state
->
rawdev
.
tid
,
NULL
,
reader
,
state
)
!=
0
)
{
state
->
prog_state
=
STATE_STOPPED
;
state
->
rawdev
.
thread_state
=
STATE_STOPPED
;
D0
(
fprintf
(
debug_file
,
"%s:line %d: Can not start new thread, disk index is not built
\n
"
,
__FILE__
,
__LINE__
));
...
...
camogm.h
View file @
63bf56d0
...
...
@@ -60,6 +60,7 @@
#define RAWDEV_START_OFFSET 1024
/** @brief Maximum length of file or raw device path */
#define ELPHEL_PATH_MAX 300
#define MMAP_CHUNK_SIZE 134217728
/**
* @enum state_flags
...
...
@@ -99,6 +100,8 @@ typedef struct {
uint64_t
start_pos
;
uint64_t
end_pos
;
uint64_t
curr_pos_w
;
uint64_t
*
disk_mmap
;
uint64_t
mmap_size
;
volatile
uint64_t
curr_pos_r
;
uint64_t
file_start
;
pthread_t
tid
;
...
...
camogm_read.c
View file @
63bf56d0
...
...
@@ -33,6 +33,9 @@
#include <ctype.h>
#include <asm/byteorder.h>
#include <sys/statvfs.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "camogm_read.h"
...
...
@@ -41,6 +44,9 @@
/** @brief Separator character between seconds and microseconds in JPEG file name */
#define SUBSEC_SEPARATOR '.'
#define EXIF_DATE_TIME_FORMAT "%Y:%m:%d %H:%M:%S"
#define CMD_DELIMITER "/?"
#define CMD_BUFF_LEN 1024
#define COMMAND_LOOP_DELAY 500000
/** @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
/** @brief Include or exclude file start and stop markers from resulting file. This must be set to 1 for JPEG files */
...
...
@@ -60,6 +66,26 @@ static const struct iovec elphel_en = {
.
iov_len
=
sizeof
(
elphelen
)
};
#define COMMAND_TABLE \
X(CMD_BUILD_INDEX, "build_index") \
X(CMD_GET_INDEX, "get_index") \
X(CMD_READ_DISK, "read_disk") \
X(CMD_READ_FILE, "read_file") \
X(CMD_READ_ALL_FILES, "read_all_files") \
X(CMD_STATUS, "status")
#define X(a, b) a,
enum
socket_commands
{
COMMAND_TABLE
};
#undef X
#define X(a, b) b,
static
const
char
*
cmd_list
[]
=
{
COMMAND_TABLE
};
#undef X
/**
* @enum file_result
* @brief Return codes for file operations
...
...
@@ -122,6 +148,16 @@ enum search_state {
SEARCH_FILE_START
,
SEARCH_FILE_DATA
};
//enum sock_commands {
// CMD_BUILD_INDEX,
// CMD_GET_INDEX,
// CMD_READ_DISK,
// CMD_READ_FILE,
// CMD_READ_ALL_FILES,
// CMD_STATUS
//};
/**
* @brief Exif data format table.
*
...
...
@@ -219,6 +255,8 @@ struct exit_state {
int
ret_val
;
};
static
inline
void
exit_thread
(
void
*
arg
);
void
dump_index_dir
(
const
struct
disk_idir
*
idir
)
{
struct
disk_index
*
ind
=
idir
->
head
;
...
...
@@ -540,39 +578,39 @@ int stop_index(struct disk_idir *idir, uint64_t pos_stop)
* @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
;
}
//
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
...
...
@@ -636,56 +674,221 @@ static int check_edge_case(const struct iovec *from, const struct iovec *to, con
* @param[in] to end pointer to data buffer
* @return a constant of #file_result type
*/
static
int
write_buffer
(
struct
file_opts
*
f_op
,
unsigned
char
*
from
,
unsigned
char
*
to
)
//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
)
{
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
;
size_t
bytes_left
=
sz
;
size_t
bytes_written
=
0
;
size_t
offset
=
0
;
while
(
bytes_left
>
0
)
{
bytes_written
=
write
(
sockfd
,
&
buff
[
offset
],
bytes_left
);
bytes_left
-=
bytes_written
;
offset
+=
bytes_written
;
}
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
;
}
int
mmap_disk
(
rawdev_buffer
*
rawdev
)
{
int
ret
=
0
;
rawdev
->
rawdev_fd
=
open
(
rawdev
->
rawdev_path
,
O_RDONLY
);
if
(
rawdev
->
rawdev_fd
<
0
)
{
return
-
1
;
}
}
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
;
rawdev
->
disk_mmap
=
mmap
(
0
,
rawdev
->
mmap_size
,
PROT_READ
,
MAP_SHARED
,
rawdev
->
rawdev_fd
,
rawdev
->
start_pos
);
if
(
rawdev
->
disk_mmap
==
MAP_FAILED
)
{
close
(
rawdev
->
rawdev_fd
);
return
-
1
;
}
return
ret
;
}
int
unmmap_disk
(
rawdev_buffer
*
rawdev
)
{
int
ret
=
0
;
if
(
munmap
(
rawdev
->
disk_mmap
,
rawdev
->
mmap_size
)
!=
0
)
return
-
1
;
if
(
close
(
rawdev
->
rawdev_fd
)
!=
0
)
return
-
1
;
return
ret
;
}
#define PORT_NUMBER 3456
void
prep_socket
(
int
*
socket_fd
)
{
int
opt
=
1
;
struct
sockaddr_in
sock
;
memset
((
char
*
)
&
sock
,
0
,
sizeof
(
struct
sockaddr_in
));
sock
.
sin_family
=
AF_INET
;
sock
.
sin_port
=
htons
(
PORT_NUMBER
);
*
socket_fd
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
setsockopt
(
*
socket_fd
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
char
*
)
&
opt
,
sizeof
(
opt
));
bind
(
*
socket_fd
,
(
struct
sockaddr
*
)
&
sock
,
sizeof
(
struct
sockaddr_in
));
listen
(
*
socket_fd
,
10
);
}
/**
*
* @param cmd
* cmd pointer is updated to point to current command
* @return -1 command not recognized, -2 end of buffer
*/
int
parse_command
(
char
**
cmd
)
{
size_t
cmd_len
;
int
cmd_indx
=
-
1
;
char
*
char_ptr
;
D6
(
fprintf
(
debug_file
,
"Parsing command line: %s
\n
"
,
*
cmd
));
char_ptr
=
strpbrk
(
*
cmd
,
CMD_DELIMITER
);
if
(
char_ptr
!=
NULL
)
{
char_ptr
[
0
]
=
'\0'
;
char_ptr
++
;
for
(
int
i
=
0
;
i
<
sizeof
(
cmd_list
)
/
sizeof
(
cmd_list
[
0
]);
i
++
)
{
cmd_len
=
strlen
(
cmd_list
[
i
]);
if
(
strncmp
(
char_ptr
,
cmd_list
[
i
],
cmd_len
)
==
0
)
{
cmd_indx
=
i
;
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
;
}
}
*
cmd
=
char_ptr
;
}
else
{
f_op
->
fh
=
NULL
;
f_op
->
file_cntr
++
;
cmd_indx
=
-
2
;
}
return
cmd_indx
;
}
/**
* @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.
* @param[in,out] cmd pointer to HTTP GET string
*/
void
trim_command
(
char
*
cmd
,
ssize_t
cmd_len
)
{
char
*
ptr_start
,
*
ptr_end
;
if
(
cmd_len
>=
0
&&
cmd_len
<
CMD_BUFF_LEN
)
cmd
[
cmd_len
]
=
'\0'
;
ptr_start
=
strpbrk
(
cmd
,
CMD_DELIMITER
);
if
(
ptr_start
)
{
ptr_end
=
strchr
(
ptr_start
,
' '
);
if
(
ptr_end
)
ptr_end
[
0
]
=
'\0'
;
}
}
/**
*
* @param arg
* @todo print unrecognized command
*/
void
*
reader
(
void
*
arg
)
{
int
sockfd
,
fd
;
int
cmd
;
char
cmd_buff
[
CMD_BUFF_LEN
]
=
{
0
};
char
*
cmd_ptr
;
ssize_t
cmd_len
;
camogm_state
*
state
=
(
camogm_state
*
)
arg
;
rawdev_buffer
*
rawdev
=
&
state
->
rawdev
;
unsigned
char
*
disk_buff
=
NULL
;
struct
exit_state
exit_state
=
{
.
state
=
state
,
.
ret_val
=
0
};
prep_socket
(
&
sockfd
);
while
(
true
)
{
fd
=
accept
(
sockfd
,
NULL
,
0
);
if
(
fd
==
-
1
)
continue
;
cmd_len
=
read
(
fd
,
cmd_buff
,
sizeof
(
cmd_buff
)
-
1
);
cmd_ptr
=
cmd_buff
;
trim_command
(
cmd_ptr
,
cmd_len
);
while
((
cmd
=
parse_command
(
&
cmd_ptr
))
!=
-
2
)
{
if
(
cmd
>=
0
)
D6
(
fprintf
(
debug_file
,
"Got command '%s'
\n
"
,
cmd_list
[
cmd
]));
switch
(
cmd
)
{
case
CMD_BUILD_INDEX
:
break
;
case
CMD_GET_INDEX
:
break
;
case
CMD_READ_DISK
:
break
;
case
CMD_READ_FILE
:
break
;
case
CMD_READ_ALL_FILES
:
break
;
case
CMD_STATUS
:
break
;
default:
ret
=
FILE_OPT_ERR
;
D0
(
fprintf
(
debug_file
,
"Unrecognized command is skipped
\n
"
))
;
}
return
ret
;
}
fprintf
(
debug_file
,
"Closing connection
\n
"
);
close
(
fd
);
usleep
(
COMMAND_LOOP_DELAY
);
}
return
(
void
*
)
0
;
}
static
inline
void
*
exit_thread
(
void
*
arg
)
static
inline
void
exit_thread
(
void
*
arg
)
{
struct
exit_state
*
s
=
(
struct
exit_state
*
)
arg
;
...
...
@@ -694,7 +897,6 @@ static inline void *exit_thread(void *arg)
s
->
state
->
rawdev
.
rawdev_fd
=
-
1
;
}
s
->
state
->
rawdev
.
thread_finished
=
true
;
return
(
void
*
)
s
->
ret_val
;
}
/**
...
...
camogm_read.h
View file @
63bf56d0
...
...
@@ -23,7 +23,7 @@ struct disk_index {
struct
disk_index
*
next
;
struct
disk_index
*
prev
;
time_t
rawtime
;
u
seconds_
t
usec
;
u
nsigned
in
t
usec
;
uint32_t
port
;
size_t
f_size
;
uint64_t
f_offset
;
...
...
@@ -36,5 +36,6 @@ struct disk_idir {
};
void
*
build_index
(
void
*
arg
);
void
*
reader
(
void
*
arg
);
#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