Commit 67643efd authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Start/restart behavior, more of relevant status output

parent eb2f643e
Loading
Loading
Loading
Loading
+78 −22
Original line number Diff line number Diff line
@@ -363,9 +363,14 @@ int camogm_start(camogm_state *state, bool restart)
			D1(syslog (LOG_INFO,    "Starting raw data recording, marked %s", get_state_path(state)));
			next_state_path(state); // increment path so next time will use different one.
		} else {
			D1(fprintf(debug_file, "Re-starting raw data recording, using the same state file, text will be %s, state->path='%s'\n", get_state_path(state), state->path));
			if (state->prog_state == STATE_STARTING) {
				D1(fprintf(debug_file, "Continue starting, state->path='%s'\n", state->path));
				D1(syslog (LOG_INFO,   "Continue starting, state->path='%s'\n", state->path));
			} else {
				D1(fprintf(debug_file, "Re-starting raw data recording, using the same state file, next will be %s, state->path='%s'\n", get_state_path(state), state->path));
				D1(syslog (LOG_INFO,   "Re-starting raw data recording, next will be %s", get_state_path(state)));
			}
		}
	} else {
		D1(fprintf(debug_file, "Starting file system recording to %s\n", state->path));
		D1(syslog (LOG_INFO, "Starting file system recording to %s", state->path));
@@ -375,10 +380,11 @@ int camogm_start(camogm_state *state, bool restart)
	state->frameno = 0;

	// do not trigger overrun alert on successfull (from GUI) restarts
#if ERRORS_FROM_START == 0
	if (state->prog_state != STATE_RESTARTING)
		for (int p = 0; p < SENSOR_PORTS; p++)
			state->buf_overruns[p] = -1;

#endif
	state->timescale = state->set_timescale; // current timescale, default 1
// debug
	int * ifp =      (int*)&(state->frame_params[port]);
@@ -431,12 +437,36 @@ int camogm_start(camogm_state *state, bool restart)
				if (!state->ignore_fps) {                                                                               // don't even try in ignore mode
					if (((fp = lseek(state->fd_circ[chn], LSEEK_CIRC_PREV, SEEK_END))) >= 0) state->cirbuf_rp[chn] = fp;//try to have 2 frames available for fps
				}
#if ERRORS_FROM_START == 0
				state->buf_overruns[chn]++;
				// file pointer here should match state->rp; so no need to do    lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET);
				state->buf_min[chn] = getGPValue(chn, G_FREECIRCBUF);
#endif
			} else {
				if (state->buf_min[chn] > getGPValue(chn, G_FREECIRCBUF)) state->buf_min[chn] = getGPValue(chn, G_FREECIRCBUF);
#if ERRORS_FROM_START == 0
				if (state->buf_min[chn] > getGPValue(chn, G_FREECIRCBUF)) {
					state->buf_min[chn] = getGPValue(chn, G_FREECIRCBUF);
				}
#endif
			}
#if ERRORS_FROM_START
			if (!restart) { // only reset errors and minimal buffer size during slient-initiated start (not after buffer overrun)
				state->buf_mmin = state->circ_buff_size[0] - MIN_USED_SIZE;;
				FOR_EACH_PORT(int, chn) {
					state->buf_overruns[chn] = 0;
					state->buf_min[chn] = state->circ_buff_size[chn] - MIN_USED_SIZE;
					if (state->buf_min[chn] < state->buf_mmin){ // will never happed with the same buffers
						state->buf_mmin = state->buf_min[chn];
					}
				}
				state->last_error_code = 0;                             // Reset error
				state->error_restarts = 0;
			} else { // restart only after buffer overrun
				if (state->prog_state != STATE_STARTING) { // during STATE_STARTING it continuously gets here if
					state->error_restarts ++;
				}
			}
#endif
			D3(fprintf(debug_file, "3: state->cirbuf_rp=0x%x\n", state->cirbuf_rp[chn]));
			D3(fprintf(debug_file, "4:lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END)=0x%x\n",\
					(int)lseek(state->fd_circ[chn], LSEEK_CIRC_READY, SEEK_END)));
@@ -1160,14 +1190,15 @@ void camogm_status(camogm_state *state, char * fn, int xml)
	int _dur = 0, _udur = 0, _dur_raw, _udur_raw;
	FILE* f;
	char *_state, *_output_format, *_using_exif, *_using_global_pointer, *_compressor_state[SENSOR_PORTS];
	int _b_free[SENSOR_PORTS], _b_used[SENSOR_PORTS], _b_size[SENSOR_PORTS];
//	int _b_free[SENSOR_PORTS], _b_used[SENSOR_PORTS], _b_size[SENSOR_PORTS];
	int _b_size[SENSOR_PORTS];
	int _frames_remain[SENSOR_PORTS] = {0};
	int _sec_remain[SENSOR_PORTS] = {0};
	int _frames_skip = 0;
	int _sec_skip = 0;
	char *_kml_enable, *_kml_used, *_kml_height_mode;
	unsigned int _percent_done;
	off_t save_p;
//	off_t save_p;

	_kml_enable =      state->kml_enable ? "yes" : "no";
	_kml_used =        state->kml_used ? "yes" : "no";
@@ -1175,11 +1206,11 @@ void camogm_status(camogm_state *state, char * fn, int xml)

	for (int chn = 0; chn < SENSOR_PORTS; chn++) {
		_b_size[chn] = getGPValue(chn, G_FRAME_SIZE);
		save_p = lseek(state->fd_circ[chn], 0, SEEK_CUR);
		_b_free[chn] = lseek(state->fd_circ[chn], LSEEK_CIRC_FREE, SEEK_END);
		lseek(state->fd_circ[chn], save_p, SEEK_SET);
		_b_used[chn] = lseek(state->fd_circ[chn], LSEEK_CIRC_USED, SEEK_END);
		lseek(state->fd_circ[chn], save_p, SEEK_SET);
//		save_p = lseek(state->fd_circ[chn], 0, SEEK_CUR);
//		_b_free[chn] = lseek(state->fd_circ[chn], LSEEK_CIRC_FREE, SEEK_END);
//		lseek(state->fd_circ[chn], save_p, SEEK_SET);
//		_b_used[chn] = lseek(state->fd_circ[chn], LSEEK_CIRC_USED, SEEK_END);
//		lseek(state->fd_circ[chn], save_p, SEEK_SET);
		_compressor_state[chn] = (getGPValue(chn, P_COMPRESSOR_RUN) == 2) ? "running" : "stopped";
		if (state->frames_skip > 0)
			_frames_remain[chn] = state->frames_skip_left[chn];
@@ -1252,6 +1283,8 @@ void camogm_status(camogm_state *state, char * fn, int xml)
		fprintf(f, "<?xml version=\"1.0\"?>\n" \
			"<camogm_state>\n" \
			"  <state>\"%s\"</state>\n" \
			"  <buf_mfree>\"%d\"</buf_mfree>\n" \
			"  <buf_mmin>\"%d\"</buf_mmin>\n" \
			"  <file_name>\"%s\"</file_name>\n" \
			"  <frame_number>%d</frame_number>\n" \
			"  <start_after_timestamp>%f</start_after_timestamp>\n"	\
@@ -1270,6 +1303,7 @@ void camogm_status(camogm_state *state, char * fn, int xml)
			"  <timescale>%f</timescale>\n"	\
			"  <frames_per_chunk>%d</frames_per_chunk>\n" \
			"  <last_error_code>%d</last_error_code>\n" \
			"  <error_restarts>%d</error_restarts>\n" \
			"  <debug_output>\"%s\"</debug_output>\n" \
			"  <debug_level>%d</debug_level>\n" \
			"  <use_global_rp>\"%s\"</use_global_rp>\n" \
@@ -1292,11 +1326,11 @@ void camogm_status(camogm_state *state, char * fn, int xml)
			"  <lba_start>%llu</lba_start>\n" \
			"  <lba_current>%llu</lba_current>\n" \
			"  <lba_end>%llu</lba_end>\n",
			_state,  state->path, state->frameno, state->start_after_timestamp, _dur, _udur, _len, \
			_state, state->buf_mfree, state->buf_mmin, state->path, state->frameno, state->start_after_timestamp, _dur, _udur, _len, \
			_frames_skip, _sec_skip, \
			state->width, state->height, _output_format, _using_exif, \
			state->path_prefix, state->segment_duration, state->segment_length, state->max_frames, state->timescale, \
			state->frames_per_chunk,  state->last_error_code, \
			state->frames_per_chunk,  state->last_error_code, state->error_restarts, \
			state->debug_name, debug_level, _using_global_pointer, \
			_kml_enable, _kml_used, state->kml_path, state->kml_horHalfFov, state->kml_vertHalfFov, state->kml_near, \
			_kml_height_mode, state->kml_height, state->kml_period, state->kml_last_ts, state->kml_last_uts, \
@@ -1328,8 +1362,8 @@ void camogm_status(camogm_state *state, char * fn, int xml)
				state->buf_overruns[chn],
				state->buf_min[chn],
				state->frame_period[chn],
				_b_free[chn],
				_b_used[chn],
				state->buf_free[chn], // _b_free[chn],
				state->circ_buff_size[chn] - state->buf_free[chn], // _b_used[chn],
				state->cirbuf_rp[chn]
				);
			camogm_err_stat(state, chn, f, true);
@@ -1338,6 +1372,8 @@ void camogm_status(camogm_state *state, char * fn, int xml)
		fprintf(f, "</camogm_state>\n");
	} else {
		fprintf(f, "state              \t%s\n",        _state);
		fprintf(f, "buf_mfree          \t%d\n",        state->buf_mfree); // minimal of all ports
		fprintf(f, "buf_mmin           \t%d\n",        state->buf_mmin); // minimal of all ports
		fprintf(f, "file               \t%s\n",        state->path);
		fprintf(f, "frame              \t%d\n",        state->frameno);
		fprintf(f, "start_after_timestamp \t%f\n",     state->start_after_timestamp);
@@ -1363,6 +1399,7 @@ void camogm_status(camogm_state *state, char * fn, int xml)
		fprintf(f, "ignore fps         \t%s\n",        state->ignore_fps ? "yes" : "no");
		fprintf(f, "\n");
		fprintf(f, "last error code    \t%d\n",        state->last_error_code);
		fprintf(f, "error_restarts     \t%d\n",        state->error_restarts);
		fprintf(f, "\n");
		fprintf(f, "debug output to    \t%s\n",        state->debug_name);
		fprintf(f, "debug level        \t%d\n",        debug_level);
@@ -1396,17 +1433,20 @@ void camogm_status(camogm_state *state, char * fn, int xml)
			fprintf(f, "buffer overruns    \t%d\n",    state->buf_overruns[chn]);
			fprintf(f, "buffer minimal     \t%d\n",    state->buf_min[chn]);
			fprintf(f, "frame period       \t%d (0x%x)\n", state->frame_period[chn], state->frame_period[chn]);
			fprintf(f, "buffer free        \t%d\n",    _b_free[chn]);
			fprintf(f, "buffer used        \t%d\n",    _b_used[chn]);
			fprintf(f, "buffer free        \t%d\n",    state->buf_free[chn]); // _b_free[chn]);
			fprintf(f, "buffer used        \t%d\n",    state->circ_buff_size[chn] - state->buf_free[chn]); //_b_used[chn]);
			fprintf(f, "circbuf_rp         \t%d (0x%x)\n", state->cirbuf_rp[chn], state->cirbuf_rp[chn]);
			camogm_err_stat(state, chn, f, false);
			fprintf(f, "\n");
		}
	}

	if ((f != stdout) && (f != stderr)) fclose(f);
#if ERRORS_FROM_START == 0
	FOR_EACH_PORT(int, chn) {if (state->buf_overruns[chn] >= 0) state->buf_overruns[chn] = 0;}  // resets overruns after reading status , so "overruns" means since last reading status
	state->last_error_code = 0;                             // Reset error
	FOR_EACH_PORT(int, chn) {state->buf_min[chn] = _b_free[chn];}
#endif
}

/**
@@ -1877,7 +1917,8 @@ int listener_loop(camogm_state *state)
			case  CAMOGM_FRAME_INVALID:     // invalid frame pointer
			case  CAMOGM_FRAME_BROKEN:      // frame broken (buffer overrun)
				// restart the file
				D0(fprintf(debug_file,"%s:line %d - sendImageFrame() returned -%d\n", __FILE__, __LINE__, rslt));
				D0(fprintf(debug_file,"%s:line %d - *** sendImageFrame() returned -%d, restarting\n", __FILE__, __LINE__, rslt));
				D0(syslog (LOG_INFO,"%s:line %d - *** sendImageFrame() returned -%d, restarting", __FILE__, __LINE__, rslt));
				camogm_stop(state);
				state->prog_state = STATE_RESTARTING;
				D6(fprintf(debug_file, "camogm_start() from %s:%d: @ %07d\n", \
@@ -1920,7 +1961,6 @@ int listener_loop(camogm_state *state)
//next_segment_pos
			}
		} else if (state->prog_state == STATE_STARTING) { // no commands in queue,starting (but not started yet)

			// retry starting
			D2(fprintf(debug_file, "camogm_start() from %s:%d: @ %07d\n", __FILE__, __LINE__,get_fpga_usec(state->fd_fparmsall[0], 0)));
			switch ((rslt = -camogm_start(state, true))) {
@@ -2213,20 +2253,32 @@ unsigned int select_port(camogm_state *state)
								port,state->cirbuf_rp[port]); for (i=0; i< 16; i++) { \
							fprintf(debug_file," 0x%08lx", ((unsigned long* )&ccam_dma_buf[port][dbg_meta >> 2])[i]); \
						if ((i & 7) == 7) fprintf(debug_file,"\n");	});

#if ERRORS_FROM_START
						state ->buf_overruns[port]++;
#endif
						chn = -1; // port;
						break;

					}
					D6(fprintf(debug_file, "port %i = %li, ", port, free_sz));
				}
				if ((free_sz < min_sz && free_sz >= 0) || min_sz == -1) {
#if ERRORS_FROM_START
				if (free_sz >= 0) {
					state-> buf_free[port] = free_sz;
					if (free_sz < state-> buf_min[port]){
						state-> buf_min[port] = free_sz;
					}
				}
#endif
				if (((free_sz < min_sz) && (free_sz >= 0)) || min_sz == -1) {
					if (free_sz < CAMOGM_MIN_BUF_FRAMES * state->image_size[port]) {
						if ((state->prog_state == STATE_STARTING) || (state->prog_state == STATE_RUNNING)) {
							D1(fprintf(debug_file, "port %i has too little free space (%ld <CAMOGM_MIN_BUF_FRAMES * %d), considered BROKEN, state=%d\n", \
									port, free_sz, state->image_size[port], state->prog_state));

						}
#if ERRORS_FROM_START
						state ->buf_overruns[port]++;
#endif
						chn = -1; // port;
						break;
					}
@@ -2248,6 +2300,10 @@ unsigned int select_port(camogm_state *state)
		}
	}
	if ((state->prog_state == STATE_STARTING) || (state->prog_state == STATE_RUNNING)) {
		state->buf_mfree = min_sz;
		if (state->buf_mfree < state->buf_mmin){
			state->buf_mmin = state->buf_mfree;
		}
#ifdef MIN_USED_SIZE
		D1(if ((chn >=0) && (lseek(state->fd_circ[chn], LSEEK_CIRC_READY, SEEK_END) >= 0) && \
				(lseek(state->fd_circ[chn], LSEEK_CIRC_USED, SEEK_END) >= MIN_USED_SIZE)) {\
+6 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#define NUM_NEED_NEMPTY           (NUM_WRITER_THREADS + 0) // wake up main thread if there are at least this number of empty pages
#define NUM_FREE_MANY             (NUM_WRITER_THREADS + 1) // Set many if get_num_empty() < NUM_FREE_MANY

#define ERRORS_FROM_START         1        ///< Reset errors only when starting recording, not after reading status
//#define NODEBUG
#define CAMOGM_FRAME_NOT_READY    1        ///< frame pointer valid, but not yet acquired
#define CAMOGM_FRAME_INVALID      2        ///< invalid frame pointer
@@ -172,7 +173,7 @@ enum state_flags {
	STATE_STARTING,
	STATE_RUNNING,
	STATE_READING,
	STATE_RESTARTING,
	STATE_RESTARTING, // after errors, until started
	STATE_CANCEL
};

@@ -337,6 +338,10 @@ typedef struct {
	int data_segments;                                      ///< the number of segments in frame
	int buf_overruns[SENSOR_PORTS];
	int buf_min[SENSOR_PORTS];
	int buf_free[SENSOR_PORTS];                             ///< free buffer size last measured, per port
	int buf_mfree;                                          ///< free buffer size - minimal for all ports
	int buf_mmin;                                           ///< minimum of buf_min[port]
	int error_restarts;                                     ///< number of restarts due to errors;
	int set_frames_skip;                                    ///< will be copied to frames_skip if stopped or at start
	int frames_skip;                                        ///< number of frames to skip after the one recorded (for time lapse)
	                                                        ///< if negative - -(interval between frames in seconds)