~ubuntu-branches/debian/sid/pgadmin3/sid

« back to all changes in this revision

Viewing changes to xtra/admin/misc.c

  • Committer: Bazaar Package Importer
  • Author(s): Gerfried Fuchs
  • Date: 2009-07-30 12:27:16 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090730122716-fddbh42on721bbs2
Tags: 1.10.0-1
* New upstream release.
* Adjusted watch file to match release candidates.
* Updated to Standards-Version 3.8.2:
  - Moved to Section: database.
  - Add DEB_BUILD_OPTIONS support for parallel building.
  - Move from findstring to filter suggestion for DEB_BUILD_OPTIONS parsing.
* pgagent got split into its own separate source package by upstream.
* Exclude Docs.vcproj from installation.
* Move doc-base.enus from pgadmin3 to pgadmin3-data package, the files are
  in there too.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * admin.c
3
 
 * miscellaneous administrative functions
4
 
 *
5
 
 * Copyright (c) 2002 - 2006, PostgreSQL Global Development Group
6
 
 *
7
 
 * Author: Andreas Pflug <pgadmin@pse-consulting.de>
8
 
 *
9
 
 * IDENTIFICATION
10
 
 *        $PostgreSQL: $
11
 
 *
12
 
 */
13
 
 
14
 
#include "postgres.h"
15
 
 
16
 
#include <sys/file.h>
17
 
#include <signal.h>
18
 
#include <dirent.h>
19
 
#include <time.h>
20
 
#include <sys/time.h>
21
 
 
22
 
#include "commands/dbcommands.h"
23
 
#include "miscadmin.h"
24
 
#include "storage/sinval.h"
25
 
#include "storage/fd.h"
26
 
#include "funcapi.h"
27
 
#include "catalog/pg_type.h"
28
 
#include "catalog/pg_tablespace.h"
29
 
#include "postmaster/syslogger.h"
30
 
 
31
 
extern DLLIMPORT char *DataDir;
32
 
extern DLLIMPORT char *Log_directory;
33
 
extern DLLIMPORT char *Log_filename;
34
 
extern DLLIMPORT pid_t PostmasterPid;
35
 
 
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);
40
 
 
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);
45
 
Datum
46
 
pg_reload_conf(PG_FUNCTION_ARGS)
47
 
{
48
 
        if (!superuser()) 
49
 
                ereport(ERROR,
50
 
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
51
 
                                 (errmsg("only superuser can signal the postmaster"))));
52
 
 
53
 
        if (kill(PostmasterPid, SIGHUP))
54
 
        {
55
 
                ereport(WARNING,
56
 
                                (errmsg("failed to send signal to postmaster: %m")));
57
 
 
58
 
                PG_RETURN_INT32(0);
59
 
        }
60
 
 
61
 
        PG_RETURN_INT32(1);
62
 
}
63
 
 
64
 
 
65
 
typedef struct 
66
 
{
67
 
        char *location;
68
 
        DIR *dirdesc;
69
 
} directory_fctx;
70
 
 
71
 
 
72
 
/*
73
 
 * logfile handling functions
74
 
 */
75
 
 
76
 
#if ROTATE_SUPPORTED
77
 
/* not yet in backend */
78
 
Datum pg_logfile_rotate(PG_FUNCTION_ARGS)
79
 
{
80
 
        if (!superuser()) 
81
 
                ereport(ERROR,
82
 
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
83
 
                                 (errmsg("only superuser can issue a logfile rotation command"))));
84
 
 
85
 
    PG_RETURN_BOOL(LogFileRotate());
86
 
}
87
 
 
88
 
#endif
89
 
 
90
 
Datum pg_logdir_ls(PG_FUNCTION_ARGS)
91
 
{
92
 
        FuncCallContext *funcctx;
93
 
        struct dirent *de;
94
 
        directory_fctx *fctx;
95
 
 
96
 
        if (!superuser()) 
97
 
                ereport(ERROR,
98
 
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
99
 
                                 (errmsg("only superuser can list the log directory"))));
100
 
        
101
 
        if (memcmp(Log_filename, "postgresql-%Y-%m-%d_%H%M%S.log", 30) != 0)
102
 
                ereport(ERROR,
103
 
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
104
 
                                 (errmsg("the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'"))));
105
 
 
106
 
        if (SRF_IS_FIRSTCALL())
107
 
        {
108
 
                MemoryContext oldcontext;
109
 
                TupleDesc tupdesc;
110
 
 
111
 
                funcctx=SRF_FIRSTCALL_INIT();
112
 
                oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
113
 
 
114
 
                fctx = palloc(sizeof(directory_fctx));
115
 
                if (is_absolute_path(Log_directory))
116
 
                    fctx->location = Log_directory;
117
 
                else
118
 
                {
119
 
                        fctx->location = palloc(strlen(DataDir) + strlen(Log_directory) +2);
120
 
                        sprintf(fctx->location, "%s/%s", DataDir, Log_directory);
121
 
                }
122
 
                tupdesc = CreateTemplateTupleDesc(2, false);
123
 
                TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime",
124
 
                                                   TIMESTAMPOID, -1, 0);
125
 
                TupleDescInitEntry(tupdesc, (AttrNumber) 2, "filename",
126
 
                                                   TEXTOID, -1, 0);
127
 
 
128
 
                funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
129
 
                
130
 
                fctx->dirdesc = AllocateDir(fctx->location);
131
 
 
132
 
                if (!fctx->dirdesc)
133
 
                    ereport(ERROR,
134
 
                                        (errcode_for_file_access(),
135
 
                                         errmsg("%s is not browsable: %m", fctx->location)));
136
 
 
137
 
                funcctx->user_fctx = fctx;
138
 
                MemoryContextSwitchTo(oldcontext);
139
 
        }
140
 
 
141
 
        funcctx=SRF_PERCALL_SETUP();
142
 
        fctx = (directory_fctx*) funcctx->user_fctx;
143
 
 
144
 
        if (!fctx->dirdesc)  /* not a readable directory  */
145
 
                SRF_RETURN_DONE(funcctx);
146
 
 
147
 
        while ((de = readdir(fctx->dirdesc)) != NULL)
148
 
        {
149
 
                char *values[2];
150
 
                HeapTuple tuple;
151
 
            
152
 
                char            *field[MAXDATEFIELDS];
153
 
                char            lowstr[MAXDATELEN + 1];
154
 
                int             dtype;
155
 
                int             nf, ftype[MAXDATEFIELDS];
156
 
                fsec_t          fsec;
157
 
                int             tz = 0;
158
 
                struct          pg_tm date;
159
 
 
160
 
                /*
161
 
                 * Default format:
162
 
                 *        postgresql-YYYY-MM-DD_HHMMSS.log
163
 
                 */
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"))
168
 
                      continue;
169
 
 
170
 
                values[1] = palloc(strlen(fctx->location) + strlen(de->d_name) + 2);
171
 
                sprintf(values[1], "%s/%s", fctx->location, de->d_name);
172
 
 
173
 
                values[0] = de->d_name + 11;       /* timestamp */
174
 
                values[0][17] = 0;
175
 
 
176
 
                /* parse and decode expected timestamp */
177
 
 
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
182
 
                 * version below.
183
 
                 *
184
 
                 * if (ParseDateTime(values[0], lowstr, field, ftype, MAXDATEFIELDS, &nf))
185
 
                 *
186
 
                 */
187
 
 
188
 
                if (ParseDateTime(values[0], lowstr, sizeof(lowstr), field, ftype, MAXDATEFIELDS, &nf))
189
 
                    continue;
190
 
 
191
 
                if (DecodeDateTime(field, ftype, nf, &dtype, &date, &fsec, &tz))
192
 
                    continue;
193
 
 
194
 
                /* Seems the format fits the expected format; feed it into the tuple */
195
 
 
196
 
                tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
197
 
 
198
 
                SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
199
 
        }
200
 
 
201
 
        FreeDir(fctx->dirdesc);
202
 
        SRF_RETURN_DONE(funcctx);
203
 
}
204
 
 
205
 
 
206
 
Datum pg_postmaster_starttime(PG_FUNCTION_ARGS)
207
 
{
208
 
    Timestamp result;
209
 
    
210
 
    if (!superuser()) 
211
 
            ereport(ERROR,
212
 
                            (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
213
 
                             (errmsg("only superuser can query the postmaster starttime"))));
214
 
 
215
 
#ifdef WIN32
216
 
    {
217
 
            struct pg_tm tm;
218
 
        extern DLLIMPORT HANDLE PostmasterHandle;
219
 
        FILETIME creationTime;
220
 
        FILETIME exitTime, kernelTime, userTime;
221
 
        SYSTEMTIME st;
222
 
    
223
 
        bool rc=GetProcessTimes(PostmasterHandle, &creationTime,
224
 
            &exitTime, &kernelTime, &userTime);
225
 
        if (!rc)
226
 
            PG_RETURN_NULL();
227
 
    
228
 
        FileTimeToSystemTime(&creationTime, &st);
229
 
    
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;
236
 
 
237
 
                if (tm2timestamp(&tm, 0, NULL, &result) != 0)
238
 
                {
239
 
                        ereport(ERROR,
240
 
            (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
241
 
            errmsg("postmaster timestamp out of range")));
242
 
                }
243
 
    }
244
 
#else
245
 
        {
246
 
                FILE *fp;
247
 
                char buffer[MAXPGPATH];
248
 
            pg_time_t now = time(NULL);
249
 
                struct pg_tm *tm = pg_localtime(&now);
250
 
                double systemSeconds;
251
 
                long procJiffies;
252
 
                int i;
253
 
 
254
 
                tm->tm_year += 1900;
255
 
                tm->tm_mon += 1;
256
 
 
257
 
                if (tm2timestamp(tm, 0, NULL, &result) != 0)
258
 
                {
259
 
                        ereport(ERROR,
260
 
            (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
261
 
            errmsg("postmaster timestamp out of range")));
262
 
                }
263
 
 
264
 
                fp = fopen("/proc/uptime", "r");
265
 
                if (!fp)
266
 
                    ereport(ERROR,
267
 
                                        (errcode_for_file_access(), 
268
 
                                         errmsg("could not open /proc/uptime: %m")));
269
 
 
270
 
                if (fscanf(fp, "%lf", &systemSeconds) != 1)
271
 
                    ereport(ERROR,
272
 
                                        (errcode_for_file_access(), 
273
 
                                         errmsg("could not interpret /proc/uptime: %m")));
274
 
 
275
 
                fclose(fp);
276
 
 
277
 
                sprintf(buffer, "/proc/%u/stat", PostmasterPid);
278
 
                fp = fopen(buffer, "r");
279
 
                if (!fp)
280
 
                    ereport(ERROR,
281
 
                                        (errcode_for_file_access(), 
282
 
                                         errmsg("could not open %s: %m", buffer)));
283
 
 
284
 
 
285
 
#define PROC_STAT_POS 22
286
 
 
287
 
                for (i=1 ; i < PROC_STAT_POS ; i++)
288
 
                {
289
 
                    char c;
290
 
                        do
291
 
                        {
292
 
                                c = fgetc(fp);
293
 
                        }
294
 
                        while (c && c != ' ');
295
 
                }
296
 
 
297
 
                if (fscanf(fp, "%ld", &procJiffies) != 1)
298
 
                    ereport(ERROR,
299
 
                                        (errcode_for_file_access(), 
300
 
                                         errmsg("could not interpret %s: %m", buffer)));
301
 
 
302
 
                fclose(fp);
303
 
 
304
 
#ifdef HAVE_INT64_TIMESTAMP
305
 
                result += (procJiffies/100. - systemSeconds) / INT64CONST(1000000);
306
 
#else
307
 
                result += (procJiffies/100. - systemSeconds);
308
 
#endif
309
 
        }
310
 
#endif
311
 
 
312
 
 
313
 
    PG_RETURN_TIMESTAMP(result);
314
 
}