]>
Commit | Line | Data |
---|---|---|
92f1da4d UD |
1 | /*- |
2 | * See the file LICENSE for redistribution information. | |
3 | * | |
4 | * Copyright (c) 1996, 1997 | |
5 | * Sleepycat Software. All rights reserved. | |
6 | */ | |
7 | #include "config.h" | |
8 | ||
9 | #ifndef lint | |
cc3fa755 | 10 | static const char sccsid[] = "@(#)mp_fput.c 10.14 (Sleepycat) 10/5/97"; |
92f1da4d UD |
11 | #endif /* not lint */ |
12 | ||
13 | #ifndef NO_SYSTEM_INCLUDES | |
14 | #include <sys/types.h> | |
15 | ||
16 | #include <errno.h> | |
17 | #include <stdlib.h> | |
18 | #endif | |
19 | ||
20 | #include "db_int.h" | |
21 | #include "shqueue.h" | |
22 | #include "db_shash.h" | |
23 | #include "mp.h" | |
24 | #include "common_ext.h" | |
25 | ||
26 | /* | |
27 | * memp_fput -- | |
28 | * Mpool file put function. | |
29 | */ | |
30 | int | |
31 | memp_fput(dbmfp, pgaddr, flags) | |
32 | DB_MPOOLFILE *dbmfp; | |
33 | void *pgaddr; | |
a5a0310d | 34 | int flags; |
92f1da4d UD |
35 | { |
36 | BH *bhp; | |
37 | DB_MPOOL *dbmp; | |
cc3fa755 | 38 | MPOOL *mp; |
92f1da4d UD |
39 | MPOOLFILE *mfp; |
40 | int wrote, ret; | |
41 | ||
42 | dbmp = dbmfp->dbmp; | |
cc3fa755 | 43 | mp = dbmp->mp; |
92f1da4d UD |
44 | |
45 | /* Validate arguments. */ | |
46 | if (flags) { | |
47 | if ((ret = __db_fchk(dbmp->dbenv, "memp_fput", flags, | |
48 | DB_MPOOL_CLEAN | DB_MPOOL_DIRTY | DB_MPOOL_DISCARD)) != 0) | |
49 | return (ret); | |
50 | if ((ret = __db_fcchk(dbmp->dbenv, "memp_fput", | |
51 | flags, DB_MPOOL_CLEAN, DB_MPOOL_DIRTY)) != 0) | |
52 | return (ret); | |
53 | ||
54 | if (LF_ISSET(DB_MPOOL_DIRTY) && F_ISSET(dbmfp, MP_READONLY)) { | |
55 | __db_err(dbmp->dbenv, | |
56 | "%s: dirty flag set for readonly file page", | |
57 | dbmfp->path); | |
58 | return (EACCES); | |
59 | } | |
60 | } | |
61 | ||
62 | /* Decrement the pinned reference count. */ | |
a5a0310d | 63 | LOCKHANDLE(dbmp, dbmfp->mutexp); |
92f1da4d UD |
64 | if (dbmfp->pinref == 0) |
65 | __db_err(dbmp->dbenv, | |
66 | "%s: put: more blocks returned than retrieved", | |
67 | dbmfp->path); | |
68 | else | |
69 | --dbmfp->pinref; | |
a5a0310d | 70 | UNLOCKHANDLE(dbmp, dbmfp->mutexp); |
92f1da4d UD |
71 | |
72 | /* | |
73 | * If we're mapping the file, there's nothing to do. Because we can | |
74 | * quit mapping at any time, we have to check on each buffer to see | |
75 | * if it's in the map region. | |
76 | */ | |
77 | if (dbmfp->addr != NULL && pgaddr >= dbmfp->addr && | |
78 | (u_int8_t *)pgaddr <= (u_int8_t *)dbmfp->addr + dbmfp->len) | |
79 | return (0); | |
80 | ||
81 | /* Convert the page address to a buffer header. */ | |
82 | bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf)); | |
83 | ||
84 | LOCKREGION(dbmp); | |
85 | ||
86 | /* Set/clear the page bits. */ | |
cc3fa755 UD |
87 | if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) { |
88 | ++mp->stat.st_page_clean; | |
89 | --mp->stat.st_page_dirty; | |
92f1da4d | 90 | F_CLR(bhp, BH_DIRTY); |
cc3fa755 UD |
91 | } |
92 | if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) { | |
93 | --mp->stat.st_page_clean; | |
94 | ++mp->stat.st_page_dirty; | |
92f1da4d | 95 | F_SET(bhp, BH_DIRTY); |
cc3fa755 | 96 | } |
92f1da4d UD |
97 | if (LF_ISSET(DB_MPOOL_DISCARD)) |
98 | F_SET(bhp, BH_DISCARD); | |
99 | ||
100 | /* | |
101 | * If more than one reference to the page, we're done. Ignore discard | |
102 | * flags (for now) and leave it at its position in the LRU chain. The | |
103 | * rest gets done at last reference close. | |
104 | */ | |
105 | #ifdef DEBUG | |
106 | if (bhp->ref == 0) { | |
107 | __db_err(dbmp->dbenv, | |
108 | "Internal error: bhp->ref on page %lu went negative.", | |
109 | (u_long)bhp->pgno); | |
110 | abort(); | |
111 | } | |
112 | #endif | |
113 | if (--bhp->ref > 0) { | |
114 | UNLOCKREGION(dbmp); | |
115 | return (0); | |
116 | } | |
117 | ||
118 | /* Move the buffer to the head/tail of the LRU chain. */ | |
cc3fa755 | 119 | SH_TAILQ_REMOVE(&mp->bhq, bhp, q, __bh); |
92f1da4d | 120 | if (F_ISSET(bhp, BH_DISCARD)) |
cc3fa755 | 121 | SH_TAILQ_INSERT_HEAD(&mp->bhq, bhp, q, __bh); |
92f1da4d | 122 | else |
cc3fa755 | 123 | SH_TAILQ_INSERT_TAIL(&mp->bhq, bhp, q); |
92f1da4d UD |
124 | |
125 | /* | |
126 | * If this buffer is scheduled for writing because of a checkpoint, | |
127 | * write it now. If we can't write it, set a flag so that the next | |
128 | * time the memp_sync function is called we try writing it there, | |
129 | * as the checkpoint application better be able to write all of the | |
130 | * files. | |
131 | */ | |
132 | if (F_ISSET(bhp, BH_WRITE)) | |
133 | if (F_ISSET(bhp, BH_DIRTY)) { | |
134 | if (__memp_bhwrite(dbmp, | |
135 | dbmfp->mfp, bhp, NULL, &wrote) != 0 || !wrote) | |
cc3fa755 | 136 | F_SET(mp, MP_LSN_RETRY); |
92f1da4d UD |
137 | } else { |
138 | F_CLR(bhp, BH_WRITE); | |
139 | ||
cc3fa755 | 140 | mfp = R_ADDR(dbmp, bhp->mf_offset); |
92f1da4d UD |
141 | --mfp->lsn_cnt; |
142 | ||
cc3fa755 | 143 | --mp->lsn_cnt; |
92f1da4d UD |
144 | } |
145 | ||
146 | UNLOCKREGION(dbmp); | |
147 | return (0); | |
148 | } |