1 /*-------------------------------------------------------------------------
2 *
3 * logging.c
4 * logging functions
5 *
6 * Copyright (c) 2010-2016, PostgreSQL Global Development Group
7 *
8 *-------------------------------------------------------------------------
9 */
10 #include "postgres_fe.h"
11
12 #include <unistd.h>
13 #include <time.h>
14
15 #include "pg_rewind.h"
16 #include "logging.h"
17
18 #include "pgtime.h"
19
20 /* Progress counters */
21 uint64 fetch_size;
22 uint64 fetch_done;
23
24 static pg_time_t last_progress_report = 0;
25
26 #define QUERY_ALLOC 8192
27
28 #define MESSAGE_WIDTH 60
29
30 static
31 pg_attribute_printf(2, 0)
32 void
pg_log_v(eLogType type,const char * fmt,va_list ap)33 pg_log_v(eLogType type, const char *fmt, va_list ap)
34 {
35 char message[QUERY_ALLOC];
36
37 vsnprintf(message, sizeof(message), _(fmt), ap);
38
39 switch (type)
40 {
41 case PG_DEBUG:
42 if (debug)
43 printf("%s", message);
44 break;
45
46 case PG_PROGRESS:
47 if (showprogress)
48 printf("%s", message);
49 break;
50
51 case PG_WARNING:
52 printf("%s", message);
53 break;
54
55 case PG_FATAL:
56 printf("\n%s", message);
57 printf("%s", _("Failure, exiting\n"));
58 exit(1);
59 break;
60
61 default:
62 break;
63 }
64 fflush(stdout);
65 }
66
67
68 void
pg_log(eLogType type,const char * fmt,...)69 pg_log(eLogType type, const char *fmt,...)
70 {
71 va_list args;
72
73 va_start(args, fmt);
74 pg_log_v(type, fmt, args);
75 va_end(args);
76 }
77
78
79 /*
80 * Print an error message, and exit.
81 */
82 void
pg_fatal(const char * fmt,...)83 pg_fatal(const char *fmt,...)
84 {
85 va_list args;
86
87 va_start(args, fmt);
88 pg_log_v(PG_FATAL, fmt, args);
89 va_end(args);
90 /* should not get here, pg_log_v() exited already */
91 exit(1);
92 }
93
94
95 /*
96 * Print a progress report based on the global variables.
97 *
98 * Progress report is written at maximum once per second, unless the
99 * force parameter is set to true.
100 */
101 void
progress_report(bool force)102 progress_report(bool force)
103 {
104 int percent;
105 char fetch_done_str[32];
106 char fetch_size_str[32];
107 pg_time_t now;
108
109 if (!showprogress)
110 return;
111
112 now = time(NULL);
113 if (now == last_progress_report && !force)
114 return; /* Max once per second */
115
116 last_progress_report = now;
117 percent = fetch_size ? (int) ((fetch_done) * 100 / fetch_size) : 0;
118
119 /*
120 * Avoid overflowing past 100% or the full size. This may make the total
121 * size number change as we approach the end of the backup (the estimate
122 * will always be wrong if WAL is included), but that's better than having
123 * the done column be bigger than the total.
124 */
125 if (percent > 100)
126 percent = 100;
127 if (fetch_done > fetch_size)
128 fetch_size = fetch_done;
129
130 /*
131 * Separate step to keep platform-dependent format code out of
132 * translatable strings. And we only test for INT64_FORMAT availability
133 * in snprintf, not fprintf.
134 */
135 snprintf(fetch_done_str, sizeof(fetch_done_str), INT64_FORMAT,
136 fetch_done / 1024);
137 snprintf(fetch_size_str, sizeof(fetch_size_str), INT64_FORMAT,
138 fetch_size / 1024);
139
140 pg_log(PG_PROGRESS, "%*s/%s kB (%d%%) copied",
141 (int) strlen(fetch_size_str), fetch_done_str, fetch_size_str,
142 percent);
143 printf("\r");
144 }
145