mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-30 04:26:45 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			309 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*-
 | |
|  * See the file LICENSE for redistribution information.
 | |
|  *
 | |
|  * Copyright (c) 2001-2002
 | |
|  *	Sleepycat Software.  All rights reserved.
 | |
|  */
 | |
| 
 | |
| #include "db_config.h"
 | |
| 
 | |
| #ifndef lint
 | |
| static const char revid[] = "$Id: fop_rec.c,v 1.18 2002/08/14 20:27:01 bostic Exp $";
 | |
| #endif /* not lint */
 | |
| 
 | |
| #ifndef NO_SYSTEM_INCLUDES
 | |
| #include <sys/types.h>
 | |
| 
 | |
| #include <string.h>
 | |
| #endif
 | |
| 
 | |
| #include "db_int.h"
 | |
| #include "dbinc/db_page.h"
 | |
| #include "dbinc/fop.h"
 | |
| #include "dbinc/db_am.h"
 | |
| #include "dbinc/txn.h"
 | |
| 
 | |
| /*
 | |
|  * __fop_create_recover --
 | |
|  *	Recovery function for create.
 | |
|  *
 | |
|  * PUBLIC: int __fop_create_recover
 | |
|  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
 | |
|  */
 | |
| int
 | |
| __fop_create_recover(dbenv, dbtp, lsnp, op, info)
 | |
| 	DB_ENV *dbenv;
 | |
| 	DBT *dbtp;
 | |
| 	DB_LSN *lsnp;
 | |
| 	db_recops op;
 | |
| 	void *info;
 | |
| {
 | |
| 	DB_FH fh;
 | |
| 	__fop_create_args *argp;
 | |
| 	char *real_name;
 | |
| 	int ret;
 | |
| 
 | |
| 	real_name = NULL;
 | |
| 	COMPQUIET(info, NULL);
 | |
| 	REC_PRINT(__fop_create_print);
 | |
| 	REC_NOOP_INTRO(__fop_create_read);
 | |
| 
 | |
| 	if ((ret = __db_appname(dbenv, (APPNAME)argp->appname,
 | |
| 	    (const char *)argp->name.data, 0, NULL, &real_name)) != 0)
 | |
| 		goto out;
 | |
| 
 | |
| 	if (DB_UNDO(op))
 | |
| 		(void)__os_unlink(dbenv, real_name);
 | |
| 	else if (DB_REDO(op))
 | |
| 		if ((ret = __os_open(dbenv, real_name,
 | |
| 		    DB_OSO_CREATE | DB_OSO_EXCL, argp->mode, &fh)) == 0)
 | |
| 			__os_closehandle(dbenv, &fh);
 | |
| 
 | |
| 	*lsnp = argp->prev_lsn;
 | |
| 
 | |
| out: if (real_name != NULL)
 | |
| 		__os_free(dbenv, real_name);
 | |
| 
 | |
| 	REC_NOOP_CLOSE;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * __fop_remove_recover --
 | |
|  *	Recovery function for remove.
 | |
|  *
 | |
|  * PUBLIC: int __fop_remove_recover
 | |
|  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
 | |
|  */
 | |
| int
 | |
| __fop_remove_recover(dbenv, dbtp, lsnp, op, info)
 | |
| 	DB_ENV *dbenv;
 | |
| 	DBT *dbtp;
 | |
| 	DB_LSN *lsnp;
 | |
| 	db_recops op;
 | |
| 	void *info;
 | |
| {
 | |
| 	__fop_remove_args *argp;
 | |
| 	char *real_name;
 | |
| 	int ret;
 | |
| 
 | |
| 	real_name = NULL;
 | |
| 	COMPQUIET(info, NULL);
 | |
| 	REC_PRINT(__fop_remove_print);
 | |
| 	REC_NOOP_INTRO(__fop_remove_read);
 | |
| 
 | |
| 	if ((ret = __db_appname(dbenv, (APPNAME)argp->appname,
 | |
| 	    (const char *)argp->name.data, 0, NULL, &real_name)) != 0)
 | |
| 		goto out;
 | |
| 
 | |
| 	if (DB_REDO(op) && (ret = dbenv->memp_nameop(dbenv,
 | |
| 	    (u_int8_t *)argp->fid.data, NULL, real_name, NULL)) != 0)
 | |
| 		goto out;
 | |
| 
 | |
| 	*lsnp = argp->prev_lsn;
 | |
| out:	if (real_name != NULL)
 | |
| 		__os_free(dbenv, real_name);
 | |
| 	REC_NOOP_CLOSE;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * __fop_write_recover --
 | |
|  *	Recovery function for writechunk.
 | |
|  *
 | |
|  * PUBLIC: int __fop_write_recover
 | |
|  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
 | |
|  */
 | |
| int
 | |
| __fop_write_recover(dbenv, dbtp, lsnp, op, info)
 | |
| 	DB_ENV *dbenv;
 | |
| 	DBT *dbtp;
 | |
| 	DB_LSN *lsnp;
 | |
| 	db_recops op;
 | |
| 	void *info;
 | |
| {
 | |
| 	__fop_write_args *argp;
 | |
| 	int ret;
 | |
| 
 | |
| 	COMPQUIET(info, NULL);
 | |
| 	REC_PRINT(__fop_write_print);
 | |
| 	REC_NOOP_INTRO(__fop_write_read);
 | |
| 
 | |
| 	if (DB_UNDO(op))
 | |
| 		DB_ASSERT(argp->flag != 0);
 | |
| 	else if (DB_REDO(op))
 | |
| 		ret = __fop_write(dbenv,
 | |
| 		    argp->txnid, argp->name.data, argp->appname, NULL,
 | |
| 		    argp->offset, argp->page.data, argp->page.size, argp->flag);
 | |
| 
 | |
| 	*lsnp = argp->prev_lsn;
 | |
| 	REC_NOOP_CLOSE;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * __fop_rename_recover --
 | |
|  *	Recovery function for rename.
 | |
|  *
 | |
|  * PUBLIC: int __fop_rename_recover
 | |
|  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
 | |
|  */
 | |
| int
 | |
| __fop_rename_recover(dbenv, dbtp, lsnp, op, info)
 | |
| 	DB_ENV *dbenv;
 | |
| 	DBT *dbtp;
 | |
| 	DB_LSN *lsnp;
 | |
| 	db_recops op;
 | |
| 	void *info;
 | |
| {
 | |
| 	__fop_rename_args *argp;
 | |
| 	DBMETA *meta;
 | |
| 	char *real_new, *real_old, *src;
 | |
| 	int ret;
 | |
| 	u_int8_t *fileid, mbuf[DBMETASIZE];
 | |
| 
 | |
| 	real_new = NULL;
 | |
| 	real_old = NULL;
 | |
| 	ret = 0;
 | |
| 	meta = (DBMETA *)&mbuf[0];
 | |
| 
 | |
| 	COMPQUIET(info, NULL);
 | |
| 	REC_PRINT(__fop_rename_print);
 | |
| 	REC_NOOP_INTRO(__fop_rename_read);
 | |
| 	fileid = argp->fileid.data;
 | |
| 
 | |
| 	if ((ret = __db_appname(dbenv, (APPNAME)argp->appname,
 | |
| 	    (const char *)argp->newname.data, 0, NULL, &real_new)) != 0)
 | |
| 		goto out;
 | |
| 	if ((ret = __db_appname(dbenv, (APPNAME)argp->appname,
 | |
| 	    (const char *)argp->oldname.data, 0, NULL, &real_old)) != 0)
 | |
| 		goto out;
 | |
| 
 | |
| 	/*
 | |
| 	 * Verify that we are manipulating the correct file.  We should always
 | |
| 	 * be OK on an ABORT or an APPLY, but during recovery, we have to
 | |
| 	 * check.
 | |
| 	 */
 | |
| 	if (op != DB_TXN_ABORT && op != DB_TXN_APPLY) {
 | |
| 		src = DB_UNDO(op) ? real_new : real_old;
 | |
| 		/*
 | |
| 		 * Interpret any error as meaning that the file either doesn't
 | |
| 		 * exist, doesn't have a meta-data page, or is in some other
 | |
| 		 * way, shape or form, incorrect, so that we should not restore
 | |
| 		 * it.
 | |
| 		 */
 | |
| 		if (__fop_read_meta(
 | |
| 		    dbenv, src, mbuf, DBMETASIZE, NULL, 1, 0) != 0)
 | |
| 			goto done;
 | |
| 		if (__db_chk_meta(dbenv, NULL, meta, 1) != 0)
 | |
| 			goto done;
 | |
| 		if (memcmp(argp->fileid.data, meta->uid, DB_FILE_ID_LEN) != 0)
 | |
| 			goto done;
 | |
| 	}
 | |
| 
 | |
| 	if (DB_UNDO(op))
 | |
| 		(void)dbenv->memp_nameop(dbenv, fileid,
 | |
| 		    (const char *)argp->oldname.data, real_new, real_old);
 | |
| 	if (DB_REDO(op))
 | |
| 		(void)dbenv->memp_nameop(dbenv, fileid,
 | |
| 		    (const char *)argp->newname.data, real_old, real_new);
 | |
| 
 | |
| done:	*lsnp = argp->prev_lsn;
 | |
| out:	if (real_new != NULL)
 | |
| 		__os_free(dbenv, real_new);
 | |
| 	if (real_old != NULL)
 | |
| 		__os_free(dbenv, real_old);
 | |
| 
 | |
| 	REC_NOOP_CLOSE;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * __fop_file_remove_recover --
 | |
|  *	Recovery function for file_remove.  On the REDO pass, we need to
 | |
|  * make sure no one recreated the file while we weren't looking.  On an
 | |
|  * undo pass must check if the file we are interested in is the one that
 | |
|  * exists and then set the status of the child transaction depending on
 | |
|  * what we find out.
 | |
|  *
 | |
|  * PUBLIC: int __fop_file_remove_recover
 | |
|  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
 | |
|  */
 | |
| int
 | |
| __fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
 | |
| 	DB_ENV *dbenv;
 | |
| 	DBT *dbtp;
 | |
| 	DB_LSN *lsnp;
 | |
| 	db_recops op;
 | |
| 	void *info;
 | |
| {
 | |
| 	__fop_file_remove_args *argp;
 | |
| 	DBMETA *meta;
 | |
| 	char *real_name;
 | |
| 	int is_real, is_tmp, ret;
 | |
| 	u_int8_t mbuf[DBMETASIZE];
 | |
| 	u_int32_t cstat;
 | |
| 
 | |
| 	real_name = NULL;
 | |
| 	is_real = is_tmp = 0;
 | |
| 	meta = (DBMETA *)&mbuf[0];
 | |
| 	REC_PRINT(__fop_file_remove_print);
 | |
| 	REC_NOOP_INTRO(__fop_file_remove_read);
 | |
| 
 | |
| 	/*
 | |
| 	 * This record is only interesting on the backward, forward, and
 | |
| 	 * apply phases.
 | |
| 	 */
 | |
| 	if (op != DB_TXN_BACKWARD_ROLL &&
 | |
| 	    op != DB_TXN_FORWARD_ROLL && op != DB_TXN_APPLY)
 | |
| 		goto done;
 | |
| 
 | |
| 	if ((ret = __db_appname(dbenv,
 | |
| 	    (APPNAME)argp->appname, argp->name.data, 0, NULL, &real_name)) != 0)
 | |
| 		goto out;
 | |
| 
 | |
| 	/* Verify that we are manipulating the correct file.  */
 | |
| 	if ((ret = __fop_read_meta(dbenv,
 | |
| 	    real_name, mbuf, DBMETASIZE, NULL, 1, 0)) != 0) {
 | |
| 		/* File does not exist. */
 | |
| 		cstat = TXN_EXPECTED;
 | |
| 	} else {
 | |
| 		/*
 | |
| 		 * We can ignore errors here since we'll simply fail the
 | |
| 		 * checks below and assume this is the wrong file.
 | |
| 		 */
 | |
| 		(void)__db_chk_meta(dbenv, NULL, meta, 1);
 | |
| 		is_real =
 | |
| 		    memcmp(argp->real_fid.data, meta->uid, DB_FILE_ID_LEN) == 0;
 | |
| 		is_tmp =
 | |
| 		    memcmp(argp->tmp_fid.data, meta->uid, DB_FILE_ID_LEN) == 0;
 | |
| 
 | |
| 		if (!is_real && !is_tmp)
 | |
| 			/* File exists, but isn't what we were removing. */
 | |
| 			cstat = TXN_IGNORE;
 | |
| 		else
 | |
| 			/* File exists and is the one that we were removing. */
 | |
| 			cstat = TXN_COMMIT;
 | |
| 	}
 | |
| 
 | |
| 	if (DB_UNDO(op)) {
 | |
| 		/* On the backward pass, we leave a note for the child txn. */
 | |
| 		if ((ret = __db_txnlist_update(dbenv,
 | |
| 		    info, argp->child, cstat, NULL)) == DB_NOTFOUND)
 | |
| 			ret = __db_txnlist_add(dbenv,
 | |
| 			    info, argp->child, cstat, NULL);
 | |
| 	} else if (DB_REDO(op)) {
 | |
| 		/*
 | |
| 		 * On the forward pass, check if someone recreated the
 | |
| 		 * file while we weren't looking.
 | |
| 		 */
 | |
| 		if (cstat == TXN_COMMIT)
 | |
| 			(void)dbenv->memp_nameop(dbenv,
 | |
| 			    is_real ? argp->real_fid.data : argp->tmp_fid.data,
 | |
| 			    NULL, real_name, NULL);
 | |
| 	}
 | |
| 
 | |
| done:	*lsnp = argp->prev_lsn;
 | |
| 	ret = 0;
 | |
| 
 | |
| out:	if (real_name != NULL)
 | |
| 		__os_free(dbenv, real_name);
 | |
| 	REC_NOOP_CLOSE;
 | |
| }
 | 
