34 #define AW_GAUGE_SIZE 40 // length of gauge display (in characters)
35 #define AW_GAUGE_GRANULARITY 10000 // how fine the gauge is transported to status (no of steps) [old value = 1000]
37 #define AW_STATUS_KILL_DELAY 4000 // in ms
38 #define AW_STATUS_LISTEN_DELAY 300 // in ms
39 #define AW_STATUS_HIDE_DELAY 60 // in sec
40 #define AW_STATUS_PIPE_CHECK_DELAY 1000*2 // in ms (a pipe check every 2 seconds)
42 #define AWAR_STATUS "tmp/status/"
43 #define AWAR_STATUS_TITLE AWAR_STATUS "title"
44 #define AWAR_STATUS_TEXT AWAR_STATUS "text"
45 #define AWAR_STATUS_GAUGE AWAR_STATUS "gauge"
46 #define AWAR_STATUS_ELAPSED AWAR_STATUS "elapsed"
48 #define AW_MESSAGE_LINES 500
62 #if !defined(DEVEL_RELEASE)
63 # define FORCE_WEIGHTED_ESTIMATION // see also ../CORE/arb_progress.h@FORCEWEIGHTEDESTIMATION
80 #define AW_EST_BUFFER 5 // size of buffer used to smoothen estimations
132 #define POLL_TIMEOUT 0 // idle wait POLL_TIMEOUT microseconds before returning EOF when polling
135 #define WRITE_TIMEOUT 1000 // 1 second for debug version (short because it always reaches timeout inside debugger)
137 #define WRITE_TIMEOUT 10000 // 10 seconds for release
141 #if defined(PIPE_DEBUGGING)
144 "Pipe already broken in mark_pipe_broken(); pipe_broken=%i aw_stg.errno=%i errno=%i\n",
148 fprintf(stderr,
"Marking pipe as broken (errno=%i)\n", err_no);
149 #endif // PIPE_DEBUGGING
154 static bool error_shown =
false;
157 "******************************************************************\n"
158 "The connection to the status window was blocked unexpectedly!\n"
159 "This happens if you run the program from inside the debugger\n"
160 "or when the process is blocked longer than %5.2f seconds.\n"
161 "Further communication with the status window is suppressed.\n"
162 "******************************************************************\n"
167 static ssize_t
safe_write(
int fd,
const char *buf,
int count) {
169 #if defined(PIPE_DEBUGGING)
170 fprintf(stderr,
"pipe is broken -- avoiding write of %i bytes\n", count);
171 #endif // PIPE_DEBUGGING
180 struct timeval timeout;
187 int sel_res = select(fd+1,
NULp, &set,
NULp, &timeout);
190 fprintf(stderr,
"select (before write) returned error (errno=%i)\n", errno);
194 bool pipe_would_block = !FD_ISSET(fd, &set);
196 #if defined(PIPE_DEBUGGING)
197 fprintf(stderr,
"select returned %i, pipe_would_block=%i (errno=%i)\n",
198 sel_res,
int(pipe_would_block), errno);
200 if (pipe_would_block) {
201 fprintf(stderr,
" Avoiding to write to pipe (because it would block!)\n");
204 fprintf(stderr,
" Write %i bytes to pipe.\n", count);
206 #endif // PIPE_DEBUGGING
208 if (!pipe_would_block) {
209 result = write(fd, buf, count);
216 else if (result != count) {
217 #if defined(PIPE_DEBUGGING)
218 fprintf(stderr,
"write wrote %i bytes instead of %i as requested.\n", result, count);
219 #endif // PIPE_DEBUGGING
239 struct timeval timeout;
247 if (erg == 0)
return EOF;
249 erg = read(fd, (
char *)&(buffer[0]), 1);
252 fprintf(stderr,
"father died, now i kill myself\n");
266 struct timeval timeout;
274 if (erg == 0)
return EOF;
281 erg = read(fd, input.buffer,
sizeof(
int));
283 fprintf(stderr,
"father died, now i kill myself\n");
307 str = strdup(buffer);
311 if (gaugePtr) *gaugePtr = gauge;
320 if (rough_gauge<AW_GAUGE_SIZE) {
322 buffer[rough_gauge] =
"-\\|/"[fine_gauge%4];
326 str = strdup(buffer);
335 if (getppid() <= 1) {
336 #if defined(TRACE_STATUS)
337 fprintf(stderr,
"Terminating status process.\n");
338 #endif // TRACE_STATUS
349 for (erg = 0; !erg;) {
350 struct timeval timeout;
359 #if defined(TRACE_STATUS)
360 fprintf(stderr,
"Waiting for status open command..\n");
fflush(stderr);
361 #endif // TRACE_STATUS
371 #if defined(TRACE_STATUS)
372 fprintf(stderr,
"OK got status open command!\n");
fflush(stderr);
373 #endif // TRACE_STATUS
403 #if defined(TRACE_STATUS_MORE)
404 fprintf(stderr,
"in aw_status_timer_event\n");
fflush(stdout);
405 #endif // TRACE_STATUS_MORE
408 "Couldn't quit properly in time.\n"
409 "Now you can either\n"
410 "- wait again (recommended),\n"
411 "- kill the whole application(!) or\n"
413 "Wait again,Kill application!,Continue");
420 sprintf(buf,
"kill -9 %i", aw_stg.
pid);
429 "please send the following information to devel@arb-home.de:\n"
431 "Calculation not abortable from status window.\n"
454 if (!
aw_ask_sure(
"aw_status_kill",
"Are you sure to abort running calculation?")) {
462 #if defined(TRACE_STATUS_MORE)
464 #endif // TRACE_STATUS_MORE
473 if (aw_stg.
lines[i]) {
486 free(aw_stg.
lines[0]);
491 time_t t = time(
NULp);
492 struct tm *lt = localtime(&t);
493 const char *lf = strchr(message,
'\n');
497 const int indentation = 10;
500 while (lf) { lf = strchr(lf+1,
'\n'); ++count; }
502 int newsize = strlen(message)+count*indentation+1;
505 lf = strchr(message,
'\n');
509 memcpy(cp, message, len+1);
511 memset(cp,
' ', indentation);
515 lf = strchr(message,
'\n');
524 lt->tm_hour, lt->tm_min, lt->tm_sec,
537 #define MAX_SEC_WIDTH 7 // max width reported from sec2disp
538 #define MAX_SEC_WIDTH_STR stringize_pscan(MAX_SEC_WIDTH)
543 if (seconds<0) seconds = 0;
545 sprintf(buffer,
"%li sec", seconds);
548 long minutes = (seconds+30)/60;
551 sprintf(buffer,
"%li min", minutes);
554 long hours = minutes/60;
556 minutes = minutes%60;
557 if (minutes == 0 && hours<10) sprintf(buffer,
"%li hour%s", hours,
plural(hours));
558 else sprintf(buffer,
"%lih:%02lim", hours, minutes);
561 long days = hours/24;
564 if (hours == 0) sprintf(buffer,
"%li day%s", days,
plural(days));
565 else sprintf(buffer,
"%lid:%02lih", days, hours);
571 if (days == 0) sprintf(buffer,
"%li week%s", weeks,
plural(weeks));
572 else sprintf(buffer,
"%liw:%02lid", weeks, days);
575 const double MEAN_MONTH_DAYS = 365/12.0;
576 long months = days/MEAN_MONTH_DAYS;
578 days = days -
long(months*MEAN_MONTH_DAYS);
581 if (months == 1) strcpy(buffer,
"1 month");
582 else sprintf(buffer,
"%li mon", months);
584 else sprintf(buffer,
"%liM:%02liw", months, weeks);
587 long years = days/365;
589 months = days/MEAN_MONTH_DAYS;
591 if (months == 0) sprintf(buffer,
"%li year%s", years,
plural(years));
592 else sprintf(buffer,
"%liy:%02liM", years, months);
617 char *timestr = ctime(&t);
618 char *
nl = strchr(timestr,
'\n');
628 static time_t last_minute = 0;
629 static time_t last_second = 0;
632 double since_last_second = difftime(now, last_second);
633 if (since_last_second<1) hide =
true;
634 else last_second = now;
637 double since_last_minute = difftime(now, last_minute);
638 if (since_last_minute<60) hide =
true;
639 else last_minute = now;
642 double since_last_minute = difftime(now, last_minute);
643 if (since_last_minute<(15*60)) hide =
true;
644 else last_minute = now;
654 const char *elapsed =
sec2disp(sec_elapsed);
669 const char *ahead =
sec2disp(sec_ahead);
679 fputs(
"[unknown time + duration]", stderr);
690 static void aw_status_append_to_log(
const char*
str) {
691 static const char *logname = 0;
696 int fd = open(logname, O_WRONLY|O_APPEND);
697 if (fd == -1) fd = open(logname, O_CREAT|O_WRONLY|O_APPEND, S_IWUSR | S_IRUSR);
698 if (fd == -1)
return;
700 write(fd, str, strlen(str));
713 #if defined(TRACE_STATUS_MORE)
714 fprintf(stderr,
"in aw_status_timer_listen_event (aw_stg.is_child=%i)\n", (
int)aw_stg.
is_child);
fflush(stdout);
715 #endif // TRACE_STATUS_MORE
734 #if defined(TRACE_STATUS)
735 fprintf(stderr,
"received AW_STATUS_CMD_OPEN\n");
fflush(stdout);
736 #endif // TRACE_STATUS
748 #if defined(ARB_LOGGING)
749 aw_status_append_to_log(
"----------------------------");
750 #endif // ARB_LOGGING
764 #if defined(TRACE_STATUS)
765 fprintf(stderr,
"received AW_STATUS_CMD_CLOSE\n");
fflush(stdout);
766 #endif // TRACE_STATUS
772 #if defined(FORCE_WEIGHTED_ESTIMATION)
773 if (strcmp(str,
"REQUEST_ESTIMATION") == 0) {
781 #if defined(TRACE_STATUS)
782 fprintf(stderr,
"received AW_STATUS_CMD_TEXT\n");
fflush(stdout);
783 #endif // TRACE_STATUS
784 #if defined(ARB_LOGGING)
785 aw_status_append_to_log(str);
786 #endif // ARB_LOGGING
792 #if defined(TRACE_STATUS)
793 fprintf(stderr,
"received AW_STATUS_CMD_NEW_TITLE\n");
fflush(stdout);
794 #endif // TRACE_STATUS
795 #if defined(ARB_LOGGING)
796 aw_status_append_to_log(str);
797 #endif // ARB_LOGGING
802 #if defined(TRACE_STATUS)
803 fprintf(stderr,
"received AW_STATUS_CMD_GAUGE\n");
fflush(stdout);
804 #endif // TRACE_STATUS
806 reassign(gauge, str);
816 off += sprintf(buffer+off,
"%i%% ", gaugePercent);
817 off += sprintf(buffer+off,
"Elapsed: %s ",
sec2disp(sec_elapsed));
824 long used_estimation = 0;
837 long sec_rest = used_estimation-sec_elapsed;
838 off += sprintf(buffer+off,
"Rest: %s",
sec2disp(sec_rest));
843 off += sprintf(buffer+off,
"Rest: ???");
848 #if defined(TRACE_STATUS)
849 fprintf(stderr,
"gauge=%i\n", gaugeValue);
fflush(stdout);
850 #endif // TRACE_STATUS
852 static int last_logged_gaugePercent = 0;
854 if (gaugePercent != last_logged_gaugePercent &&
855 gaugePercent>0 && gaugePercent<100)
857 sprintf(buffer,
"%i%%", gaugePercent);
859 (gaugePercent%5) == 0
864 last_logged_gaugePercent = gaugePercent;
867 else if (gaugeValue == 0) {
871 #if defined(TRACE_STATUS)
872 fprintf(stderr,
"reset status timer (gauge=0)\n");
fflush(stdout);
873 #endif // TRACE_STATUS
879 #if defined(TRACE_STATUS)
880 fprintf(stderr,
"received AW_STATUS_CMD_MESSAGE\n");
fflush(stdout);
881 #endif // TRACE_STATUS
882 #if defined(ARB_LOGGING)
883 aw_status_append_to_log(str);
884 #endif // ARB_LOGGING
897 #if defined(TRACE_STATUS_MORE)
898 fprintf(stderr,
"exited while loop\n");
fflush(stdout);
899 #endif // TRACE_STATUS_MORE
906 else if (delay<0) delay = 0;
907 #if defined(TRACE_STATUS_MORE)
908 fprintf(stderr,
"add aw_status_timer_listen_event with delay = %i\n", delay);
fflush(stdout);
909 #endif // TRACE_STATUS_MORE
927 FILE *out = fopen(fullname,
"wt");
930 error =
GB_IO_error(
"saving message box content to", fullname);
939 if (fclose(out) != 0) {
940 error =
GB_IO_error(
"saving message box content to", fullname);
946 const char *name =
"arb-message-box.txt";
979 aw_stg.
pid = getpid();
981 pid_t clientid = fork();
984 #if defined(TRACE_STATUS)
985 fprintf(stderr,
"Forked status! (i am the father)\n");
fflush(stderr);
986 #endif // TRACE_STATUS
992 #if defined(TRACE_STATUS)
993 fprintf(stderr,
"Forked status! (i am the child)\n");
fflush(stderr);
994 #endif // TRACE_STATUS
1004 AW_window_simple *aws =
new AW_window_simple;
1005 aws->init(aw_root,
"PROGRESS_BAR",
"ARB PROGRESS");
1006 aws->load_xfig(
"status.fig");
1023 aws->create_button(
"HIDE",
"Hide",
"h");
1027 aws->create_button(
"ABORT",
"Abort",
"k");
1035 AW_window_simple *
awm =
new AW_window_simple;
1036 awm->
init(aw_root,
"MESSAGE_BOX",
"MESSAGE BOX");
1037 awm->load_xfig(
"message.fig");
1039 awm->button_length(8);
1040 awm->auto_space(5, 5);
1047 awm->create_button(
"HIDE",
"Hide",
"h");
1050 awm->create_button(
"SAVE_PROPS",
"Save",
"S");
1053 awm->create_button(
"CLEAR",
"Clear",
"C");
1056 awm->create_button(
"HIDE_CLEAR",
"Ok",
"O");
1061 #if defined(TRACE_STATUS)
1062 fprintf(stderr,
"Created status window!\n");
fflush(stderr);
1063 #endif // TRACE_STATUS
1080 if (!text) text =
"";
1105 static int last_val = -1;
1108 if (val != last_val) {
1109 if (val>0 || gauge == 0.0) {
1145 printf(
"aw_message: '%s'\n", msg);
GB_ERROR GBK_system(const char *system_command)
#define AW_STATUS_PIPE_CHECK_DELAY
static ssize_t safe_write(int fd, const char *buf, int count)
static void status_write_cmd_and_text(StatusCommand cmd, const char *text, int textlen)
#define AW_STATUS_HIDE_DELAY
static aw_stg_struct aw_stg
void aw_openstatus(const char *title)
#define AWAR_STATUS_GAUGE
#define AW_GAUGE_GRANULARITY
#define MAX_SEC_WIDTH_STR
#define AWAR_STATUS_TITLE
static void aw_status_hide(AW_window *aws)
GB_ERROR GB_IO_error(const char *action, const char *filename)
void aw_status_title(const char *new_title)
const char * GBS_global_string(const char *templat,...)
static int aw_status_read_byte(int fd, int poll_flag)
void AW_POPDOWN(AW_window *window)
void add_timed_callback_never_disabled(int ms, const TimedCallback &tcb)
void cat(const char *from)
void add_timed_callback(int ms, const TimedCallback &tcb)
static void aw_status_write(int fd, int cmd)
char buffer[MESSAGE_BUFFERSIZE]
static void save_messagebox_content_to(const char *name)
void LOG_STATUS(const char *txt1, const char *txt2, LogLevel level)
const char * plural(NUM val)
const char * read_char_pntr() const
static AW_root * SINGLETON
static int diff(int v1, int v2, int v3, int v4, int st, int en)
void aw_clear_message_cb(AW_window *aww)
static unsigned aw_status_timer_event(AW_root *awr)
static void mark_pipe_broken(int err_no)
static unsigned aw_status_timer_hide_event(AW_root *)
static void aw_message_save_cb(AW_window *aww)
GB_ERROR GB_install_pid(int mode)
#define AW_STATUS_KILL_DELAY
TYPE * ARB_alloc(size_t nelem)
const char * sec2disp(long seconds)
static GB_CSTR GB_getenvHOME()
static void aw_status_kill(AW_window *aws)
void GBK_terminate(const char *error) __ATTR__NORETURN
const char * readableTime(const time_t &t)
#define AW_STATUS_LISTEN_DELAY
void AW_save_properties(AW_window *aw)
long last_estimation[AW_EST_BUFFER]
void message(char *errortext)
static void error(const char *msg)
void aw_status_subtitle(const char *text)
char * read_string() const
static void aw_insert_message_in_tmp_message_delayed(const char *message)
AW_awar * awar(const char *awar)
static AW_window_menu_modes_opengl * awm
static time_t status_started
bool aw_ask_sure(const char *unique_id, const char *msg)
int aw_question(const char *unique_id, const char *question, const char *buttons, bool sameSizeButtons, const char *helpfile)
fputs(TRACE_PREFIX, stderr)
static void copy(double **i, double **j)
static void create_status_awars(AW_root *aw_root)
static int aw_status_read_int(int fd, int poll_flag)
#define AWAR_ERROR_MESSAGES
static unsigned aw_status_timer_listen_event(AW_root *awr)
GB_CSTR GB_path_in_HOME(const char *relative_path)
void aw_message(const char *msg)
void aw_status_gauge(double gauge)
static void aw_status_wait_for_open(int fd)
static void aw_status_check_pipe()
static void aw_refresh_tmp_message_display(AW_root *awr)
GB_ERROR write_string(const char *aw_string)
const char * get_data() const
static void aw_clear_and_hide_message_cb(AW_window *aww)
static void aw_insert_message_in_tmp_message(AW_root *awr, const char *message)
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
#define AWAR_STATUS_ELAPSED
void aw_message_if(GB_ERROR error)
static int aw_status_read_command(int fd, int poll_flag, char *&str, int *gaugePtr=NULp)
char * GBS_global_string_copy(const char *templat,...)
void aw_set_local_message()
char * lines[AW_MESSAGE_LINES]