1
/* meter.c - lutil_meter meters */
2
/* $OpenLDAP: pkg/ldap/libraries/liblutil/meter.c,v 1.2.2.1 2009/02/05 20:10:59 quanah Exp $ */
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5
* Copyright (c) 2009 by Matthew Backes, Symas Corp.
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted only as authorized by the OpenLDAP
12
* A copy of this license is available in the file LICENSE in the
13
* top-level directory of the distribution or, alternatively, at
14
* <http://www.OpenLDAP.org/license.html>.
17
* This work was initially developed by Matthew Backes for inclusion
18
* in OpenLDAP software.
22
#include "lutil_meter.h"
24
#include <ac/assert.h>
25
#include <ac/string.h>
33
static const int time_div[] = {31556952,
40
const int * time_divp = time_div;
41
static const char * time_name_ch = "ywdhms";
42
const char * time_name_chp = time_name_ch;
47
assert ( max_terms >= 2 ); /* room for "none" message */
53
if ( duration == 0 ) {
54
strcpy( dest, "none" );
57
while ( term_count < max_terms && duration > 0 ) {
58
if (duration > *time_divp) {
59
time_quot = duration / *time_divp;
60
duration %= *time_divp;
64
*(buf++) = time_quot / 10 + '0';
65
*(buf++) = time_quot % 10 + '0';
66
*(buf++) = *time_name_chp;
70
if ( *(++time_divp) == 0) duration = 0;
78
lutil_get_now (double *now)
80
#ifdef HAVE_GETTIMEOFDAY
84
gettimeofday( &tv, NULL );
85
*now = ((double) tv.tv_sec) + (((double) tv.tv_usec) / 1000000.0);
100
const lutil_meter_display_t *display,
101
const lutil_meter_estimator_t *estimator,
102
unsigned long goal_value)
106
assert( meter != NULL );
107
assert( display != NULL );
108
assert( estimator != NULL );
110
if (goal_value < 1) return -1;
112
memset( (void*) meter, 0, sizeof( lutil_meter_t ));
113
meter->display = display;
114
meter->estimator = estimator;
115
lutil_get_now( &meter->start_time );
116
meter->last_update = meter->start_time;
117
meter->goal_value = goal_value;
118
meter->last_position = 0;
120
rc = meter->display->display_open( &meter->display_data );
121
if( rc != 0 ) return rc;
123
rc = meter->estimator->estimator_open( &meter->estimator_data );
125
meter->display->display_close( &meter->display_data );
134
lutil_meter_t *meter,
135
unsigned long position,
138
static const double display_rate = 0.5;
139
double frac, cycle_length, speed, now;
140
time_t remaining_time, elapsed;
143
assert( meter != NULL );
144
assert( position >= 0 );
146
lutil_get_now( &now );
148
if ( !force && now - meter->last_update < display_rate ) return 0;
150
frac = ((double)position) / ((double) meter->goal_value);
151
elapsed = now - meter->start_time;
152
if (frac <= 0.0) return 0;
154
rc = meter->display->display_update(
155
&meter->display_data,
159
((double)position) / elapsed);
161
rc = meter->estimator->estimator_update(
162
&meter->estimator_data,
167
cycle_length = now - meter->last_update;
168
speed = cycle_length > 0.0 ?
169
((double)(position - meter->last_position))
172
rc = meter->display->display_update(
173
&meter->display_data,
179
meter->last_update = now;
180
meter->last_position = position;
189
lutil_meter_close (lutil_meter_t *meter)
191
meter->estimator->estimator_close( &meter->estimator_data );
192
meter->display->display_close( &meter->display_data );
197
/* Default display and estimator */
204
} text_display_state_t;
207
text_open (void ** display_datap)
209
static const int default_buffer_length = 81;
210
text_display_state_t *data;
212
assert( display_datap != NULL );
213
data = calloc( 1, sizeof( text_display_state_t ));
214
assert( data != NULL );
215
data->buffer_length = default_buffer_length;
216
data->buffer = calloc( 1, default_buffer_length );
217
assert( data->buffer != NULL );
218
data->output = stderr;
219
*display_datap = data;
225
void **display_datap,
227
time_t remaining_time,
231
text_display_state_t *data;
234
assert( display_datap != NULL );
235
assert( *display_datap != NULL );
236
data = (text_display_state_t*) *display_datap;
238
if ( data->output == NULL ) return 1;
241
buf_end = buf + data->buffer_length - 1;
243
/* |#################### 100.00% eta 1d19h elapsed 23w 7d23h15m12s spd nnnn.n M/s */
247
static const int phase_mod = 8;
248
static const char phase_char[] = "_.-*\"*-.";
249
*buf++ = phase_char[data->phase % phase_mod];
255
static const int bar_length = 20;
256
static const double bar_lengthd = 20.0;
257
static const char fill_char = '#';
258
static const char blank_char = ' ';
259
char *bar_end = buf + bar_length;
260
char *bar_pos = frac < 0.0 ?
263
buf + (int) (bar_lengthd * frac) :
266
assert( (buf_end - buf) > bar_length );
267
while ( buf < bar_end ) {
268
*buf = buf < bar_pos ?
269
fill_char : blank_char;
276
(void) snprintf( buf, buf_end-buf, "%7.2f%%", 100.0*frac );
281
/* eta and elapsed */
282
char time_buffer[19];
284
rc = lutil_time_string( time_buffer, remaining_time, 2);
286
snprintf( buf, buf_end-buf, " eta %6s", time_buffer );
288
rc = lutil_time_string( time_buffer, elapsed, 5);
290
snprintf( buf, buf_end-buf, " elapsed %15s",
297
static const char prefixes[] = " kMGTPEZY";
298
const char *prefix_chp = prefixes;
300
while (*prefix_chp && byte_rate >= 1024.0) {
304
if ( byte_rate >= 1024.0 ) {
305
snprintf( buf, buf_end-buf, " fast!" );
308
snprintf( buf, buf_end-buf, " spd %5.1f %c/s",
315
(void) fprintf( data->output,
323
text_close (void ** display_datap)
325
text_display_state_t *data;
328
if (*display_datap) {
329
data = (text_display_state_t*) *display_datap;
330
if (data->output && data->need_eol)
331
fputs ("\n", data->output);
333
free( data->buffer );
336
*display_datap = NULL;
342
null_open_close (void **datap)
351
void **estimator_datap,
359
assert( estimator_datap != NULL );
360
assert( *estimator_datap == NULL );
361
assert( start > 0.0 );
362
assert( frac >= 0.0 );
363
assert( frac <= 1.0 );
364
assert( remaining != NULL );
365
lutil_get_now( &now );
368
assert( elapsed >= 0.0 );
372
} else if ( frac >= 1.0 ) {
376
*remaining = (time_t) (elapsed/frac-elapsed+0.5);
381
const lutil_meter_display_t lutil_meter_text_display = {
382
text_open, text_update, text_close
385
const lutil_meter_estimator_t lutil_meter_linear_estimator = {
386
null_open_close, linear_update, null_open_close