Loading camogm.c +9 −5 Original line number Diff line number Diff line Loading @@ -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; } /** Loading Loading @@ -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 */ } } Loading Loading @@ -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" : Loading Loading @@ -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, \ Loading Loading @@ -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 \t0x%llx\n", state->rawdev.curr_pos_w); fprintf(f, "raw read position \t0x%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); Loading Loading @@ -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")); Loading @@ -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__)); Loading camogm.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading camogm_read.c +279 −77 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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 */ Loading @@ -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 Loading Loading @@ -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. * Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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; } } 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; 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; } 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; Loading @@ -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; } /** Loading camogm_read.h +2 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ struct disk_index { struct disk_index *next; struct disk_index *prev; time_t rawtime; useconds_t usec; unsigned int usec; uint32_t port; size_t f_size; uint64_t f_offset; Loading @@ -36,5 +36,6 @@ struct disk_idir { }; void *build_index(void *arg); void *reader(void *arg); #endif /* _CAMOGM_READ_H */ Loading
camogm.c +9 −5 Original line number Diff line number Diff line Loading @@ -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; } /** Loading Loading @@ -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 */ } } Loading Loading @@ -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" : Loading Loading @@ -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, \ Loading Loading @@ -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 \t0x%llx\n", state->rawdev.curr_pos_w); fprintf(f, "raw read position \t0x%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); Loading Loading @@ -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")); Loading @@ -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__)); Loading
camogm.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading
camogm_read.c +279 −77 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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 */ Loading @@ -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 Loading Loading @@ -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. * Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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; } } 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; 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; } 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; Loading @@ -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; } /** Loading
camogm_read.h +2 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ struct disk_index { struct disk_index *next; struct disk_index *prev; time_t rawtime; useconds_t usec; unsigned int usec; uint32_t port; size_t f_size; uint64_t f_offset; Loading @@ -36,5 +36,6 @@ struct disk_idir { }; void *build_index(void *arg); void *reader(void *arg); #endif /* _CAMOGM_READ_H */