ARB
arb_handlers.cxx
Go to the documentation of this file.
1 // ================================================================ //
2 // //
3 // File : arb_handlers.cxx //
4 // Purpose : //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in November 2010 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // ================================================================ //
11 
12 #include <arb_handlers.h>
13 #include <arb_msg.h>
14 #include "arb_misc.h"
15 #include <smartptr.h>
16 #include <unistd.h>
17 #include <time.h>
18 #include <arb_algo.h>
19 
20 // AISC_MKPT_PROMOTE:#ifndef ARB_CORE_H
21 // AISC_MKPT_PROMOTE:#include <arb_core.h>
22 // AISC_MKPT_PROMOTE:#endif
23 
24 static FILE *arberr = stderr;
25 static FILE *arbout = stdout;
26 
27 static void to_arberr(const char *msg) {
28  fflush(arbout);
29  fprintf(arberr, "%s\n", msg);
30  fflush(arberr);
31 }
32 static void to_arbout(const char *msg) {
33  fprintf(arbout, "%s\n", msg);
34 }
35 
36 // -------------------------
37 // ARB_arbout_status
38 
39 const int WIDTH = 70;
40 const char CHAR = '.';
41 
42 const int MIN_SECONDS_PER_ROW = 10; // otherwise decrease number of rows
43 const int MAX_SECONDS_PER_ROW = 3*60; // otherwise increase number of rows
44 
45 const int DEFAULT_HEIGHT = 12; // 12 can be devided by 2, 3, 4, 6 (so subtitles tend to be at start of line)
46 const int MAXHEIGHT = 3*DEFAULT_HEIGHT;
47 
48 #if defined(DEBUG)
49 // # define TRACE_BASIC_COUNTER
50 #endif
51 
52 class BasicStatus : virtual Noncopyable {
53  int openCount;
54  char *subtitle;
55  const char *cursor;
56 
57  int printed;
58  int height; // number of rows to print (gets decided while printing 1st row)
59 
60  bool mayReconsiderHeight; // true -> 'height' may change
61  int printedAtHeightChange; // value of 'printed' at time when 'height' was reconsidered and changed
62 
63  time_t start;
64 
65  void reset() {
66  printed = 0;
67  cursor = NULp;
68  subtitle = NULp;
69 
70  time(&start);
71 
72  mayReconsiderHeight = true;
73  printedAtHeightChange = 0;
74 
75  height = DEFAULT_HEIGHT;
76  }
77 
78 public:
79  BasicStatus() : openCount(0) { reset(); }
80  ~BasicStatus() { if (openCount) close(); }
81 
82  void open(const char *title) {
83  arb_assert(++openCount <= 1);
84  fprintf(arbout, "Progress: %s\n", title);
85  reset();
86  }
87  void close() {
88  freenull(subtitle);
89  fprintf(arbout, "[done]\n");
90  arb_assert(--openCount >= 0);
91  fflush(arbout);
92  }
93 
94  int next_LF() const { return printed-printed%WIDTH+WIDTH; }
95 
96  void set_subtitle(const char *stitle) {
97  arb_assert(openCount == 1);
98  if (!cursor) {
99 #if defined(FORCE_WEIGHTED_ESTIMATION)
100  if (strcmp(stitle, "REQUEST_ESTIMATION") == 0) { // hack
101  return;
102  }
103 #endif
104  freeset(subtitle, GBS_global_string_copy("{%s}", stitle));
105  cursor = subtitle;
106  }
107  }
108 
109  static double estimate_overall_seconds(double seconds_passed, double gauge) {
110  return seconds_passed / gauge;
111  }
112 
113  void set_gauge(double gauge) {
114  arb_assert(openCount == 1);
115 
116  int wanted = int(gauge*WIDTH*height);
117  if (printed<wanted) {
118 #if defined(TRACE_BASIC_COUNTER)
119  fprintf(arbout, "\nBasicStatus::set_gauge(gauge=%f) -> wanted=%i printed=%i; ", gauge, wanted, printed);
120 #endif
121  while (printed<wanted) {
122  if (cursor && cursor[0]) {
123  fputc(*cursor++, arbout);
124  }
125  else {
126  cursor = NULp;
127  fputc(CHAR, arbout);
128  }
129  int nextLF = next_LF();
130  printed++;
131  if (printed == nextLF) {
132  mayReconsiderHeight = false;
133 
134  time_t now;
135  time(&now);
136 
137  fprintf(arbout, " [%5.1f%%]", printed*100.0/(WIDTH*height));
138  bool done = (printed == (WIDTH*height));
139  double seconds = difftime(now, start);
140 
141  const char *whatshown = done ? "used" : "left";
142  fprintf(arbout, " %s: ", whatshown);
143 
144  long show_sec = done ? seconds : long((estimate_overall_seconds(seconds, gauge)-seconds)+0.5);
145  fputs(GBS_readable_timediff(show_sec), arbout);
146  fputc('\n', arbout);
147 
148  nextLF = next_LF();
149  }
150  else if (mayReconsiderHeight) {
151  if ((2*printed) > nextLF) {
152  mayReconsiderHeight = false; // stop redeciding
153  }
154  else {
155  time_t now;
156  time(&now);
157 
158  double seconds = difftime(now, start)+0.5;
159  double overall_seconds = estimate_overall_seconds(seconds, gauge);
160 
161  int max_wanted_height = int(overall_seconds/MIN_SECONDS_PER_ROW+0.5);
162  int min_wanted_height = int(overall_seconds/MAX_SECONDS_PER_ROW+0.5);
163 
164  arb_assert(min_wanted_height <= max_wanted_height);
165 
166  int old_height = height;
167 
168  height = force_in_range(min_wanted_height, DEFAULT_HEIGHT, max_wanted_height);
169  height = force_in_range(1, height, MAXHEIGHT);
170 
171  if (old_height != height) {
172 #if defined(TRACE_BASIC_COUNTER)
173  fprintf(arbout, "redeciding height=%i printedAtHeightChange=%i printed=%i wanted=%i\n", height, printedAtHeightChange, printed, wanted);
174 #endif
175  printedAtHeightChange = std::max(printedAtHeightChange, printed);
176  // now 'wanted' got wrong -> rerun this loop by recursion
177  set_gauge(gauge);
178  return;
179  }
180  }
181  }
182  }
183  fflush(arbout);
184 #if defined(DEBUG)
185  // ARB_sleep(25, MS); // uncomment to see slow status
186 #endif
187  }
188  else if (!mayReconsiderHeight && printed>printedAtHeightChange && wanted<printed) {
189  arb_assert(wanted>0);
190  int print_limit = (printed * 9) / 10;
191  if (wanted<print_limit) {
192  int print_again_from = (wanted * 8) / 10;
193  fprintf(arbout, "\n *** progress counter ran backwards *** (wanted=%i printed=%i print_limit=%i print_again_from=%i)\n", wanted, printed, print_limit, print_again_from);
194  printed = print_again_from;
195 
196  // rerun this loop by recursion:
197  set_gauge(gauge);
198  arb_assert(0); // progress went backwards. to find reason, uncomment TRACE_BASIC_COUNTER and run in debugger!
199  return;
200  }
201  }
202  }
203 };
204 
206 
207 static void basic_openstatus(const char *title) { status.open(title); }
208 static void basic_closestatus() { status.close(); }
209 static void basic_set_title(const char */*title*/) { }
210 static void basic_set_subtitle(const char *stitle) { status.set_subtitle(stitle); }
211 static void basic_set_gauge(double gauge) {
212  arb_assert(gauge>=0);
213  status.set_gauge(gauge);
214 }
215 static bool basic_user_abort() { return false; }
216 
218  AST_FORWARD,
219  basic_openstatus, // openstatus
220  basic_closestatus, // closestatus
221  basic_set_title, // set_title
222  basic_set_subtitle, // set_subtitle
223  basic_set_gauge, // set_gauge
224  basic_user_abort // user_abort
225 };
226 
228  to_arberr,
229  to_arbout,
230  to_arbout,
232 };
233 
235 
236 void ARB_install_handlers(arb_handlers& handlers) { active_arb_handlers = &handlers; }
237 
238 void ARB_redirect_handlers_to(FILE *errStream, FILE *outStream) {
239  arberr = errStream;
240  arbout = outStream;
241 }
#define arb_assert(cond)
Definition: arb_assert.h:245
void set_gauge(double gauge)
const int DEFAULT_HEIGHT
static bool basic_user_abort()
long
Definition: AW_awar.cxx:152
static arb_handlers arbout_handlers
const char * title
Definition: readseq.c:22
const int MAXHEIGHT
static double estimate_overall_seconds(double seconds_passed, double gauge)
static void basic_openstatus(const char *title)
const int WIDTH
void open(const char *title)
fflush(stdout)
arb_handlers * active_arb_handlers
static void basic_set_title(const char *)
CONSTEXPR_INLINE const T & force_in_range(const T &lower_bound, const T &value, const T &upper_bound)
Definition: arb_algo.h:20
static void to_arbout(const char *msg)
void set_subtitle(const char *stitle)
int next_LF() const
fputc('\n', stderr)
static void basic_closestatus()
static FILE * arberr
const char * GBS_readable_timediff(size_t seconds)
Definition: arb_misc.cxx:46
static BasicStatus status
const int MIN_SECONDS_PER_ROW
static void basic_set_subtitle(const char *stitle)
fputs(TRACE_PREFIX, stderr)
const char CHAR
static void to_arberr(const char *msg)
void ARB_install_handlers(arb_handlers &handlers)
#define NULp
Definition: cxxforward.h:114
static arb_status_implementation ARB_arbout_status
static void basic_set_gauge(double gauge)
static FILE * arbout
const int MAX_SECONDS_PER_ROW
void ARB_redirect_handlers_to(FILE *errStream, FILE *outStream)
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:193
#define max(a, b)
Definition: f2c.h:154