~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/misc.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * misc.c
 
4
 *
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.40 2004-12-31 22:01:22 pgsql Exp $
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
#include "postgres.h"
 
16
 
 
17
#include <sys/file.h>
 
18
#include <signal.h>
 
19
#include <dirent.h>
 
20
 
 
21
#include "commands/dbcommands.h"
 
22
#include "miscadmin.h"
 
23
#include "storage/sinval.h"
 
24
#include "storage/fd.h"
 
25
#include "utils/builtins.h"
 
26
#include "funcapi.h"
 
27
#include "catalog/pg_type.h"
 
28
#include "catalog/pg_tablespace.h"
 
29
 
 
30
#define atooid(x)  ((Oid) strtoul((x), NULL, 10))
 
31
 
 
32
 
 
33
/*
 
34
 * Check if data is Null
 
35
 */
 
36
Datum
 
37
nullvalue(PG_FUNCTION_ARGS)
 
38
{
 
39
        if (PG_ARGISNULL(0))
 
40
                PG_RETURN_BOOL(true);
 
41
        PG_RETURN_BOOL(false);
 
42
}
 
43
 
 
44
/*
 
45
 * Check if data is not Null
 
46
 */
 
47
Datum
 
48
nonnullvalue(PG_FUNCTION_ARGS)
 
49
{
 
50
        if (PG_ARGISNULL(0))
 
51
                PG_RETURN_BOOL(false);
 
52
        PG_RETURN_BOOL(true);
 
53
}
 
54
 
 
55
/*
 
56
 * current_database()
 
57
 *      Expose the current database to the user
 
58
 */
 
59
Datum
 
60
current_database(PG_FUNCTION_ARGS)
 
61
{
 
62
        Name            db;
 
63
 
 
64
        db = (Name) palloc(NAMEDATALEN);
 
65
 
 
66
        namestrcpy(db, get_database_name(MyDatabaseId));
 
67
        PG_RETURN_NAME(db);
 
68
}
 
69
 
 
70
 
 
71
/*
 
72
 * Functions to send signals to other backends.
 
73
 */
 
74
 
 
75
static int
 
76
pg_signal_backend(int pid, int sig)
 
77
{
 
78
        if (!superuser())
 
79
                ereport(ERROR,
 
80
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 
81
                (errmsg("must be superuser to signal other server processes"))));
 
82
 
 
83
        if (!IsBackendPid(pid))
 
84
        {
 
85
                /*
 
86
                 * This is just a warning so a loop-through-resultset will not
 
87
                 * abort if one backend terminated on it's own during the run
 
88
                 */
 
89
                ereport(WARNING,
 
90
                         (errmsg("PID %d is not a PostgreSQL server process", pid)));
 
91
                return 0;
 
92
        }
 
93
 
 
94
        if (kill(pid, sig))
 
95
        {
 
96
                /* Again, just a warning to allow loops */
 
97
                ereport(WARNING,
 
98
                                (errmsg("could not send signal to process %d: %m", pid)));
 
99
                return 0;
 
100
        }
 
101
        return 1;
 
102
}
 
103
 
 
104
Datum
 
105
pg_cancel_backend(PG_FUNCTION_ARGS)
 
106
{
 
107
        PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0), SIGINT));
 
108
}
 
109
 
 
110
#ifdef NOT_USED
 
111
 
 
112
/* Disabled in 8.0 due to reliability concerns; FIXME someday */
 
113
 
 
114
Datum
 
115
pg_terminate_backend(PG_FUNCTION_ARGS)
 
116
{
 
117
        PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0), SIGTERM));
 
118
}
 
119
#endif
 
120
 
 
121
 
 
122
/* Function to find out which databases make use of a tablespace */
 
123
 
 
124
typedef struct
 
125
{
 
126
        char       *location;
 
127
        DIR                *dirdesc;
 
128
} ts_db_fctx;
 
129
 
 
130
Datum
 
131
pg_tablespace_databases(PG_FUNCTION_ARGS)
 
132
{
 
133
        FuncCallContext *funcctx;
 
134
        struct dirent *de;
 
135
        ts_db_fctx *fctx;
 
136
 
 
137
        if (SRF_IS_FIRSTCALL())
 
138
        {
 
139
                MemoryContext oldcontext;
 
140
                Oid                     tablespaceOid = PG_GETARG_OID(0);
 
141
 
 
142
                funcctx = SRF_FIRSTCALL_INIT();
 
143
                oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
144
 
 
145
                fctx = palloc(sizeof(ts_db_fctx));
 
146
 
 
147
                /*
 
148
                 * size = path length + tablespace dirname length + 2 dir sep
 
149
                 * chars + oid + terminator
 
150
                 */
 
151
                fctx->location = (char *) palloc(strlen(DataDir) + 11 + 10 + 1);
 
152
                if (tablespaceOid == GLOBALTABLESPACE_OID)
 
153
                {
 
154
                        fctx->dirdesc = NULL;
 
155
                        ereport(WARNING,
 
156
                                        (errmsg("global tablespace never has databases")));
 
157
                }
 
158
                else
 
159
                {
 
160
                        if (tablespaceOid == DEFAULTTABLESPACE_OID)
 
161
                                sprintf(fctx->location, "%s/base", DataDir);
 
162
                        else
 
163
                                sprintf(fctx->location, "%s/pg_tblspc/%u", DataDir,
 
164
                                                tablespaceOid);
 
165
 
 
166
                        fctx->dirdesc = AllocateDir(fctx->location);
 
167
 
 
168
                        if (!fctx->dirdesc)
 
169
                        {
 
170
                                /* the only expected error is ENOENT */
 
171
                                if (errno != ENOENT)
 
172
                                        ereport(ERROR,
 
173
                                                        (errcode_for_file_access(),
 
174
                                                         errmsg("could not open directory \"%s\": %m",
 
175
                                                                        fctx->location)));
 
176
                                ereport(WARNING,
 
177
                                  (errmsg("%u is not a tablespace OID", tablespaceOid)));
 
178
                        }
 
179
                }
 
180
                funcctx->user_fctx = fctx;
 
181
                MemoryContextSwitchTo(oldcontext);
 
182
        }
 
183
 
 
184
        funcctx = SRF_PERCALL_SETUP();
 
185
        fctx = (ts_db_fctx *) funcctx->user_fctx;
 
186
 
 
187
        if (!fctx->dirdesc)                     /* not a tablespace */
 
188
                SRF_RETURN_DONE(funcctx);
 
189
 
 
190
        while ((de = readdir(fctx->dirdesc)) != NULL)
 
191
        {
 
192
                char       *subdir;
 
193
                DIR                *dirdesc;
 
194
 
 
195
                Oid                     datOid = atooid(de->d_name);
 
196
 
 
197
                /* this test skips . and .., but is awfully weak */
 
198
                if (!datOid)
 
199
                        continue;
 
200
 
 
201
                /* if database subdir is empty, don't report tablespace as used */
 
202
 
 
203
                /* size = path length + dir sep char + file name + terminator */
 
204
                subdir = palloc(strlen(fctx->location) + 1 + strlen(de->d_name) + 1);
 
205
                sprintf(subdir, "%s/%s", fctx->location, de->d_name);
 
206
                dirdesc = AllocateDir(subdir);
 
207
                pfree(subdir);
 
208
                if (!dirdesc)
 
209
                        continue;                       /* XXX more sloppiness */
 
210
 
 
211
                while ((de = readdir(dirdesc)) != 0)
 
212
                {
 
213
                        if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
 
214
                                break;
 
215
                }
 
216
                FreeDir(dirdesc);
 
217
 
 
218
                if (!de)
 
219
                        continue;                       /* indeed, nothing in it */
 
220
 
 
221
                SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(datOid));
 
222
        }
 
223
 
 
224
        FreeDir(fctx->dirdesc);
 
225
        SRF_RETURN_DONE(funcctx);
 
226
}