00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include <unistd.h>
00018
00019 #include "catalog/catalog.h"
00020 #include "common/relpath.h"
00021 #include "storage/copydir.h"
00022 #include "storage/fd.h"
00023 #include "storage/reinit.h"
00024 #include "utils/hsearch.h"
00025 #include "utils/memutils.h"
00026
00027 static void ResetUnloggedRelationsInTablespaceDir(const char *tsdirname,
00028 int op);
00029 static void ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname,
00030 int op);
00031 static bool parse_filename_for_nontemp_relation(const char *name,
00032 int *oidchars, ForkNumber *fork);
00033
00034 typedef struct
00035 {
00036 char oid[OIDCHARS + 1];
00037 } unlogged_relation_entry;
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 void
00049 ResetUnloggedRelations(int op)
00050 {
00051 char temp_path[MAXPGPATH];
00052 DIR *spc_dir;
00053 struct dirent *spc_de;
00054 MemoryContext tmpctx,
00055 oldctx;
00056
00057
00058 elog(DEBUG1, "resetting unlogged relations: cleanup %d init %d",
00059 (op & UNLOGGED_RELATION_CLEANUP) != 0,
00060 (op & UNLOGGED_RELATION_INIT) != 0);
00061
00062
00063
00064
00065
00066 tmpctx = AllocSetContextCreate(CurrentMemoryContext,
00067 "ResetUnloggedRelations",
00068 ALLOCSET_DEFAULT_MINSIZE,
00069 ALLOCSET_DEFAULT_INITSIZE,
00070 ALLOCSET_DEFAULT_MAXSIZE);
00071 oldctx = MemoryContextSwitchTo(tmpctx);
00072
00073
00074
00075
00076 ResetUnloggedRelationsInTablespaceDir("base", op);
00077
00078
00079
00080
00081 spc_dir = AllocateDir("pg_tblspc");
00082
00083 while ((spc_de = ReadDir(spc_dir, "pg_tblspc")) != NULL)
00084 {
00085 if (strcmp(spc_de->d_name, ".") == 0 ||
00086 strcmp(spc_de->d_name, "..") == 0)
00087 continue;
00088
00089 snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s",
00090 spc_de->d_name, TABLESPACE_VERSION_DIRECTORY);
00091 ResetUnloggedRelationsInTablespaceDir(temp_path, op);
00092 }
00093
00094 FreeDir(spc_dir);
00095
00096
00097
00098
00099 MemoryContextSwitchTo(oldctx);
00100 MemoryContextDelete(tmpctx);
00101 }
00102
00103
00104 static void
00105 ResetUnloggedRelationsInTablespaceDir(const char *tsdirname, int op)
00106 {
00107 DIR *ts_dir;
00108 struct dirent *de;
00109 char dbspace_path[MAXPGPATH];
00110
00111 ts_dir = AllocateDir(tsdirname);
00112 if (ts_dir == NULL)
00113 {
00114
00115 if (errno != ENOENT)
00116 elog(LOG,
00117 "could not open tablespace directory \"%s\": %m",
00118 tsdirname);
00119 return;
00120 }
00121
00122 while ((de = ReadDir(ts_dir, tsdirname)) != NULL)
00123 {
00124 int i = 0;
00125
00126
00127
00128
00129
00130
00131 while (isdigit((unsigned char) de->d_name[i]))
00132 ++i;
00133 if (de->d_name[i] != '\0' || i == 0)
00134 continue;
00135
00136 snprintf(dbspace_path, sizeof(dbspace_path), "%s/%s",
00137 tsdirname, de->d_name);
00138 ResetUnloggedRelationsInDbspaceDir(dbspace_path, op);
00139 }
00140
00141 FreeDir(ts_dir);
00142 }
00143
00144
00145 static void
00146 ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
00147 {
00148 DIR *dbspace_dir;
00149 struct dirent *de;
00150 char rm_path[MAXPGPATH];
00151
00152
00153 Assert((op & (UNLOGGED_RELATION_CLEANUP | UNLOGGED_RELATION_INIT)) != 0);
00154
00155
00156
00157
00158
00159
00160 if ((op & UNLOGGED_RELATION_CLEANUP) != 0)
00161 {
00162 HTAB *hash = NULL;
00163 HASHCTL ctl;
00164
00165
00166 dbspace_dir = AllocateDir(dbspacedirname);
00167 if (dbspace_dir == NULL)
00168 {
00169 elog(LOG,
00170 "could not open dbspace directory \"%s\": %m",
00171 dbspacedirname);
00172 return;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182 ctl.keysize = sizeof(unlogged_relation_entry);
00183 ctl.entrysize = sizeof(unlogged_relation_entry);
00184 hash = hash_create("unlogged hash", 32, &ctl, HASH_ELEM);
00185
00186
00187 while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
00188 {
00189 ForkNumber forkNum;
00190 int oidchars;
00191 unlogged_relation_entry ent;
00192
00193
00194 if (!parse_filename_for_nontemp_relation(de->d_name, &oidchars,
00195 &forkNum))
00196 continue;
00197
00198
00199 if (forkNum != INIT_FORKNUM)
00200 continue;
00201
00202
00203
00204
00205
00206 memset(ent.oid, 0, sizeof(ent.oid));
00207 memcpy(ent.oid, de->d_name, oidchars);
00208 hash_search(hash, &ent, HASH_ENTER, NULL);
00209 }
00210
00211
00212 FreeDir(dbspace_dir);
00213
00214
00215
00216
00217
00218 if (hash_get_num_entries(hash) == 0)
00219 {
00220 hash_destroy(hash);
00221 return;
00222 }
00223
00224
00225
00226
00227
00228 dbspace_dir = AllocateDir(dbspacedirname);
00229 if (dbspace_dir == NULL)
00230 {
00231 elog(LOG,
00232 "could not open dbspace directory \"%s\": %m",
00233 dbspacedirname);
00234 hash_destroy(hash);
00235 return;
00236 }
00237
00238
00239 while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
00240 {
00241 ForkNumber forkNum;
00242 int oidchars;
00243 bool found;
00244 unlogged_relation_entry ent;
00245
00246
00247 if (!parse_filename_for_nontemp_relation(de->d_name, &oidchars,
00248 &forkNum))
00249 continue;
00250
00251
00252 if (forkNum == INIT_FORKNUM)
00253 continue;
00254
00255
00256
00257
00258
00259 memset(ent.oid, 0, sizeof(ent.oid));
00260 memcpy(ent.oid, de->d_name, oidchars);
00261 hash_search(hash, &ent, HASH_FIND, &found);
00262
00263
00264 if (found)
00265 {
00266 snprintf(rm_path, sizeof(rm_path), "%s/%s",
00267 dbspacedirname, de->d_name);
00268
00269
00270
00271
00272
00273
00274
00275 if (unlink(rm_path))
00276 elog(LOG, "could not unlink file \"%s\": %m", rm_path);
00277 else
00278 elog(DEBUG2, "unlinked file \"%s\"", rm_path);
00279 }
00280 }
00281
00282
00283 FreeDir(dbspace_dir);
00284 hash_destroy(hash);
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294 if ((op & UNLOGGED_RELATION_INIT) != 0)
00295 {
00296
00297 dbspace_dir = AllocateDir(dbspacedirname);
00298 if (dbspace_dir == NULL)
00299 {
00300
00301 elog(LOG,
00302 "could not open dbspace directory \"%s\": %m",
00303 dbspacedirname);
00304 return;
00305 }
00306
00307
00308 while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
00309 {
00310 ForkNumber forkNum;
00311 int oidchars;
00312 char oidbuf[OIDCHARS + 1];
00313 char srcpath[MAXPGPATH];
00314 char dstpath[MAXPGPATH];
00315
00316
00317 if (!parse_filename_for_nontemp_relation(de->d_name, &oidchars,
00318 &forkNum))
00319 continue;
00320
00321
00322 if (forkNum != INIT_FORKNUM)
00323 continue;
00324
00325
00326 snprintf(srcpath, sizeof(srcpath), "%s/%s",
00327 dbspacedirname, de->d_name);
00328
00329
00330 memcpy(oidbuf, de->d_name, oidchars);
00331 oidbuf[oidchars] = '\0';
00332 snprintf(dstpath, sizeof(dstpath), "%s/%s%s",
00333 dbspacedirname, oidbuf, de->d_name + oidchars + 1 +
00334 strlen(forkNames[INIT_FORKNUM]));
00335
00336
00337 elog(DEBUG2, "copying %s to %s", srcpath, dstpath);
00338 copy_file(srcpath, dstpath);
00339 }
00340
00341 FreeDir(dbspace_dir);
00342 }
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 static bool
00358 parse_filename_for_nontemp_relation(const char *name, int *oidchars,
00359 ForkNumber *fork)
00360 {
00361 int pos;
00362
00363
00364 for (pos = 0; isdigit((unsigned char) name[pos]); ++pos)
00365 ;
00366 if (pos == 0 || pos > OIDCHARS)
00367 return false;
00368 *oidchars = pos;
00369
00370
00371 if (name[pos] != '_')
00372 *fork = MAIN_FORKNUM;
00373 else
00374 {
00375 int forkchar;
00376
00377 forkchar = forkname_chars(&name[pos + 1], fork);
00378 if (forkchar <= 0)
00379 return false;
00380 pos += forkchar + 1;
00381 }
00382
00383
00384 if (name[pos] == '.')
00385 {
00386 int segchar;
00387
00388 for (segchar = 1; isdigit((unsigned char) name[pos + segchar]); ++segchar)
00389 ;
00390 if (segchar <= 1)
00391 return false;
00392 pos += segchar;
00393 }
00394
00395
00396 if (name[pos] != '\0')
00397 return false;
00398 return true;
00399 }