root / qemu-progress.c @ c48c6522
History | View | Annotate | Download (4 kB)
1 |
/*
|
---|---|
2 |
* QEMU progress printing utility functions
|
3 |
*
|
4 |
* Copyright (C) 2011 Jes Sorensen <Jes.Sorensen@redhat.com>
|
5 |
*
|
6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 |
* of this software and associated documentation files (the "Software"), to deal
|
8 |
* in the Software without restriction, including without limitation the rights
|
9 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 |
* copies of the Software, and to permit persons to whom the Software is
|
11 |
* furnished to do so, subject to the following conditions:
|
12 |
*
|
13 |
* The above copyright notice and this permission notice shall be included in
|
14 |
* all copies or substantial portions of the Software.
|
15 |
*
|
16 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 |
* THE SOFTWARE.
|
23 |
*/
|
24 |
|
25 |
#include "qemu-common.h" |
26 |
#include "osdep.h" |
27 |
#include "sysemu.h" |
28 |
#include <stdio.h> |
29 |
|
30 |
struct progress_state {
|
31 |
float current;
|
32 |
float last_print;
|
33 |
float min_skip;
|
34 |
void (*print)(void); |
35 |
void (*end)(void); |
36 |
}; |
37 |
|
38 |
static struct progress_state state; |
39 |
static volatile sig_atomic_t print_pending; |
40 |
|
41 |
/*
|
42 |
* Simple progress print function.
|
43 |
* @percent relative percent of current operation
|
44 |
* @max percent of total operation
|
45 |
*/
|
46 |
static void progress_simple_print(void) |
47 |
{ |
48 |
printf(" (%3.2f/100%%)\r", state.current);
|
49 |
fflush(stdout); |
50 |
} |
51 |
|
52 |
static void progress_simple_end(void) |
53 |
{ |
54 |
printf("\n");
|
55 |
} |
56 |
|
57 |
static void progress_simple_init(void) |
58 |
{ |
59 |
state.print = progress_simple_print; |
60 |
state.end = progress_simple_end; |
61 |
} |
62 |
|
63 |
#ifdef CONFIG_POSIX
|
64 |
static void sigusr_print(int signal) |
65 |
{ |
66 |
print_pending = 1;
|
67 |
} |
68 |
#endif
|
69 |
|
70 |
static void progress_dummy_print(void) |
71 |
{ |
72 |
if (print_pending) {
|
73 |
fprintf(stderr, " (%3.2f/100%%)\n", state.current);
|
74 |
print_pending = 0;
|
75 |
} |
76 |
} |
77 |
|
78 |
static void progress_dummy_end(void) |
79 |
{ |
80 |
} |
81 |
|
82 |
static void progress_dummy_init(void) |
83 |
{ |
84 |
#ifdef CONFIG_POSIX
|
85 |
struct sigaction action;
|
86 |
|
87 |
memset(&action, 0, sizeof(action)); |
88 |
sigfillset(&action.sa_mask); |
89 |
action.sa_handler = sigusr_print; |
90 |
action.sa_flags = 0;
|
91 |
sigaction(SIGUSR1, &action, NULL);
|
92 |
#endif
|
93 |
|
94 |
state.print = progress_dummy_print; |
95 |
state.end = progress_dummy_end; |
96 |
} |
97 |
|
98 |
/*
|
99 |
* Initialize progress reporting.
|
100 |
* If @enabled is false, actual reporting is suppressed. The user can
|
101 |
* still trigger a report by sending a SIGUSR1.
|
102 |
* Reports are also suppressed unless we've had at least @min_skip
|
103 |
* percent progress since the last report.
|
104 |
*/
|
105 |
void qemu_progress_init(int enabled, float min_skip) |
106 |
{ |
107 |
state.min_skip = min_skip; |
108 |
if (enabled) {
|
109 |
progress_simple_init(); |
110 |
} else {
|
111 |
progress_dummy_init(); |
112 |
} |
113 |
} |
114 |
|
115 |
void qemu_progress_end(void) |
116 |
{ |
117 |
state.end(); |
118 |
} |
119 |
|
120 |
/*
|
121 |
* Report progress.
|
122 |
* @delta is how much progress we made.
|
123 |
* If @max is zero, @delta is an absolut value of the total job done.
|
124 |
* Else, @delta is a progress delta since the last call, as a fraction
|
125 |
* of @max. I.e. the delta is @delta * @max / 100. This allows
|
126 |
* relative accounting of functions which may be a different fraction of
|
127 |
* the full job, depending on the context they are called in. I.e.
|
128 |
* a function might be considered 40% of the full job if used from
|
129 |
* bdrv_img_create() but only 20% if called from img_convert().
|
130 |
*/
|
131 |
void qemu_progress_print(float delta, int max) |
132 |
{ |
133 |
float current;
|
134 |
|
135 |
if (max == 0) { |
136 |
current = delta; |
137 |
} else {
|
138 |
current = state.current + delta / 100 * max;
|
139 |
} |
140 |
if (current > 100) { |
141 |
current = 100;
|
142 |
} |
143 |
state.current = current; |
144 |
|
145 |
if (current > (state.last_print + state.min_skip) ||
|
146 |
(current == 100) || (current == 0)) { |
147 |
state.last_print = state.current; |
148 |
state.print(); |
149 |
} |
150 |
} |