source: branches/stable/CORE/arb_handlers.cxx

Last change on this file was 11060, checked in by westram, 6 years ago
File size: 6.1 KB
Line 
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_assert.h>
15#include "arb_misc.h"
16#include <smartptr.h>
17#include <unistd.h>
18#include <time.h>
19#include <arb_algo.h>
20
21// AISC_MKPT_PROMOTE:#ifndef ARB_CORE_H
22// AISC_MKPT_PROMOTE:#include <arb_core.h>
23// AISC_MKPT_PROMOTE:#endif
24
25static FILE *arberr = stderr;
26static FILE *arbout = stdout;
27
28static void to_arberr(const char *msg) {
29    fflush(arbout);
30    fprintf(arberr, "%s\n", msg);
31    fflush(arberr);
32}
33static void to_arbout(const char *msg) {
34    fprintf(arbout, "%s\n", msg);
35}
36
37// -------------------------
38//      ARB_arbout_status
39
40const int  WIDTH = 70;
41const char CHAR  = '.';
42
43const int MIN_SECONDS_PER_ROW = 10;   // otherwise decrease number of rows
44const int MAX_SECONDS_PER_ROW = 3*60; // otherwise increase number of rows
45
46const int DEFAULT_HEIGHT = 12; // 12 can be devided by 2, 3, 4, 6 (so subtitles tend to be at start of line)
47const int MAXHEIGHT      = 3*DEFAULT_HEIGHT;
48
49class BasicStatus : virtual Noncopyable {
50    int         openCount;
51    char       *subtitle;
52    int         printed;
53    const char *cursor;
54
55    bool mayRedicideHeight;
56    int  height;
57
58    time_t start;
59
60    void reset() {
61        printed  = 0;
62        cursor   = NULL;
63        subtitle = NULL;
64
65        time(&start);
66        mayRedicideHeight = true;
67        height = DEFAULT_HEIGHT;
68    }
69
70public:
71    BasicStatus() : openCount(0) { reset(); }
72    ~BasicStatus() { if (openCount) close(); }
73
74    void open(const char *title) {
75        arb_assert(++openCount <= 1);
76        fprintf(arbout, "Progress: %s\n", title);
77        reset();
78    }
79    void close() {
80        freenull(subtitle);
81        fprintf(arbout, "[done]\n");
82        arb_assert(--openCount >= 0);
83        fflush(arbout);
84    }
85
86    int next_LF() const { return printed-printed%WIDTH+WIDTH; }
87
88    void set_subtitle(const char *stitle) {
89        arb_assert(openCount == 1);
90        if (!cursor) {
91            freeset(subtitle, GBS_global_string_copy("{%s}", stitle));
92            cursor = subtitle;
93        }
94    }
95
96    static double estimate_overall_seconds(double seconds_passed, double gauge) {
97        return seconds_passed / gauge;
98    }
99
100    void set_gauge(double gauge) {
101        arb_assert(openCount == 1);
102
103        int wanted = int(gauge*WIDTH*height);
104        if (printed<wanted) {
105            while (printed<wanted) {
106                if (cursor && cursor[0]) {
107                    fputc(*cursor++, arbout);
108                }
109                else {
110                    cursor = 0;
111                    fputc(CHAR, arbout);
112                }
113                int nextLF = next_LF();
114                printed++;
115                if (printed == nextLF) {
116                    mayRedicideHeight = false;
117
118                    time_t now;
119                    time(&now);
120
121                    fprintf(arbout, " [%5.1f%%]", printed*100.0/(WIDTH*height));
122                    bool   done    = (printed == (WIDTH*height));
123                    double seconds = difftime(now, start);
124
125                    const char *whatshown = done ? "used" : "left";
126                    fprintf(arbout, " %s: ", whatshown);
127
128                    long show_sec = done ? seconds : long((estimate_overall_seconds(seconds, gauge)-seconds)+0.5);
129                    fputs(GBS_readable_timediff(show_sec), arbout);
130                    fputc('\n', arbout);
131
132                    nextLF = next_LF();
133                }
134                else if (mayRedicideHeight) {
135                    if ((2*printed) > nextLF) {
136                        mayRedicideHeight = false; // stop redeciding
137                    }
138                    else {
139                        time_t now;
140                        time(&now);
141
142                        double seconds         = difftime(now, start)+0.5;
143                        double overall_seconds = estimate_overall_seconds(seconds, gauge);
144
145                        int max_wanted_height = int(overall_seconds/MIN_SECONDS_PER_ROW+0.5);
146                        int min_wanted_height = int(overall_seconds/MAX_SECONDS_PER_ROW+0.5);
147
148                        arb_assert(min_wanted_height <= max_wanted_height);
149
150                        height = force_in_range(min_wanted_height, DEFAULT_HEIGHT, max_wanted_height);
151                        height = force_in_range(1, height, MAXHEIGHT);
152                    }
153                }
154            }
155            fflush(arbout);
156#if defined(DEBUG)
157            // GB_sleep(25, MS); // uncomment to see slow status
158#endif
159        }
160    }
161};
162
163static BasicStatus status;
164
165static void basic_openstatus(const char *title) { status.open(title); }
166static void basic_closestatus() { status.close(); }
167static bool basic_set_title(const char */*title*/) { return false; }
168static bool basic_set_subtitle(const char *stitle) { status.set_subtitle(stitle); return false; }
169static bool basic_set_gauge(double gauge) { status.set_gauge(gauge); return false; }
170static bool basic_user_abort() { return false; }
171
172static arb_status_implementation ARB_arbout_status = {
173    AST_FORWARD, 
174    basic_openstatus,
175    basic_closestatus,
176    basic_set_title,
177    basic_set_subtitle,
178    basic_set_gauge,
179    basic_user_abort
180};
181
182static arb_handlers arbout_handlers = {
183    to_arberr,
184    to_arbout,
185    to_arbout,
186    ARB_arbout_status,
187};
188
189arb_handlers *active_arb_handlers = &arbout_handlers; // default-handlers
190
191void ARB_install_handlers(arb_handlers& handlers) { active_arb_handlers = &handlers; }
192
193void ARB_redirect_handlers_to(FILE *errStream, FILE *outStream) {
194    arberr = errStream;
195    arbout = outStream;
196}
Note: See TracBrowser for help on using the repository browser.