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