2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
8 * Copyright (c) 1990, 1993, 1994, 1995, 1996
9 * Keith Bostic. All rights reserved.
12 * Copyright (c) 1990, 1993, 1994, 1995
13 * The Regents of the University of California. All rights reserved.
15 * This code is derived from software contributed to Berkeley by
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 * 3. All advertising materials mentioning features or use of this software
27 * must display the following acknowledgement:
28 * This product includes software developed by the University of
29 * California, Berkeley and its contributors.
30 * 4. Neither the name of the University nor the names of its contributors
31 * may be used to endorse or promote products derived from this software
32 * without specific prior written permission.
34 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 static const char sccsid
[] = "@(#)bt_page.c 10.12 (Sleepycat) 5/6/98";
53 #ifndef NO_SYSTEM_INCLUDES
54 #include <sys/types.h>
66 * Get a new page, preferably from the freelist.
68 * PUBLIC: int __bam_new __P((DB *, u_int32_t, PAGE **));
71 __bam_new(dbp
, type
, pagepp
)
84 metalock
= LOCK_INVALID
;
87 if ((ret
= __bam_lget(dbp
, 0, pgno
, DB_LOCK_WRITE
, &metalock
)) != 0)
89 if ((ret
= __bam_pget(dbp
, (PAGE
**)&meta
, &pgno
, 0)) != 0)
92 if (meta
->free
== PGNO_INVALID
) {
93 if ((ret
= __bam_pget(dbp
, &h
, &pgno
, DB_MPOOL_NEW
)) != 0)
99 if ((ret
= __bam_pget(dbp
, &h
, &pgno
, 0)) != 0)
101 meta
->free
= h
->next_pgno
;
104 /* Log the change. */
105 if (DB_LOGGING(dbp
)) {
106 if ((ret
= __bam_pg_alloc_log(dbp
->dbenv
->lg_info
, dbp
->txn
,
107 &meta
->lsn
, 0, dbp
->log_fileid
, &meta
->lsn
, &h
->lsn
,
108 h
->pgno
, (u_int32_t
)type
, meta
->free
)) != 0)
113 (void)memp_fput(dbp
->mpf
, (PAGE
*)meta
, DB_MPOOL_DIRTY
);
114 (void)__BT_TLPUT(dbp
, metalock
);
116 P_INIT(h
, dbp
->pgsize
, h
->pgno
, PGNO_INVALID
, PGNO_INVALID
, 0, type
);
121 (void)memp_fput(dbp
->mpf
, h
, 0);
123 (void)memp_fput(dbp
->mpf
, meta
, 0);
124 if (metalock
!= LOCK_INVALID
)
125 (void)__BT_TLPUT(dbp
, metalock
);
131 * Add a page to the head of the freelist.
133 * PUBLIC: int __bam_free __P((DB *, PAGE *));
144 u_int32_t dirty_flag
;
148 * Retrieve the metadata page and insert the page at the head of
149 * the free list. If either the lock get or page get routines
150 * fail, then we need to put the page with which we were called
151 * back because our caller assumes we take care of it.
154 pgno
= PGNO_METADATA
;
155 if ((ret
= __bam_lget(dbp
, 0, pgno
, DB_LOCK_WRITE
, &metalock
)) != 0)
157 if ((ret
= __bam_pget(dbp
, (PAGE
**)&meta
, &pgno
, 0)) != 0) {
158 (void)__BT_TLPUT(dbp
, metalock
);
162 /* Log the change. */
163 if (DB_LOGGING(dbp
)) {
164 memset(&ldbt
, 0, sizeof(ldbt
));
166 ldbt
.size
= P_OVERHEAD
;
167 if ((ret
= __bam_pg_free_log(dbp
->dbenv
->lg_info
,
168 dbp
->txn
, &meta
->lsn
, 0, dbp
->log_fileid
, h
->pgno
,
169 &meta
->lsn
, &ldbt
, meta
->free
)) != 0) {
170 (void)memp_fput(dbp
->mpf
, (PAGE
*)meta
, 0);
171 (void)__BT_TLPUT(dbp
, metalock
);
178 * The page should have nothing interesting on it, re-initialize it,
179 * leaving only the page number and the LSN.
182 { db_pgno_t __pgno
; DB_LSN __lsn
;
185 memset(h
, 0xff, dbp
->pgsize
);
190 P_INIT(h
, dbp
->pgsize
, h
->pgno
, PGNO_INVALID
, meta
->free
, 0, P_INVALID
);
192 /* Link the page on the metadata free list. */
193 meta
->free
= h
->pgno
;
195 /* Discard the metadata page. */
196 ret
= memp_fput(dbp
->mpf
, (PAGE
*)meta
, DB_MPOOL_DIRTY
);
197 if ((t_ret
= __BT_TLPUT(dbp
, metalock
)) != 0)
200 /* Discard the caller's page reference. */
201 dirty_flag
= DB_MPOOL_DIRTY
;
202 err
: if ((t_ret
= memp_fput(dbp
->mpf
, h
, dirty_flag
)) != 0 && ret
== 0)
207 * We have to unlock the caller's page in the caller!
215 * Print out the list of currently held locks.
217 * PUBLIC: int __bam_lt __P((DB *));
225 if (F_ISSET(dbp
, DB_AM_LOCKING
)) {
226 req
.op
= DB_LOCK_DUMP
;
227 lock_vec(dbp
->dbenv
->lk_info
, dbp
->locker
, 0, &req
, 1, NULL
);
235 * The standard lock get call.
237 * PUBLIC: int __bam_lget __P((DB *, int, db_pgno_t, db_lockmode_t, DB_LOCK *));
240 __bam_lget(dbp
, do_couple
, pgno
, mode
, lockp
)
247 DB_LOCKREQ couple
[2];
251 if (!F_ISSET(dbp
, DB_AM_LOCKING
)) {
252 *lockp
= LOCK_INVALID
;
256 locker
= dbp
->txn
== NULL
? dbp
->locker
: dbp
->txn
->txnid
;
257 dbp
->lock
.pgno
= pgno
;
260 * If the object not currently locked, acquire the lock and return,
261 * otherwise, lock couple. If we fail and it's not a system error,
265 couple
[0].op
= DB_LOCK_GET
;
266 couple
[0].obj
= &dbp
->lock_dbt
;
267 couple
[0].mode
= mode
;
268 couple
[1].op
= DB_LOCK_PUT
;
269 couple
[1].lock
= *lockp
;
271 ret
= lock_vec(dbp
->dbenv
->lk_info
, locker
, 0, couple
, 2, NULL
);
273 /* If we fail, discard the lock we held. */
274 __bam_lput(dbp
, *lockp
);
276 return (ret
< 0 ? EAGAIN
: ret
);
278 *lockp
= couple
[0].lock
;
280 ret
= lock_get(dbp
->dbenv
->lk_info
,
281 locker
, 0, &dbp
->lock_dbt
, mode
, lockp
);
282 return (ret
< 0 ? EAGAIN
: ret
);
289 * The standard lock put call.
291 * PUBLIC: int __bam_lput __P((DB *, DB_LOCK));
294 __bam_lput(dbp
, lock
)
298 return (__BT_LPUT(dbp
, lock
));
303 * The standard page get call.
305 * PUBLIC: int __bam_pget __P((DB *, PAGE **, db_pgno_t *, u_int32_t));
308 __bam_pget(dbp
, hp
, pgnop
, mpool_flags
)
312 u_int32_t mpool_flags
;
314 return (memp_fget((dbp
)->mpf
,
315 pgnop
, mpool_flags
, hp
) == 0 ? 0 : __db_pgerr(dbp
, *pgnop
));