source: tags/ms_r18q1/CORE/arb_handlers.cxx

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