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