3
* miscellaneous administrative functions
5
* Copyright (c) 2002 - 2006, PostgreSQL Global Development Group
7
* Author: Andreas Pflug <pgadmin@pse-consulting.de>
22
#include "commands/dbcommands.h"
23
#include "miscadmin.h"
24
#include "storage/sinval.h"
25
#include "storage/fd.h"
27
#include "catalog/pg_type.h"
28
#include "catalog/pg_tablespace.h"
29
#include "postmaster/syslogger.h"
31
extern DLLIMPORT char *DataDir;
32
extern DLLIMPORT char *Log_directory;
33
extern DLLIMPORT char *Log_filename;
34
extern DLLIMPORT pid_t PostmasterPid;
36
Datum pg_reload_conf(PG_FUNCTION_ARGS);
37
Datum pg_logfile_rotate(PG_FUNCTION_ARGS);
38
Datum pg_logdir_ls(PG_FUNCTION_ARGS);
39
Datum pg_postmaster_starttime(PG_FUNCTION_ARGS);
41
PG_FUNCTION_INFO_V1(pg_reload_conf);
42
PG_FUNCTION_INFO_V1(pg_logfile_rotate);
43
PG_FUNCTION_INFO_V1(pg_logdir_ls);
44
PG_FUNCTION_INFO_V1(pg_postmaster_starttime);
46
pg_reload_conf(PG_FUNCTION_ARGS)
50
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
51
(errmsg("only superuser can signal the postmaster"))));
53
if (kill(PostmasterPid, SIGHUP))
56
(errmsg("failed to send signal to postmaster: %m")));
73
* logfile handling functions
77
/* not yet in backend */
78
Datum pg_logfile_rotate(PG_FUNCTION_ARGS)
82
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
83
(errmsg("only superuser can issue a logfile rotation command"))));
85
PG_RETURN_BOOL(LogFileRotate());
90
Datum pg_logdir_ls(PG_FUNCTION_ARGS)
92
FuncCallContext *funcctx;
98
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
99
(errmsg("only superuser can list the log directory"))));
101
if (memcmp(Log_filename, "postgresql-%Y-%m-%d_%H%M%S.log", 30) != 0)
103
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
104
(errmsg("the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'"))));
106
if (SRF_IS_FIRSTCALL())
108
MemoryContext oldcontext;
111
funcctx=SRF_FIRSTCALL_INIT();
112
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
114
fctx = palloc(sizeof(directory_fctx));
115
if (is_absolute_path(Log_directory))
116
fctx->location = Log_directory;
119
fctx->location = palloc(strlen(DataDir) + strlen(Log_directory) +2);
120
sprintf(fctx->location, "%s/%s", DataDir, Log_directory);
122
tupdesc = CreateTemplateTupleDesc(2, false);
123
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime",
124
TIMESTAMPOID, -1, 0);
125
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "filename",
128
funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
130
fctx->dirdesc = AllocateDir(fctx->location);
134
(errcode_for_file_access(),
135
errmsg("%s is not browsable: %m", fctx->location)));
137
funcctx->user_fctx = fctx;
138
MemoryContextSwitchTo(oldcontext);
141
funcctx=SRF_PERCALL_SETUP();
142
fctx = (directory_fctx*) funcctx->user_fctx;
144
if (!fctx->dirdesc) /* not a readable directory */
145
SRF_RETURN_DONE(funcctx);
147
while ((de = readdir(fctx->dirdesc)) != NULL)
152
char *field[MAXDATEFIELDS];
153
char lowstr[MAXDATELEN + 1];
155
int nf, ftype[MAXDATEFIELDS];
162
* postgresql-YYYY-MM-DD_HHMMSS.log
164
if (strlen(de->d_name) != 32
165
|| memcmp(de->d_name, "postgresql-", 11)
166
|| de->d_name[21] != '_'
167
|| strcmp(de->d_name + 28, ".log"))
170
values[1] = palloc(strlen(fctx->location) + strlen(de->d_name) + 2);
171
sprintf(values[1], "%s/%s", fctx->location, de->d_name);
173
values[0] = de->d_name + 11; /* timestamp */
176
/* parse and decode expected timestamp */
178
/* The ParseDateTime signature changed in PostgreSQL 8.0.4. Because
179
* there is no way to check the PG version at build time at present
180
* we'll have to keep a manual condition compile here :-(
181
* Use the following line for < 8.0.4, otherwise, use the uncommented
184
* if (ParseDateTime(values[0], lowstr, field, ftype, MAXDATEFIELDS, &nf))
188
if (ParseDateTime(values[0], lowstr, sizeof(lowstr), field, ftype, MAXDATEFIELDS, &nf))
191
if (DecodeDateTime(field, ftype, nf, &dtype, &date, &fsec, &tz))
194
/* Seems the format fits the expected format; feed it into the tuple */
196
tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
198
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
201
FreeDir(fctx->dirdesc);
202
SRF_RETURN_DONE(funcctx);
206
Datum pg_postmaster_starttime(PG_FUNCTION_ARGS)
212
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
213
(errmsg("only superuser can query the postmaster starttime"))));
218
extern DLLIMPORT HANDLE PostmasterHandle;
219
FILETIME creationTime;
220
FILETIME exitTime, kernelTime, userTime;
223
bool rc=GetProcessTimes(PostmasterHandle, &creationTime,
224
&exitTime, &kernelTime, &userTime);
228
FileTimeToSystemTime(&creationTime, &st);
230
tm.tm_year = st.wYear;
231
tm.tm_mon = st.wMonth;
232
tm.tm_mday = st.wDay;
233
tm.tm_hour = st.wHour;
234
tm.tm_min = st.wMinute;
235
tm.tm_sec = st.wSecond;
237
if (tm2timestamp(&tm, 0, NULL, &result) != 0)
240
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
241
errmsg("postmaster timestamp out of range")));
247
char buffer[MAXPGPATH];
248
pg_time_t now = time(NULL);
249
struct pg_tm *tm = pg_localtime(&now);
250
double systemSeconds;
257
if (tm2timestamp(tm, 0, NULL, &result) != 0)
260
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
261
errmsg("postmaster timestamp out of range")));
264
fp = fopen("/proc/uptime", "r");
267
(errcode_for_file_access(),
268
errmsg("could not open /proc/uptime: %m")));
270
if (fscanf(fp, "%lf", &systemSeconds) != 1)
272
(errcode_for_file_access(),
273
errmsg("could not interpret /proc/uptime: %m")));
277
sprintf(buffer, "/proc/%u/stat", PostmasterPid);
278
fp = fopen(buffer, "r");
281
(errcode_for_file_access(),
282
errmsg("could not open %s: %m", buffer)));
285
#define PROC_STAT_POS 22
287
for (i=1 ; i < PROC_STAT_POS ; i++)
294
while (c && c != ' ');
297
if (fscanf(fp, "%ld", &procJiffies) != 1)
299
(errcode_for_file_access(),
300
errmsg("could not interpret %s: %m", buffer)));
304
#ifdef HAVE_INT64_TIMESTAMP
305
result += (procJiffies/100. - systemSeconds) / INT64CONST(1000000);
307
result += (procJiffies/100. - systemSeconds);
313
PG_RETURN_TIMESTAMP(result);