2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
10 static const char sccsid
[] = "@(#)mp_fput.c 10.22 (Sleepycat) 4/26/98";
13 #ifndef NO_SYSTEM_INCLUDES
14 #include <sys/types.h>
23 #include "common_ext.h"
27 * Mpool file put function.
30 memp_fput(dbmfp
, pgaddr
, flags
)
43 /* Validate arguments. */
45 if ((ret
= __db_fchk(dbmp
->dbenv
, "memp_fput", flags
,
46 DB_MPOOL_CLEAN
| DB_MPOOL_DIRTY
| DB_MPOOL_DISCARD
)) != 0)
48 if ((ret
= __db_fcchk(dbmp
->dbenv
, "memp_fput",
49 flags
, DB_MPOOL_CLEAN
, DB_MPOOL_DIRTY
)) != 0)
52 if (LF_ISSET(DB_MPOOL_DIRTY
) && F_ISSET(dbmfp
, MP_READONLY
)) {
54 "%s: dirty flag set for readonly file page",
60 /* Decrement the pinned reference count. */
61 LOCKHANDLE(dbmp
, dbmfp
->mutexp
);
62 if (dbmfp
->pinref
== 0)
64 "%s: put: more blocks returned than retrieved",
68 UNLOCKHANDLE(dbmp
, dbmfp
->mutexp
);
71 * If we're mapping the file, there's nothing to do. Because we can
72 * stop mapping the file at any time, we have to check on each buffer
73 * to see if the address we gave the application was part of the map
76 if (dbmfp
->addr
!= NULL
&& pgaddr
>= dbmfp
->addr
&&
77 (u_int8_t
*)pgaddr
<= (u_int8_t
*)dbmfp
->addr
+ dbmfp
->len
)
80 /* Convert the page address to a buffer header. */
81 bhp
= (BH
*)((u_int8_t
*)pgaddr
- SSZA(BH
, buf
));
85 /* Set/clear the page bits. */
86 if (LF_ISSET(DB_MPOOL_CLEAN
) && F_ISSET(bhp
, BH_DIRTY
)) {
87 ++mp
->stat
.st_page_clean
;
88 --mp
->stat
.st_page_dirty
;
91 if (LF_ISSET(DB_MPOOL_DIRTY
) && !F_ISSET(bhp
, BH_DIRTY
)) {
92 --mp
->stat
.st_page_clean
;
93 ++mp
->stat
.st_page_dirty
;
96 if (LF_ISSET(DB_MPOOL_DISCARD
))
97 F_SET(bhp
, BH_DISCARD
);
100 * Check for a reference count going to zero. This can happen if the
101 * application returns a page twice.
104 __db_err(dbmp
->dbenv
, "%s: page %lu: unpinned page returned",
105 __memp_fn(dbmfp
), (u_long
)bhp
->pgno
);
111 * If more than one reference to the page, we're done. Ignore the
112 * discard flags (for now) and leave it at its position in the LRU
113 * chain. The rest gets done at last reference close.
115 if (--bhp
->ref
> 0) {
121 * If this buffer is scheduled for writing because of a checkpoint, we
122 * need to write it (if we marked it dirty), or update the checkpoint
123 * counters (if we didn't mark it dirty). If we try to write it and
124 * can't, that's not necessarily an error, but set a flag so that the
125 * next time the memp_sync function runs we try writing it there, as
126 * the checkpoint application better be able to write all of the files.
128 if (F_ISSET(bhp
, BH_WRITE
)) {
129 if (F_ISSET(bhp
, BH_DIRTY
)) {
130 if (__memp_bhwrite(dbmp
,
131 dbmfp
->mfp
, bhp
, NULL
, &wrote
) != 0 || !wrote
)
132 F_SET(mp
, MP_LSN_RETRY
);
134 F_CLR(bhp
, BH_WRITE
);
136 --dbmfp
->mfp
->lsn_cnt
;
141 /* Move the buffer to the head/tail of the LRU chain. */
142 SH_TAILQ_REMOVE(&mp
->bhq
, bhp
, q
, __bh
);
143 if (F_ISSET(bhp
, BH_DISCARD
))
144 SH_TAILQ_INSERT_HEAD(&mp
->bhq
, bhp
, q
, __bh
);
146 SH_TAILQ_INSERT_TAIL(&mp
->bhq
, bhp
, q
);