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  freeset(subtitle, GBS_global_string_copy("{%s}", stitle));
100  cursor = subtitle;
101  }
102  }
103 
104  static double estimate_overall_seconds(double seconds_passed, double gauge) {
105  return seconds_passed / gauge;
106  }
107 
108  void set_gauge(double gauge) {
109  arb_assert(openCount == 1);
110 
111  int wanted = int(gauge*WIDTH*height);
112  if (printed<wanted) {
113 #if defined(TRACE_BASIC_COUNTER)
114  fprintf(arbout, "\nBasicStatus::set_gauge(gauge=%f) -> wanted=%i printed=%i; ", gauge, wanted, printed);
115 #endif
116  while (printed<wanted) {
117  if (cursor && cursor[0]) {
118  fputc(*cursor++, arbout);
119  }
120  else {
121  cursor = NULp;
122  fputc(CHAR, arbout);
123  }
124  int nextLF = next_LF();
125  printed++;
126  if (printed == nextLF) {
127  mayReconsiderHeight = false;
128 
129  time_t now;
130  time(&now);
131 
132  fprintf(arbout, " [%5.1f%%]", printed*100.0/(WIDTH*height));
133  bool done = (printed == (WIDTH*height));
134  double seconds = difftime(now, start);
135 
136  const char *whatshown = done ? "used" : "left";
137  fprintf(arbout, " %s: ", whatshown);
138 
139  long show_sec = done ? seconds : long((estimate_overall_seconds(seconds, gauge)-seconds)+0.5);
140  fputs(GBS_readable_timediff(show_sec), arbout);
141  fputc('\n', arbout);
142 
143  nextLF = next_LF();
144  }
145  else if (mayReconsiderHeight) {
146  if ((2*printed) > nextLF) {
147  mayReconsiderHeight = false; // stop redeciding
148  }
149  else {
150  time_t now;
151  time(&now);
152 
153  double seconds = difftime(now, start)+0.5;
154  double overall_seconds = estimate_overall_seconds(seconds, gauge);
155 
156  int max_wanted_height = int(overall_seconds/MIN_SECONDS_PER_ROW+0.5);
157  int min_wanted_height = int(overall_seconds/MAX_SECONDS_PER_ROW+0.5);
158 
159  arb_assert(min_wanted_height <= max_wanted_height);
160 
161  int old_height = height;
162 
163  height = force_in_range(min_wanted_height, DEFAULT_HEIGHT, max_wanted_height);
164  height = force_in_range(1, height, MAXHEIGHT);
165 
166  if (old_height != height) {
167 #if defined(TRACE_BASIC_COUNTER)
168  fprintf(arbout, "redeciding height=%i printedAtHeightChange=%i printed=%i wanted=%i\n", height, printedAtHeightChange, printed, wanted);
169 #endif
170  printedAtHeightChange = std::max(printedAtHeightChange, printed);
171  // now 'wanted' got wrong -> rerun this loop by recursion
172  set_gauge(gauge);
173  return;
174  }
175  }
176  }
177  }
178  fflush(arbout);
179 #if defined(DEBUG)
180  // ARB_sleep(25, MS); // uncomment to see slow status
181 #endif
182  }
183  else if (!mayReconsiderHeight && printed>printedAtHeightChange && wanted<printed) {
184  arb_assert(wanted>0);
185  int print_limit = (printed * 9) / 10;
186  if (wanted<print_limit) {
187  int print_again_from = (wanted * 8) / 10;
188  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);
189  printed = print_again_from;
190 
191  // rerun this loop by recursion:
192  set_gauge(gauge);
193  arb_assert(0); // progress went backwards. to find reason, uncomment TRACE_BASIC_COUNTER and run in debugger!
194  return;
195  }
196  }
197  }
198 };
199 
201 
202 static void basic_openstatus(const char *title) { status.open(title); }
203 static void basic_closestatus() { status.close(); }
204 static void basic_set_title(const char */*title*/) { }
205 static void basic_set_subtitle(const char *stitle) { status.set_subtitle(stitle); }
206 static void basic_set_gauge(double gauge) {
207  arb_assert(gauge>=0);
208  status.set_gauge(gauge);
209 }
210 static bool basic_user_abort() { return false; }
211 
213  AST_FORWARD,
214  basic_openstatus, // openstatus
215  basic_closestatus, // closestatus
216  basic_set_title, // set_title
217  basic_set_subtitle, // set_subtitle
218  basic_set_gauge, // set_gauge
219  basic_user_abort // user_abort
220 };
221 
223  to_arberr,
224  to_arbout,
225  to_arbout,
227 };
228 
230 
231 void ARB_install_handlers(arb_handlers& handlers) { active_arb_handlers = &handlers; }
232 
233 void ARB_redirect_handlers_to(FILE *errStream, FILE *outStream) {
234  arberr = errStream;
235  arbout = outStream;
236 }
#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:154
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:97
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:195
#define max(a, b)
Definition: f2c.h:154