|
9 | 9 | *
|
10 | 10 | *
|
11 | 11 | * IDENTIFICATION
|
12 |
| - * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.141 2004/08/29 05:06:41 momjian Exp $ |
| 12 | + * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.142 2004/08/29 21:08:47 tgl Exp $ |
13 | 13 | *
|
14 | 14 | *-------------------------------------------------------------------------
|
15 | 15 | */
|
@@ -385,6 +385,30 @@ createdb(const CreatedbStmt *stmt)
|
385 | 385 | (errmsg("could not initialize database directory")));
|
386 | 386 | }
|
387 | 387 | #endif /* WIN32 */
|
| 388 | + |
| 389 | + /* Record the filesystem change in XLOG */ |
| 390 | + { |
| 391 | + xl_dbase_create_rec xlrec; |
| 392 | + XLogRecData rdata[3]; |
| 393 | + |
| 394 | + xlrec.db_id = dboid; |
| 395 | + rdata[0].buffer = InvalidBuffer; |
| 396 | + rdata[0].data = (char *) &xlrec; |
| 397 | + rdata[0].len = offsetof(xl_dbase_create_rec, src_path); |
| 398 | + rdata[0].next = &(rdata[1]); |
| 399 | + |
| 400 | + rdata[1].buffer = InvalidBuffer; |
| 401 | + rdata[1].data = (char *) srcpath; |
| 402 | + rdata[1].len = strlen(srcpath) + 1; |
| 403 | + rdata[1].next = &(rdata[2]); |
| 404 | + |
| 405 | + rdata[2].buffer = InvalidBuffer; |
| 406 | + rdata[2].data = (char *) dstpath; |
| 407 | + rdata[2].len = strlen(dstpath) + 1; |
| 408 | + rdata[2].next = NULL; |
| 409 | + |
| 410 | + (void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_CREATE, rdata); |
| 411 | + } |
388 | 412 | }
|
389 | 413 | heap_endscan(scan);
|
390 | 414 | heap_close(rel, AccessShareLock);
|
@@ -970,11 +994,27 @@ remove_dbtablespaces(Oid db_id)
|
970 | 994 | }
|
971 | 995 |
|
972 | 996 | if (!rmtree(dstpath, true))
|
973 |
| - { |
974 | 997 | ereport(WARNING,
|
975 | 998 | (errmsg("could not remove database directory \"%s\"",
|
976 |
| - dstpath), |
977 |
| - errhint("Look in the postmaster's stderr log for more information."))); |
| 999 | + dstpath))); |
| 1000 | + |
| 1001 | + /* Record the filesystem change in XLOG */ |
| 1002 | + { |
| 1003 | + xl_dbase_drop_rec xlrec; |
| 1004 | + XLogRecData rdata[2]; |
| 1005 | + |
| 1006 | + xlrec.db_id = db_id; |
| 1007 | + rdata[0].buffer = InvalidBuffer; |
| 1008 | + rdata[0].data = (char *) &xlrec; |
| 1009 | + rdata[0].len = offsetof(xl_dbase_drop_rec, dir_path); |
| 1010 | + rdata[0].next = &(rdata[1]); |
| 1011 | + |
| 1012 | + rdata[1].buffer = InvalidBuffer; |
| 1013 | + rdata[1].data = (char *) dstpath; |
| 1014 | + rdata[1].len = strlen(dstpath) + 1; |
| 1015 | + rdata[1].next = NULL; |
| 1016 | + |
| 1017 | + (void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_DROP, rdata); |
978 | 1018 | }
|
979 | 1019 |
|
980 | 1020 | pfree(dstpath);
|
@@ -1063,3 +1103,105 @@ get_database_name(Oid dbid)
|
1063 | 1103 |
|
1064 | 1104 | return result;
|
1065 | 1105 | }
|
| 1106 | + |
| 1107 | +/* |
| 1108 | + * DATABASE resource manager's routines |
| 1109 | + */ |
| 1110 | +void |
| 1111 | +dbase_redo(XLogRecPtr lsn, XLogRecord *record) |
| 1112 | +{ |
| 1113 | + uint8 info = record->xl_info & ~XLR_INFO_MASK; |
| 1114 | + |
| 1115 | + if (info == XLOG_DBASE_CREATE) |
| 1116 | + { |
| 1117 | + xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) XLogRecGetData(record); |
| 1118 | + char *dst_path = xlrec->src_path + strlen(xlrec->src_path) + 1; |
| 1119 | + struct stat st; |
| 1120 | +#ifndef WIN32 |
| 1121 | + char buf[2 * MAXPGPATH + 100]; |
| 1122 | +#endif |
| 1123 | + |
| 1124 | + /* |
| 1125 | + * Our theory for replaying a CREATE is to forcibly drop the target |
| 1126 | + * subdirectory if present, then re-copy the source data. This |
| 1127 | + * may be more work than needed, but it is simple to implement. |
| 1128 | + */ |
| 1129 | + if (stat(dst_path, &st) == 0 && S_ISDIR(st.st_mode)) |
| 1130 | + { |
| 1131 | + if (!rmtree(dst_path, true)) |
| 1132 | + ereport(WARNING, |
| 1133 | + (errmsg("could not remove database directory \"%s\"", |
| 1134 | + dst_path))); |
| 1135 | + } |
| 1136 | + |
| 1137 | +#ifndef WIN32 |
| 1138 | + /* |
| 1139 | + * Copy this subdirectory to the new location |
| 1140 | + * |
| 1141 | + * XXX use of cp really makes this code pretty grotty, particularly |
| 1142 | + * with respect to lack of ability to report errors well. Someday |
| 1143 | + * rewrite to do it for ourselves. |
| 1144 | + */ |
| 1145 | + |
| 1146 | + /* We might need to use cp -R one day for portability */ |
| 1147 | + snprintf(buf, sizeof(buf), "cp -r '%s' '%s'", |
| 1148 | + xlrec->src_path, dst_path); |
| 1149 | + if (system(buf) != 0) |
| 1150 | + ereport(ERROR, |
| 1151 | + (errmsg("could not initialize database directory"), |
| 1152 | + errdetail("Failing system command was: %s", buf), |
| 1153 | + errhint("Look in the postmaster's stderr log for more information."))); |
| 1154 | +#else /* WIN32 */ |
| 1155 | + if (copydir(xlrec->src_path, dst_path) != 0) |
| 1156 | + { |
| 1157 | + /* copydir should already have given details of its troubles */ |
| 1158 | + ereport(ERROR, |
| 1159 | + (errmsg("could not initialize database directory"))); |
| 1160 | + } |
| 1161 | +#endif /* WIN32 */ |
| 1162 | + } |
| 1163 | + else if (info == XLOG_DBASE_DROP) |
| 1164 | + { |
| 1165 | + xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) XLogRecGetData(record); |
| 1166 | + |
| 1167 | + /* Drop pages for this database that are in the shared buffer cache */ |
| 1168 | + DropBuffers(xlrec->db_id); |
| 1169 | + |
| 1170 | + if (!rmtree(xlrec->dir_path, true)) |
| 1171 | + ereport(WARNING, |
| 1172 | + (errmsg("could not remove database directory \"%s\"", |
| 1173 | + xlrec->dir_path))); |
| 1174 | + } |
| 1175 | + else |
| 1176 | + elog(PANIC, "dbase_redo: unknown op code %u", info); |
| 1177 | +} |
| 1178 | + |
| 1179 | +void |
| 1180 | +dbase_undo(XLogRecPtr lsn, XLogRecord *record) |
| 1181 | +{ |
| 1182 | + elog(PANIC, "dbase_undo: unimplemented"); |
| 1183 | +} |
| 1184 | + |
| 1185 | +void |
| 1186 | +dbase_desc(char *buf, uint8 xl_info, char *rec) |
| 1187 | +{ |
| 1188 | + uint8 info = xl_info & ~XLR_INFO_MASK; |
| 1189 | + |
| 1190 | + if (info == XLOG_DBASE_CREATE) |
| 1191 | + { |
| 1192 | + xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) rec; |
| 1193 | + char *dst_path = xlrec->src_path + strlen(xlrec->src_path) + 1; |
| 1194 | + |
| 1195 | + sprintf(buf + strlen(buf), "create db: %u copy \"%s\" to \"%s\"", |
| 1196 | + xlrec->db_id, xlrec->src_path, dst_path); |
| 1197 | + } |
| 1198 | + else if (info == XLOG_DBASE_DROP) |
| 1199 | + { |
| 1200 | + xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) rec; |
| 1201 | + |
| 1202 | + sprintf(buf + strlen(buf), "drop db: %u directory: \"%s\"", |
| 1203 | + xlrec->db_id, xlrec->dir_path); |
| 1204 | + } |
| 1205 | + else |
| 1206 | + strcat(buf, "UNKNOWN"); |
| 1207 | +} |
0 commit comments