PostgreSQL Source Code  git master
dbcommands_xlog.h File Reference
#include "access/xlogreader.h"
#include "lib/stringinfo.h"
Include dependency graph for dbcommands_xlog.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  xl_dbase_create_file_copy_rec
 
struct  xl_dbase_create_wal_log_rec
 
struct  xl_dbase_drop_rec
 

Macros

#define XLOG_DBASE_CREATE_FILE_COPY   0x00
 
#define XLOG_DBASE_CREATE_WAL_LOG   0x10
 
#define XLOG_DBASE_DROP   0x20
 
#define MinSizeOfDbaseDropRec   offsetof(xl_dbase_drop_rec, tablespace_ids)
 

Typedefs

typedef struct xl_dbase_create_file_copy_rec xl_dbase_create_file_copy_rec
 
typedef struct xl_dbase_create_wal_log_rec xl_dbase_create_wal_log_rec
 
typedef struct xl_dbase_drop_rec xl_dbase_drop_rec
 

Functions

void dbase_redo (XLogReaderState *record)
 
void dbase_desc (StringInfo buf, XLogReaderState *record)
 
const char * dbase_identify (uint8 info)
 

Macro Definition Documentation

◆ MinSizeOfDbaseDropRec

#define MinSizeOfDbaseDropRec   offsetof(xl_dbase_drop_rec, tablespace_ids)

Definition at line 54 of file dbcommands_xlog.h.

◆ XLOG_DBASE_CREATE_FILE_COPY

#define XLOG_DBASE_CREATE_FILE_COPY   0x00

Definition at line 21 of file dbcommands_xlog.h.

◆ XLOG_DBASE_CREATE_WAL_LOG

#define XLOG_DBASE_CREATE_WAL_LOG   0x10

Definition at line 22 of file dbcommands_xlog.h.

◆ XLOG_DBASE_DROP

#define XLOG_DBASE_DROP   0x20

Definition at line 23 of file dbcommands_xlog.h.

Typedef Documentation

◆ xl_dbase_create_file_copy_rec

◆ xl_dbase_create_wal_log_rec

◆ xl_dbase_drop_rec

Function Documentation

◆ dbase_desc()

void dbase_desc ( StringInfo  buf,
XLogReaderState record 
)

Definition at line 22 of file dbasedesc.c.

23 {
24  char *rec = XLogRecGetData(record);
25  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
26 
27  if (info == XLOG_DBASE_CREATE_FILE_COPY)
28  {
31 
32  appendStringInfo(buf, "copy dir %u/%u to %u/%u",
33  xlrec->src_tablespace_id, xlrec->src_db_id,
34  xlrec->tablespace_id, xlrec->db_id);
35  }
36  else if (info == XLOG_DBASE_CREATE_WAL_LOG)
37  {
40 
41  appendStringInfo(buf, "create dir %u/%u",
42  xlrec->tablespace_id, xlrec->db_id);
43  }
44  else if (info == XLOG_DBASE_DROP)
45  {
46  xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) rec;
47  int i;
48 
50  for (i = 0; i < xlrec->ntablespaces; i++)
51  appendStringInfo(buf, " %u/%u",
52  xlrec->tablespace_ids[i], xlrec->db_id);
53  }
54 }
unsigned char uint8
Definition: c.h:440
#define XLOG_DBASE_CREATE_WAL_LOG
#define XLOG_DBASE_DROP
#define XLOG_DBASE_CREATE_FILE_COPY
int i
Definition: isn.c:73
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
Oid tablespace_ids[FLEXIBLE_ARRAY_MEMBER]
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:411
#define XLogRecGetData(decoder)
Definition: xlogreader.h:416
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References appendStringInfo(), appendStringInfoString(), buf, xl_dbase_create_file_copy_rec::db_id, xl_dbase_create_wal_log_rec::db_id, xl_dbase_drop_rec::db_id, i, xl_dbase_drop_rec::ntablespaces, xl_dbase_create_file_copy_rec::src_db_id, xl_dbase_create_file_copy_rec::src_tablespace_id, xl_dbase_create_file_copy_rec::tablespace_id, xl_dbase_create_wal_log_rec::tablespace_id, xl_dbase_drop_rec::tablespace_ids, XLOG_DBASE_CREATE_FILE_COPY, XLOG_DBASE_CREATE_WAL_LOG, XLOG_DBASE_DROP, XLogRecGetData, XLogRecGetInfo, and XLR_INFO_MASK.

◆ dbase_identify()

const char* dbase_identify ( uint8  info)

Definition at line 57 of file dbasedesc.c.

58 {
59  const char *id = NULL;
60 
61  switch (info & ~XLR_INFO_MASK)
62  {
64  id = "CREATE_FILE_COPY";
65  break;
67  id = "CREATE_WAL_LOG";
68  break;
69  case XLOG_DBASE_DROP:
70  id = "DROP";
71  break;
72  }
73 
74  return id;
75 }

References XLOG_DBASE_CREATE_FILE_COPY, XLOG_DBASE_CREATE_WAL_LOG, XLOG_DBASE_DROP, and XLR_INFO_MASK.

◆ dbase_redo()

void dbase_redo ( XLogReaderState record)

Definition at line 3041 of file dbcommands.c.

3042 {
3043  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
3044 
3045  /* Backup blocks are not used in dbase records */
3046  Assert(!XLogRecHasAnyBlockRefs(record));
3047 
3048  if (info == XLOG_DBASE_CREATE_FILE_COPY)
3049  {
3052  char *src_path;
3053  char *dst_path;
3054  char *parent_path;
3055  struct stat st;
3056 
3057  src_path = GetDatabasePath(xlrec->src_db_id, xlrec->src_tablespace_id);
3058  dst_path = GetDatabasePath(xlrec->db_id, xlrec->tablespace_id);
3059 
3060  /*
3061  * Our theory for replaying a CREATE is to forcibly drop the target
3062  * subdirectory if present, then re-copy the source data. This may be
3063  * more work than needed, but it is simple to implement.
3064  */
3065  if (stat(dst_path, &st) == 0 && S_ISDIR(st.st_mode))
3066  {
3067  if (!rmtree(dst_path, true))
3068  /* If this failed, copydir() below is going to error. */
3069  ereport(WARNING,
3070  (errmsg("some useless files may be left behind in old database directory \"%s\"",
3071  dst_path)));
3072  }
3073 
3074  /*
3075  * If the parent of the target path doesn't exist, create it now. This
3076  * enables us to create the target underneath later.
3077  */
3078  parent_path = pstrdup(dst_path);
3079  get_parent_directory(parent_path);
3080  if (stat(parent_path, &st) < 0)
3081  {
3082  if (errno != ENOENT)
3083  ereport(FATAL,
3084  errmsg("could not stat directory \"%s\": %m",
3085  dst_path));
3086 
3087  /* create the parent directory if needed and valid */
3088  recovery_create_dbdir(parent_path, true);
3089  }
3090  pfree(parent_path);
3091 
3092  /*
3093  * There's a case where the copy source directory is missing for the
3094  * same reason above. Create the emtpy source directory so that
3095  * copydir below doesn't fail. The directory will be dropped soon by
3096  * recovery.
3097  */
3098  if (stat(src_path, &st) < 0 && errno == ENOENT)
3099  recovery_create_dbdir(src_path, false);
3100 
3101  /*
3102  * Force dirty buffers out to disk, to ensure source database is
3103  * up-to-date for the copy.
3104  */
3106 
3107  /* Close all sgmr fds in all backends. */
3109 
3110  /*
3111  * Copy this subdirectory to the new location
3112  *
3113  * We don't need to copy subdirectories
3114  */
3115  copydir(src_path, dst_path, false);
3116 
3117  pfree(src_path);
3118  pfree(dst_path);
3119  }
3120  else if (info == XLOG_DBASE_CREATE_WAL_LOG)
3121  {
3124  char *dbpath;
3125  char *parent_path;
3126 
3127  dbpath = GetDatabasePath(xlrec->db_id, xlrec->tablespace_id);
3128 
3129  /* create the parent directory if needed and valid */
3130  parent_path = pstrdup(dbpath);
3131  get_parent_directory(parent_path);
3132  recovery_create_dbdir(parent_path, true);
3133 
3134  /* Create the database directory with the version file. */
3135  CreateDirAndVersionFile(dbpath, xlrec->db_id, xlrec->tablespace_id,
3136  true);
3137  pfree(dbpath);
3138  }
3139  else if (info == XLOG_DBASE_DROP)
3140  {
3141  xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) XLogRecGetData(record);
3142  char *dst_path;
3143  int i;
3144 
3145  if (InHotStandby)
3146  {
3147  /*
3148  * Lock database while we resolve conflicts to ensure that
3149  * InitPostgres() cannot fully re-execute concurrently. This
3150  * avoids backends re-connecting automatically to same database,
3151  * which can happen in some cases.
3152  *
3153  * This will lock out walsenders trying to connect to db-specific
3154  * slots for logical decoding too, so it's safe for us to drop
3155  * slots.
3156  */
3157  LockSharedObjectForSession(DatabaseRelationId, xlrec->db_id, 0, AccessExclusiveLock);
3159  }
3160 
3161  /* Drop any database-specific replication slots */
3163 
3164  /* Drop pages for this database that are in the shared buffer cache */
3165  DropDatabaseBuffers(xlrec->db_id);
3166 
3167  /* Also, clean out any fsync requests that might be pending in md.c */
3169 
3170  /* Clean out the xlog relcache too */
3171  XLogDropDatabase(xlrec->db_id);
3172 
3173  /* Close all sgmr fds in all backends. */
3175 
3176  for (i = 0; i < xlrec->ntablespaces; i++)
3177  {
3178  dst_path = GetDatabasePath(xlrec->db_id, xlrec->tablespace_ids[i]);
3179 
3180  /* And remove the physical files */
3181  if (!rmtree(dst_path, true))
3182  ereport(WARNING,
3183  (errmsg("some useless files may be left behind in old database directory \"%s\"",
3184  dst_path)));
3185  pfree(dst_path);
3186  }
3187 
3188  if (InHotStandby)
3189  {
3190  /*
3191  * Release locks prior to commit. XXX There is a race condition
3192  * here that may allow backends to reconnect, but the window for
3193  * this is small because the gap between here and commit is mostly
3194  * fairly small and it is unlikely that people will be dropping
3195  * databases that we are trying to connect to anyway.
3196  */
3197  UnlockSharedObjectForSession(DatabaseRelationId, xlrec->db_id, 0, AccessExclusiveLock);
3198  }
3199  }
3200  else
3201  elog(PANIC, "dbase_redo: unknown op code %u", info);
3202 }
void DropDatabaseBuffers(Oid dbid)
Definition: bufmgr.c:3413
void FlushDatabaseBuffers(Oid dbid)
Definition: bufmgr.c:3868
void copydir(char *fromdir, char *todir, bool recurse)
Definition: copydir.c:38
static void CreateDirAndVersionFile(char *dbpath, Oid dbid, Oid tsid, bool isRedo)
Definition: dbcommands.c:457
static void recovery_create_dbdir(char *path, bool only_tblspc)
Definition: dbcommands.c:3012
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define FATAL
Definition: elog.h:37
#define WARNING
Definition: elog.h:32
#define PANIC
Definition: elog.h:38
#define ereport(elevel,...)
Definition: elog.h:145
Assert(fmt[strlen(fmt) - 1] !='\n')
void UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1106
void LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1088
#define AccessExclusiveLock
Definition: lockdefs.h:43
char * pstrdup(const char *in)
Definition: mcxt.c:1392
void pfree(void *pointer)
Definition: mcxt.c:1252
void ForgetDatabaseSyncRequests(Oid dbid)
Definition: md.c:1056
void get_parent_directory(char *path)
Definition: path.c:977
void WaitForProcSignalBarrier(uint64 generation)
Definition: procsignal.c:392
uint64 EmitProcSignalBarrier(ProcSignalBarrierType type)
Definition: procsignal.c:332
@ PROCSIGNAL_BARRIER_SMGRRELEASE
Definition: procsignal.h:52
char * GetDatabasePath(Oid dbOid, Oid spcOid)
Definition: relpath.c:110
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:42
void ReplicationSlotsDropDBSlots(Oid dboid)
Definition: slot.c:1008
void ResolveRecoveryConflictWithDatabase(Oid dbid)
Definition: standby.c:531
#define stat
Definition: win32_port.h:286
#define S_ISDIR(m)
Definition: win32_port.h:327
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:418
void XLogDropDatabase(Oid dbid)
Definition: xlogutils.c:669
#define InHotStandby
Definition: xlogutils.h:57

References AccessExclusiveLock, Assert(), copydir(), CreateDirAndVersionFile(), xl_dbase_create_file_copy_rec::db_id, xl_dbase_create_wal_log_rec::db_id, xl_dbase_drop_rec::db_id, DropDatabaseBuffers(), elog(), EmitProcSignalBarrier(), ereport, errmsg(), FATAL, FlushDatabaseBuffers(), ForgetDatabaseSyncRequests(), get_parent_directory(), GetDatabasePath(), i, InHotStandby, LockSharedObjectForSession(), xl_dbase_drop_rec::ntablespaces, PANIC, pfree(), PROCSIGNAL_BARRIER_SMGRRELEASE, pstrdup(), recovery_create_dbdir(), ReplicationSlotsDropDBSlots(), ResolveRecoveryConflictWithDatabase(), rmtree(), S_ISDIR, xl_dbase_create_file_copy_rec::src_db_id, xl_dbase_create_file_copy_rec::src_tablespace_id, stat::st_mode, stat, xl_dbase_create_file_copy_rec::tablespace_id, xl_dbase_create_wal_log_rec::tablespace_id, xl_dbase_drop_rec::tablespace_ids, UnlockSharedObjectForSession(), WaitForProcSignalBarrier(), WARNING, XLOG_DBASE_CREATE_FILE_COPY, XLOG_DBASE_CREATE_WAL_LOG, XLOG_DBASE_DROP, XLogDropDatabase(), XLogRecGetData, XLogRecGetInfo, XLogRecHasAnyBlockRefs, and XLR_INFO_MASK.