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.24 (Sleepycat) 9/27/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
)
45 /* Validate arguments. */
47 if ((ret
= __db_fchk(dbmp
->dbenv
, "memp_fput", flags
,
48 DB_MPOOL_CLEAN
| DB_MPOOL_DIRTY
| DB_MPOOL_DISCARD
)) != 0)
50 if ((ret
= __db_fcchk(dbmp
->dbenv
, "memp_fput",
51 flags
, DB_MPOOL_CLEAN
, DB_MPOOL_DIRTY
)) != 0)
54 if (LF_ISSET(DB_MPOOL_DIRTY
) && F_ISSET(dbmfp
, MP_READONLY
)) {
56 "%s: dirty flag set for readonly file page",
64 /* Decrement the pinned reference count. */
65 if (dbmfp
->pinref
== 0)
67 "%s: put: more blocks returned than retrieved",
73 * If we're mapping the file, there's nothing to do. Because we can
74 * stop mapping the file at any time, we have to check on each buffer
75 * to see if the address we gave the application was part of the map
78 if (dbmfp
->addr
!= NULL
&& pgaddr
>= dbmfp
->addr
&&
79 (u_int8_t
*)pgaddr
<= (u_int8_t
*)dbmfp
->addr
+ dbmfp
->len
) {
84 /* Convert the page address to a buffer header. */
85 bhp
= (BH
*)((u_int8_t
*)pgaddr
- SSZA(BH
, buf
));
87 /* Set/clear the page bits. */
88 if (LF_ISSET(DB_MPOOL_CLEAN
) && F_ISSET(bhp
, BH_DIRTY
)) {
89 ++mp
->stat
.st_page_clean
;
90 --mp
->stat
.st_page_dirty
;
93 if (LF_ISSET(DB_MPOOL_DIRTY
) && !F_ISSET(bhp
, BH_DIRTY
)) {
94 --mp
->stat
.st_page_clean
;
95 ++mp
->stat
.st_page_dirty
;
98 if (LF_ISSET(DB_MPOOL_DISCARD
))
99 F_SET(bhp
, BH_DISCARD
);
102 * Check for a reference count going to zero. This can happen if the
103 * application returns a page twice.
106 __db_err(dbmp
->dbenv
, "%s: page %lu: unpinned page returned",
107 __memp_fn(dbmfp
), (u_long
)bhp
->pgno
);
113 * If more than one reference to the page, we're done. Ignore the
114 * discard flags (for now) and leave it at its position in the LRU
115 * chain. The rest gets done at last reference close.
117 if (--bhp
->ref
> 0) {
122 /* Move the buffer to the head/tail of the LRU chain. */
123 SH_TAILQ_REMOVE(&mp
->bhq
, bhp
, q
, __bh
);
124 if (F_ISSET(bhp
, BH_DISCARD
))
125 SH_TAILQ_INSERT_HEAD(&mp
->bhq
, bhp
, q
, __bh
);
127 SH_TAILQ_INSERT_TAIL(&mp
->bhq
, bhp
, q
);
130 * If this buffer is scheduled for writing because of a checkpoint, we
131 * need to write it (if we marked it dirty), or update the checkpoint
132 * counters (if we didn't mark it dirty). If we try to write it and
133 * can't, that's not necessarily an error, but set a flag so that the
134 * next time the memp_sync function runs we try writing it there, as
135 * the checkpoint application better be able to write all of the files.
137 if (F_ISSET(bhp
, BH_WRITE
))
138 if (F_ISSET(bhp
, BH_DIRTY
)) {
139 if (__memp_bhwrite(dbmp
,
140 dbmfp
->mfp
, bhp
, NULL
, &wrote
) != 0 || !wrote
)
141 F_SET(mp
, MP_LSN_RETRY
);
143 F_CLR(bhp
, BH_WRITE
);
145 --dbmfp
->mfp
->lsn_cnt
;