/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
* Copyright (c) 1995, 1996
* Margo Seltzer. All rights reserved.
*/
/*
* Copyright (c) 1995, 1996
* The President and Fellows of Harvard University. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#ifndef lint
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <errno.h>
#include <string.h>
#endif
#include "db_int.h"
#include "shqueue.h"
#include "db_page.h"
#include "hash.h"
#include "btree.h"
#include "log.h"
#include "common_ext.h"
/*
* __ham_insdel_recover --
*
* PUBLIC: int __ham_insdel_recover
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/
int
int redo;
void *info;
{
getmeta = 0;
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist. That
* is equivalent to having a pagelsn of 0, so we
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
goto done;
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
if (ret != 0)
goto out;
getmeta = 1;
/*
* Two possible things going on:
* If we are undoing a delete, then the information logged is the
* entire entry off the page, not just the data of a dbt. In
* this case, we want to copy it back onto the page verbatim.
* We do this by calling __putitem with the type H_OFFPAGE instead
* of H_KEYDATA.
*/
/*
* Need to redo a PUT or undo a delete. If we are undoing a
* delete, we've got to restore the item back to its original
* position. That's a royal pain in the butt (because we do
* not store item lengths on the page), but there's no choice.
*/
} else
goto out;
/* Need to undo a put or redo a delete. */
goto out;
} else
goto out;
/* Return the previous LSN. */
ret = 0;
}
/*
* __ham_newpage_recover --
* message takes care of the pointer chains, not the data on the pages.
*
* PUBLIC: int __ham_newpage_recover
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/
int
int redo;
void *info;
{
getmeta = 0;
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist. That
* is equivalent to having a pagelsn of 0, so we
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
ret = 0;
goto ppage;
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
if (ret != 0)
goto out;
getmeta = 1;
/*
* There are potentially three pages we need to check: the one
* it.
*/
change = 0;
/* Redo a create new page or undo a delete new page. */
change = 1;
/*
* Redo a delete or undo a create new page. All we
* really need to do is change the LSN.
*/
change = 1;
}
if (!change) {
goto out;
} else {
goto out;
}
/* Now do the prev page. */
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist.
* That is equivalent to having a pagelsn of 0,
* so we would not have to undo anything. In
* this case, don't bother creating a page.
*/
ret = 0;
goto npage;
} else if ((ret =
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
change = 0;
/* Redo a create new page or undo a delete new page. */
change = 1;
/* Redo a delete or undo a create new page. */
change = 1;
}
if (!change) {
if ((ret =
goto out;
} else {
if ((ret =
goto out;
}
}
/* Now time to do the next page */
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist.
* That is equivalent to having a pagelsn of 0,
* so we would not have to undo anything. In
* this case, don't bother creating a page.
*/
goto done;
} else if ((ret =
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
change = 0;
/* Redo a create new page or undo a delete new page. */
change = 1;
/* Redo a delete or undo a create new page. */
change = 1;
}
if (!change) {
if ((ret =
goto out;
} else {
if ((ret =
goto out;
}
}
ret = 0;
}
/*
* __ham_replace_recover --
* This log message refers to partial puts that are local to a single
* page. You can think of them as special cases of the more general
* insdel log message.
*
* PUBLIC: int __ham_replace_recover
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/
int
int redo;
void *info;
{
getmeta = 0;
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist. That
* is equivalent to having a pagelsn of 0, so we
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
goto done;
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
if (ret != 0)
goto out;
getmeta = 1;
change = 1;
/* Reapply the change as specified. */
change = 1;
/* Undo the already applied change. */
} else {
change = 0;
grow = 0;
}
if (change) {
if (redo)
else
}
}
goto out;
ret = 0;
}
/*
* __ham_newpgno_recover --
* This log message is used when allocating or deleting an overflow
* page. It takes care of modifying the meta data.
*
* PUBLIC: int __ham_newpgno_recover
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/
int
int redo;
void *info;
{
getmeta = 0;
if (ret != 0)
goto out;
getmeta = 1;
/*
* There are two phases to the recovery here. First we need
* to update the meta data; then we need to update the page.
* We'll do the meta-data first.
*/
change = 0;
/* Need to redo an allocation or undo a deletion. */
change = 1;
/* Need to redo a deletion */
change = 1;
/* undo an allocation. */
else {
}
change = 1;
}
if (change) {
}
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist. That
* is equivalent to having a pagelsn of 0, so we
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
goto done;
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
change = 0;
/* Need to redo an allocation. */
change = 1;
/* Undoing a delete. */
change = 1;
/* Need to redo a deletion or undo an allocation. */
change = 1;
}
if (change)
goto out;
ret = 0;
}
/*
* __ham_splitmeta_recover --
* This is the meta-data part of the split. Records the new and old
*
* PUBLIC: int __ham_splitmeta_recover
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/
int
int redo;
void *info;
{
getmeta = 0;
if (ret != 0)
goto out;
getmeta = 1;
/*
* There are two phases to the recovery here. First we need
* to update the meta data; then we need to update the page.
* We'll do the meta-data first.
*/
change = 0;
/* Need to redo the split information. */
}
}
change = 1;
/* Need to undo the split information. */
change = 1;
}
if (change) {
}
ret = 0;
}
/*
* __ham_splitdata_recover --
*
* PUBLIC: int __ham_splitdata_recover
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/
int
int redo;
void *info;
{
getmeta = 0;
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist. That
* is equivalent to having a pagelsn of 0, so we
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
goto done;
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
if (ret != 0)
goto out;
getmeta = 1;
/*
* There are two types of log messages here, one for the old page
* and one for the new pages created. The original image in the
* SPLITOLD record is used for undo. The image in the SPLITNEW
* is used for redo. We should never have a case where there is
* a redo operation and the SPLITOLD record is on disk, but not
* the SPLITNEW record. Therefore, we only have work to do when
* redo NEW messages and undo OLD messages, but we have to update
* LSNs in both cases.
*/
change = 0;
/* Need to redo the split described. */
change = 1;
/* Put back the old image. */
} else
change = 1;
}
goto out;
ret = 0;
}
/*
* __ham_ovfl_recover --
* This message is generated when we initialize a set of overflow pages.
*
* PUBLIC: int __ham_ovfl_recover
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/
int
int redo;
void *info;
{
getmeta = 0;
if (ret != 0)
goto out;
getmeta = 1;
/* Redo the allocation. */
}
ret = 0;
if (!redo) {
ret = 0;
continue;
}
goto out;
}
0, P_HASH);
} else if (!redo) {
} else
if (ret)
goto out;
}
ret = 0;
}
/*
* __ham_copypage_recover --
* Recovery function for copypage.
*
* PUBLIC: int __ham_copypage_recover
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
*/
int
int redo;
void *info;
{
getmeta = 0;
if (ret != 0)
goto out;
getmeta = 1;
modified = 0;
/* This is the bucket page. */
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist. That
* is equivalent to having a pagelsn of 0, so we
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
ret = 0;
goto donext;
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
/* Need to redo update described. */
modified = 1;
/* Need to undo update described. */
modified = 1;
}
goto out;
/* Now fix up the "next" page. */
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist. That
* is equivalent to having a pagelsn of 0, so we
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
ret = 0;
goto do_nn;
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
/* There is nothing to do in the REDO case; only UNDO. */
/* Need to undo update described. */
modified = 1;
}
goto out;
/* Now fix up the next's next page. */
goto done;
if (ret != 0)
if (!redo) {
/*
* We are undoing and the page doesn't exist. That
* is equivalent to having a pagelsn of 0, so we
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
goto done;
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
/* Need to redo update described. */
modified = 1;
/* Need to undo update described. */
modified = 1;
}
goto out;
ret = 0;
}