|
15 | 15 | *
|
16 | 16 | *
|
17 | 17 | * IDENTIFICATION
|
18 |
| - * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.154 2005/03/12 21:33:55 tgl Exp $ |
| 18 | + * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.155 2005/03/23 00:03:28 tgl Exp $ |
19 | 19 | *
|
20 | 20 | *-------------------------------------------------------------------------
|
21 | 21 | */
|
@@ -438,23 +438,17 @@ createdb(const CreatedbStmt *stmt)
|
438 | 438 | /* Record the filesystem change in XLOG */
|
439 | 439 | {
|
440 | 440 | xl_dbase_create_recxlrec;
|
441 |
| -XLogRecDatardata[3]; |
| 441 | +XLogRecDatardata[1]; |
442 | 442 |
|
443 | 443 | xlrec.db_id=dboid;
|
| 444 | +xlrec.tablespace_id=dsttablespace; |
| 445 | +xlrec.src_db_id=src_dboid; |
| 446 | +xlrec.src_tablespace_id=srctablespace; |
| 447 | + |
444 | 448 | rdata[0].buffer=InvalidBuffer;
|
445 | 449 | rdata[0].data= (char*)&xlrec;
|
446 |
| -rdata[0].len= offsetof(xl_dbase_create_rec,src_path); |
447 |
| -rdata[0].next=&(rdata[1]); |
448 |
| - |
449 |
| -rdata[1].buffer=InvalidBuffer; |
450 |
| -rdata[1].data= (char*)srcpath; |
451 |
| -rdata[1].len=strlen(srcpath)+1; |
452 |
| -rdata[1].next=&(rdata[2]); |
453 |
| - |
454 |
| -rdata[2].buffer=InvalidBuffer; |
455 |
| -rdata[2].data= (char*)dstpath; |
456 |
| -rdata[2].len=strlen(dstpath)+1; |
457 |
| -rdata[2].next=NULL; |
| 450 | +rdata[0].len=sizeof(xl_dbase_create_rec); |
| 451 | +rdata[0].next=NULL; |
458 | 452 |
|
459 | 453 | (void)XLogInsert(RM_DBASE_ID,XLOG_DBASE_CREATE,rdata);
|
460 | 454 | }
|
@@ -1076,18 +1070,15 @@ remove_dbtablespaces(Oid db_id)
|
1076 | 1070 | /* Record the filesystem change in XLOG */
|
1077 | 1071 | {
|
1078 | 1072 | xl_dbase_drop_recxlrec;
|
1079 |
| -XLogRecDatardata[2]; |
| 1073 | +XLogRecDatardata[1]; |
1080 | 1074 |
|
1081 | 1075 | xlrec.db_id=db_id;
|
| 1076 | +xlrec.tablespace_id=dsttablespace; |
| 1077 | + |
1082 | 1078 | rdata[0].buffer=InvalidBuffer;
|
1083 | 1079 | rdata[0].data= (char*)&xlrec;
|
1084 |
| -rdata[0].len= offsetof(xl_dbase_drop_rec,dir_path); |
1085 |
| -rdata[0].next=&(rdata[1]); |
1086 |
| - |
1087 |
| -rdata[1].buffer=InvalidBuffer; |
1088 |
| -rdata[1].data= (char*)dstpath; |
1089 |
| -rdata[1].len=strlen(dstpath)+1; |
1090 |
| -rdata[1].next=NULL; |
| 1080 | +rdata[0].len=sizeof(xl_dbase_drop_rec); |
| 1081 | +rdata[0].next=NULL; |
1091 | 1082 |
|
1092 | 1083 | (void)XLogInsert(RM_DBASE_ID,XLOG_DBASE_DROP,rdata);
|
1093 | 1084 | }
|
@@ -1190,6 +1181,86 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
|
1190 | 1181 | if (info==XLOG_DBASE_CREATE)
|
1191 | 1182 | {
|
1192 | 1183 | xl_dbase_create_rec*xlrec= (xl_dbase_create_rec*)XLogRecGetData(record);
|
| 1184 | +char*src_path; |
| 1185 | +char*dst_path; |
| 1186 | +structstatst; |
| 1187 | + |
| 1188 | +#ifndefWIN32 |
| 1189 | +charbuf[2*MAXPGPATH+100]; |
| 1190 | +#endif |
| 1191 | + |
| 1192 | +src_path=GetDatabasePath(xlrec->src_db_id,xlrec->src_tablespace_id); |
| 1193 | +dst_path=GetDatabasePath(xlrec->db_id,xlrec->tablespace_id); |
| 1194 | + |
| 1195 | +/* |
| 1196 | + * Our theory for replaying a CREATE is to forcibly drop the |
| 1197 | + * target subdirectory if present, then re-copy the source data. |
| 1198 | + * This may be more work than needed, but it is simple to |
| 1199 | + * implement. |
| 1200 | + */ |
| 1201 | +if (stat(dst_path,&st)==0&&S_ISDIR(st.st_mode)) |
| 1202 | +{ |
| 1203 | +if (!rmtree(dst_path, true)) |
| 1204 | +ereport(WARNING, |
| 1205 | +(errmsg("could not remove database directory \"%s\"", |
| 1206 | +dst_path))); |
| 1207 | +} |
| 1208 | + |
| 1209 | +/* |
| 1210 | + * Force dirty buffers out to disk, to ensure source database is |
| 1211 | + * up-to-date for the copy. (We really only need to flush buffers for |
| 1212 | + * the source database, but bufmgr.c provides no API for that.) |
| 1213 | + */ |
| 1214 | +BufferSync(); |
| 1215 | + |
| 1216 | +#ifndefWIN32 |
| 1217 | + |
| 1218 | +/* |
| 1219 | + * Copy this subdirectory to the new location |
| 1220 | + * |
| 1221 | + * XXX use of cp really makes this code pretty grotty, particularly |
| 1222 | + * with respect to lack of ability to report errors well. Someday |
| 1223 | + * rewrite to do it for ourselves. |
| 1224 | + */ |
| 1225 | + |
| 1226 | +/* We might need to use cp -R one day for portability */ |
| 1227 | +snprintf(buf,sizeof(buf),"cp -r '%s' '%s'", |
| 1228 | +src_path,dst_path); |
| 1229 | +if (system(buf)!=0) |
| 1230 | +ereport(ERROR, |
| 1231 | +(errmsg("could not initialize database directory"), |
| 1232 | +errdetail("Failing system command was: %s",buf), |
| 1233 | +errhint("Look in the postmaster's stderr log for more information."))); |
| 1234 | +#else/* WIN32 */ |
| 1235 | +if (copydir(src_path,dst_path)!=0) |
| 1236 | +{ |
| 1237 | +/* copydir should already have given details of its troubles */ |
| 1238 | +ereport(ERROR, |
| 1239 | +(errmsg("could not initialize database directory"))); |
| 1240 | +} |
| 1241 | +#endif/* WIN32 */ |
| 1242 | +} |
| 1243 | +elseif (info==XLOG_DBASE_DROP) |
| 1244 | +{ |
| 1245 | +xl_dbase_drop_rec*xlrec= (xl_dbase_drop_rec*)XLogRecGetData(record); |
| 1246 | +char*dst_path; |
| 1247 | + |
| 1248 | +dst_path=GetDatabasePath(xlrec->db_id,xlrec->tablespace_id); |
| 1249 | + |
| 1250 | +/* |
| 1251 | + * Drop pages for this database that are in the shared buffer |
| 1252 | + * cache |
| 1253 | + */ |
| 1254 | +DropBuffers(xlrec->db_id); |
| 1255 | + |
| 1256 | +if (!rmtree(dst_path, true)) |
| 1257 | +ereport(WARNING, |
| 1258 | +(errmsg("could not remove database directory \"%s\"", |
| 1259 | +dst_path))); |
| 1260 | +} |
| 1261 | +elseif (info==XLOG_DBASE_CREATE_OLD) |
| 1262 | +{ |
| 1263 | +xl_dbase_create_rec_old*xlrec= (xl_dbase_create_rec_old*)XLogRecGetData(record); |
1193 | 1264 | char*dst_path=xlrec->src_path+strlen(xlrec->src_path)+1;
|
1194 | 1265 | structstatst;
|
1195 | 1266 |
|
@@ -1245,9 +1316,9 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
|
1245 | 1316 | }
|
1246 | 1317 | #endif/* WIN32 */
|
1247 | 1318 | }
|
1248 |
| -elseif (info==XLOG_DBASE_DROP) |
| 1319 | +elseif (info==XLOG_DBASE_DROP_OLD) |
1249 | 1320 | {
|
1250 |
| -xl_dbase_drop_rec*xlrec= (xl_dbase_drop_rec*)XLogRecGetData(record); |
| 1321 | +xl_dbase_drop_rec_old*xlrec= (xl_dbase_drop_rec_old*)XLogRecGetData(record); |
1251 | 1322 |
|
1252 | 1323 | /*
|
1253 | 1324 | * Drop pages for this database that are in the shared buffer
|
@@ -1278,14 +1349,29 @@ dbase_desc(char *buf, uint8 xl_info, char *rec)
|
1278 | 1349 | if (info==XLOG_DBASE_CREATE)
|
1279 | 1350 | {
|
1280 | 1351 | xl_dbase_create_rec*xlrec= (xl_dbase_create_rec*)rec;
|
| 1352 | + |
| 1353 | +sprintf(buf+strlen(buf),"create db: copy dir %u/%u to %u/%u", |
| 1354 | +xlrec->src_db_id,xlrec->src_tablespace_id, |
| 1355 | +xlrec->db_id,xlrec->tablespace_id); |
| 1356 | +} |
| 1357 | +elseif (info==XLOG_DBASE_DROP) |
| 1358 | +{ |
| 1359 | +xl_dbase_drop_rec*xlrec= (xl_dbase_drop_rec*)rec; |
| 1360 | + |
| 1361 | +sprintf(buf+strlen(buf),"drop db: dir %u/%u", |
| 1362 | +xlrec->db_id,xlrec->tablespace_id); |
| 1363 | +} |
| 1364 | +elseif (info==XLOG_DBASE_CREATE_OLD) |
| 1365 | +{ |
| 1366 | +xl_dbase_create_rec_old*xlrec= (xl_dbase_create_rec_old*)rec; |
1281 | 1367 | char*dst_path=xlrec->src_path+strlen(xlrec->src_path)+1;
|
1282 | 1368 |
|
1283 | 1369 | sprintf(buf+strlen(buf),"create db: %u copy \"%s\" to \"%s\"",
|
1284 | 1370 | xlrec->db_id,xlrec->src_path,dst_path);
|
1285 | 1371 | }
|
1286 |
| -elseif (info==XLOG_DBASE_DROP) |
| 1372 | +elseif (info==XLOG_DBASE_DROP_OLD) |
1287 | 1373 | {
|
1288 |
| -xl_dbase_drop_rec*xlrec= (xl_dbase_drop_rec*)rec; |
| 1374 | +xl_dbase_drop_rec_old*xlrec= (xl_dbase_drop_rec_old*)rec; |
1289 | 1375 |
|
1290 | 1376 | sprintf(buf+strlen(buf),"drop db: %u directory: \"%s\"",
|
1291 | 1377 | xlrec->db_id,xlrec->dir_path);
|
|