root / util / qemu-progress.c @ e69968d4
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 "qemu/osdep.h" |
27 |
#include <stdio.h> |
28 |
|
29 |
struct progress_state {
|
30 |
float current;
|
31 |
float last_print;
|
32 |
float min_skip;
|
33 |
void (*print)(void); |
34 |
void (*end)(void); |
35 |
}; |
36 |
|
37 |
static struct progress_state state; |
38 |
static volatile sig_atomic_t print_pending; |
39 |
|
40 |
/*
|
41 |
* Simple progress print function.
|
42 |
* @percent relative percent of current operation
|
43 |
* @max percent of total operation
|
44 |
*/
|
45 |
static void progress_simple_print(void) |
46 |
{ |
47 |
printf(" (%3.2f/100%%)\r", state.current);
|
48 |
fflush(stdout); |
49 |
} |
50 |
|
51 |
static void progress_simple_end(void) |
52 |
{ |
53 |
printf("\n");
|
54 |
} |
55 |
|
56 |
static void progress_simple_init(void) |
57 |
{ |
58 |
state.print = progress_simple_print; |
59 |
state.end = progress_simple_end; |
60 |
} |
61 |
|
62 |
#ifdef CONFIG_POSIX
|
63 |
static void sigusr_print(int signal) |
64 |
{ |
65 |
print_pending = 1;
|
66 |
} |
67 |
#endif
|
68 |
|
69 |
static void progress_dummy_print(void) |
70 |
{ |
71 |
if (print_pending) {
|
72 |
fprintf(stderr, " (%3.2f/100%%)\n", state.current);
|
73 |
print_pending = 0;
|
74 |
} |
75 |
} |
76 |
|
77 |
static void progress_dummy_end(void) |
78 |
{ |
79 |
} |
80 |
|
81 |
static void progress_dummy_init(void) |
82 |
{ |
83 |
#ifdef CONFIG_POSIX
|
84 |
struct sigaction action;
|
85 |
|
86 |
memset(&action, 0, sizeof(action)); |
87 |
sigfillset(&action.sa_mask); |
88 |
action.sa_handler = sigusr_print; |
89 |
action.sa_flags = 0;
|
90 |
sigaction(SIGUSR1, &action, NULL);
|
91 |
#endif
|
92 |
|
93 |
state.print = progress_dummy_print; |
94 |
state.end = progress_dummy_end; |
95 |
} |
96 |
|
97 |
/*
|
98 |
* Initialize progress reporting.
|
99 |
* If @enabled is false, actual reporting is suppressed. The user can
|
100 |
* still trigger a report by sending a SIGUSR1.
|
101 |
* Reports are also suppressed unless we've had at least @min_skip
|
102 |
* percent progress since the last report.
|
103 |
*/
|
104 |
void qemu_progress_init(int enabled, float min_skip) |
105 |
{ |
106 |
state.min_skip = min_skip; |
107 |
if (enabled) {
|
108 |
progress_simple_init(); |
109 |
} else {
|
110 |
progress_dummy_init(); |
111 |
} |
112 |
} |
113 |
|
114 |
void qemu_progress_end(void) |
115 |
{ |
116 |
state.end(); |
117 |
} |
118 |
|
119 |
/*
|
120 |
* Report progress.
|
121 |
* @delta is how much progress we made.
|
122 |
* If @max is zero, @delta is an absolut value of the total job done.
|
123 |
* Else, @delta is a progress delta since the last call, as a fraction
|
124 |
* of @max. I.e. the delta is @delta * @max / 100. This allows
|
125 |
* relative accounting of functions which may be a different fraction of
|
126 |
* the full job, depending on the context they are called in. I.e.
|
127 |
* a function might be considered 40% of the full job if used from
|
128 |
* bdrv_img_create() but only 20% if called from img_convert().
|
129 |
*/
|
130 |
void qemu_progress_print(float delta, int max) |
131 |
{ |
132 |
float current;
|
133 |
|
134 |
if (max == 0) { |
135 |
current = delta; |
136 |
} else {
|
137 |
current = state.current + delta / 100 * max;
|
138 |
} |
139 |
if (current > 100) { |
140 |
current = 100;
|
141 |
} |
142 |
state.current = current; |
143 |
|
144 |
if (current > (state.last_print + state.min_skip) ||
|
145 |
(current == 100) || (current == 0)) { |
146 |
state.last_print = state.current; |
147 |
state.print(); |
148 |
} |
149 |
} |