smgr.c 9.2 KB
Newer Older
1 2 3
/*-------------------------------------------------------------------------
 *
 * smgr.c--
4
 *	  public interface routines to storage manager switch.
5
 *
6 7
 *	  All file system operations in POSTGRES dispatch through these
 *	  routines.
8 9 10 11 12
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
13
 *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.10 1997/09/08 02:29:36 momjian Exp $
14 15 16 17 18 19 20 21
 *
 *-------------------------------------------------------------------------
 */
#include <string.h>
#include "postgres.h"

#include "storage/ipc.h"
#include "storage/block.h"
M
Marc G. Fournier 已提交
22
#include "storage/smgr.h"
23 24 25
#include "utils/rel.h"
#include "utils/palloc.h"

26
static void smgrshutdown(int dummy);
27 28 29

typedef struct f_smgr
{
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
	int			(*smgr_init) ();/* may be NULL */
	int			(*smgr_shutdown) ();	/* may be NULL */
	int			(*smgr_create) ();
	int			(*smgr_unlink) ();
	int			(*smgr_extend) ();
	int			(*smgr_open) ();
	int			(*smgr_close) ();
	int			(*smgr_read) ();
	int			(*smgr_write) ();
	int			(*smgr_flush) ();
	int			(*smgr_blindwrt) ();
	int			(*smgr_nblocks) ();
	int			(*smgr_truncate) ();
	int			(*smgr_commit) ();		/* may be NULL */
	int			(*smgr_abort) ();		/* may be NULL */
}			f_smgr;
46 47

/*
48 49
 *	The weird placement of commas in this init block is to keep the compiler
 *	happy, regardless of what storage managers we have (or don't have).
50 51
 */

52
static f_smgr smgrsw[] = {
53

54 55 56 57
	/* magnetic disk */
	{mdinit, NULL, mdcreate, mdunlink, mdextend, mdopen, mdclose,
		mdread, mdwrite, mdflush, mdblindwrt, mdnblocks, mdtruncate,
	mdcommit, mdabort},
58 59

#ifdef MAIN_MEMORY
60 61 62 63
	/* main memory */
	{mminit, mmshutdown, mmcreate, mmunlink, mmextend, mmopen, mmclose,
		mmread, mmwrite, mmflush, mmblindwrt, mmnblocks, NULL,
	mmcommit, mmabort},
64

65
#endif							/* MAIN_MEMORY */
66 67 68
};

/*
69 70 71 72
 *	This array records which storage managers are write-once, and which
 *	support overwrite.	A 'true' entry means that the storage manager is
 *	write-once.  In the best of all possible worlds, there would be no
 *	write-once storage managers.
73 74
 */

75
static bool smgrwo[] = {
76
	false,						/* magnetic disk */
77
#ifdef MAIN_MEMORY
78 79
	false,						/* main memory */
#endif							/* MAIN_MEMORY */
80
};
81
static int	NSmgr = lengthof(smgrsw);
82 83

/*
84 85
 *	smgrinit(), smgrshutdown() -- Initialize or shut down all storage
 *								  managers.
86 87 88 89 90
 *
 */
int
smgrinit()
{
91
	int			i;
92 93 94 95 96 97 98 99

	for (i = 0; i < NSmgr; i++)
	{
		if (smgrsw[i].smgr_init)
		{
			if ((*(smgrsw[i].smgr_init)) () == SM_FAIL)
				elog(FATAL, "initialization failed on %s", smgrout(i));
		}
100 101
	}

102 103
	/* register the shutdown proc */
	on_exitpg(smgrshutdown, 0);
104

105
	return (SM_SUCCESS);
106 107
}

108
static void
109 110
smgrshutdown(int dummy)
{
111
	int			i;
112 113 114 115 116 117 118 119

	for (i = 0; i < NSmgr; i++)
	{
		if (smgrsw[i].smgr_shutdown)
		{
			if ((*(smgrsw[i].smgr_shutdown)) () == SM_FAIL)
				elog(FATAL, "shutdown failed on %s", smgrout(i));
		}
120 121 122 123
	}
}

/*
124
 *	smgrcreate() -- Create a new relation.
125
 *
126 127
 *		This routine takes a reldesc, creates the relation on the appropriate
 *		device, and returns a file descriptor for it.
128 129 130 131
 */
int
smgrcreate(int16 which, Relation reln)
{
132
	int			fd;
133

134 135 136
	if ((fd = (*(smgrsw[which].smgr_create)) (reln)) < 0)
		elog(WARN, "cannot open %s",
			 &(reln->rd_rel->relname.data[0]));
137

138
	return (fd);
139 140 141
}

/*
142
 *	smgrunlink() -- Unlink a relation.
143
 *
144
 *		The relation is removed from the store.
145 146 147 148
 */
int
smgrunlink(int16 which, Relation reln)
{
149
	int			status;
150

151 152 153
	if ((status = (*(smgrsw[which].smgr_unlink)) (reln)) == SM_FAIL)
		elog(WARN, "cannot unlink %s",
			 &(reln->rd_rel->relname.data[0]));
154

155
	return (status);
156 157 158
}

/*
159
 *	smgrextend() -- Add a new block to a file.
160
 *
161 162
 *		Returns SM_SUCCESS on success; aborts the current transaction on
 *		failure.
163 164 165 166
 */
int
smgrextend(int16 which, Relation reln, char *buffer)
{
167
	int			status;
168

169
	status = (*(smgrsw[which].smgr_extend)) (reln, buffer);
170

171 172 173
	if (status == SM_FAIL)
		elog(WARN, "%s: cannot extend",
			 &(reln->rd_rel->relname.data[0]));
174

175
	return (status);
176 177 178
}

/*
179
 *	smgropen() -- Open a relation using a particular storage manager.
180
 *
181 182
 *		Returns the fd for the open relation on success, aborts the
 *		transaction on failure.
183 184 185 186
 */
int
smgropen(int16 which, Relation reln)
{
187
	int			fd;
188

189 190 191
	if ((fd = (*(smgrsw[which].smgr_open)) (reln)) < 0)
		elog(WARN, "cannot open %s",
			 &(reln->rd_rel->relname.data[0]));
192

193
	return (fd);
194 195 196
}

/*
197
 *	smgrclose() -- Close a relation.
198
 *
199 200 201 202 203 204
 *		NOTE: mdclose frees fd vector! It may be re-used for other relation!
 *		reln should be flushed from cache after closing !..
 *		Currently, smgrclose is calling by
 *		relcache.c:RelationPurgeLocalRelation() only.
 *		It would be nice to have smgrfree(), but because of
 *		smgrclose is called from single place...		- vadim 05/22/97
V
Vadim B. Mikheev 已提交
205
 *
206
 *		Returns SM_SUCCESS on success, aborts on failure.
207 208 209 210
 */
int
smgrclose(int16 which, Relation reln)
{
211 212 213
	if ((*(smgrsw[which].smgr_close)) (reln) == SM_FAIL)
		elog(WARN, "cannot close %s",
			 &(reln->rd_rel->relname.data[0]));
214

215
	return (SM_SUCCESS);
216 217 218
}

/*
219 220
 *	smgrread() -- read a particular block from a relation into the supplied
 *				  buffer.
221
 *
222 223 224 225 226
 *		This routine is called from the buffer manager in order to
 *		instantiate pages in the shared buffer cache.  All storage managers
 *		return pages in the format that POSTGRES expects.  This routine
 *		dispatches the read.  On success, it returns SM_SUCCESS.  On failure,
 *		the current transaction is aborted.
227 228 229 230
 */
int
smgrread(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
{
231
	int			status;
232

233
	status = (*(smgrsw[which].smgr_read)) (reln, blocknum, buffer);
234

235 236 237
	if (status == SM_FAIL)
		elog(WARN, "cannot read block %d of %s",
			 blocknum, &(reln->rd_rel->relname.data[0]));
238

239
	return (status);
240 241 242
}

/*
243
 *	smgrwrite() -- Write the supplied buffer out.
244
 *
245 246 247 248
 *		This is not a synchronous write -- the interface for that is
 *		smgrflush().  The buffer is written out via the appropriate
 *		storage manager.  This routine returns SM_SUCCESS or aborts
 *		the current transaction.
249 250 251 252
 */
int
smgrwrite(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
{
253
	int			status;
254

255
	status = (*(smgrsw[which].smgr_write)) (reln, blocknum, buffer);
256

257 258 259
	if (status == SM_FAIL)
		elog(WARN, "cannot write block %d of %s",
			 blocknum, &(reln->rd_rel->relname.data[0]));
260

261
	return (status);
262 263 264
}

/*
265
 *	smgrflush() -- A synchronous smgrwrite().
266 267 268 269
 */
int
smgrflush(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
{
270
	int			status;
271

272
	status = (*(smgrsw[which].smgr_flush)) (reln, blocknum, buffer);
273

274 275 276
	if (status == SM_FAIL)
		elog(WARN, "cannot flush block %d of %s to stable store",
			 blocknum, &(reln->rd_rel->relname.data[0]));
277

278
	return (status);
279 280 281
}

/*
282
 *	smgrblindwrt() -- Write a page out blind.
283
 *
284 285 286 287 288 289 290 291
 *		In some cases, we may find a page in the buffer cache that we
 *		can't make a reldesc for.  This happens, for example, when we
 *		want to reuse a dirty page that was written by a transaction
 *		that has not yet committed, which created a new relation.  In
 *		this case, the buffer manager will call smgrblindwrt() with
 *		the name and OID of the database and the relation to which the
 *		buffer belongs.  Every storage manager must be able to force
 *		this page down to stable storage in this circumstance.
292 293 294
 */
int
smgrblindwrt(int16 which,
295 296 297 298 299 300
			 char *dbname,
			 char *relname,
			 Oid dbid,
			 Oid relid,
			 BlockNumber blkno,
			 char *buffer)
301
{
302 303 304
	char	   *dbstr;
	char	   *relstr;
	int			status;
305

306 307
	dbstr = pstrdup(dbname);
	relstr = pstrdup(relname);
308

309 310
	status = (*(smgrsw[which].smgr_blindwrt)) (dbstr, relstr, dbid, relid,
											   blkno, buffer);
311

312 313 314
	if (status == SM_FAIL)
		elog(WARN, "cannot write block %d of %s [%s] blind",
			 blkno, relstr, dbstr);
315

316 317
	pfree(dbstr);
	pfree(relstr);
318

319
	return (status);
320 321 322
}

/*
323 324
 *	smgrnblocks() -- Calculate the number of POSTGRES blocks in the
 *					 supplied relation.
325
 *
326 327
 *		Returns the number of blocks on success, aborts the current
 *		transaction on failure.
328 329 330 331
 */
int
smgrnblocks(int16 which, Relation reln)
{
332
	int			nblocks;
333

334 335 336
	if ((nblocks = (*(smgrsw[which].smgr_nblocks)) (reln)) < 0)
		elog(WARN, "cannot count blocks for %s",
			 &(reln->rd_rel->relname.data[0]));
337

338
	return (nblocks);
339 340
}

341
/*
342 343
 *	smgrtruncate() -- Truncate supplied relation to a specified number
 *						of blocks
344
 *
345 346
 *		Returns the number of blocks on success, aborts the current
 *		transaction on failure.
347 348 349 350
 */
int
smgrtruncate(int16 which, Relation reln, int nblocks)
{
351
	int			newblks;
352 353 354 355 356 357 358 359 360 361

	newblks = nblocks;
	if (smgrsw[which].smgr_truncate)
	{
		if ((newblks = (*(smgrsw[which].smgr_truncate)) (reln, nblocks)) < 0)
			elog(WARN, "cannot truncate %s to %d blocks",
				 &(reln->rd_rel->relname.data[0]), nblocks);
	}

	return (newblks);
362 363
}

364
/*
365 366
 *	smgrcommit(), smgrabort() -- Commit or abort changes made during the
 *								 current transaction.
367 368 369 370
 */
int
smgrcommit()
{
371
	int			i;
372 373 374 375 376 377 378 379

	for (i = 0; i < NSmgr; i++)
	{
		if (smgrsw[i].smgr_commit)
		{
			if ((*(smgrsw[i].smgr_commit)) () == SM_FAIL)
				elog(FATAL, "transaction commit failed on %s", smgrout(i));
		}
380 381
	}

382
	return (SM_SUCCESS);
383 384
}

385
#ifdef NOT_USED
386 387 388
int
smgrabort()
{
389
	int			i;
390 391 392 393 394 395 396 397

	for (i = 0; i < NSmgr; i++)
	{
		if (smgrsw[i].smgr_abort)
		{
			if ((*(smgrsw[i].smgr_abort)) () == SM_FAIL)
				elog(FATAL, "transaction abort failed on %s", smgrout(i));
		}
398 399
	}

400
	return (SM_SUCCESS);
401
}
402

403
#endif
404 405 406 407

bool
smgriswo(int16 smgrno)
{
408 409
	if (smgrno < 0 || smgrno >= NSmgr)
		elog(WARN, "illegal storage manager number %d", smgrno);
410

411
	return (smgrwo[smgrno]);
412
}