]>
git.ipfire.org Git - thirdparty/glibc.git/blob - db2/log/log_get.c
2d1512c6b982409c2d37e941d40859ac192f2574
2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997
5 * Sleepycat Software. All rights reserved.
10 static const char sccsid
[] = "@(#)log_get.c 10.22 (Sleepycat) 11/22/97";
13 #ifndef NO_SYSTEM_INCLUDES
14 #include <sys/types.h>
28 #include "common_ext.h"
35 log_get(dblp
, alsn
, dbt
, flags
)
44 /* Validate arguments. */
45 #define OKFLAGS (DB_CHECKPOINT | \
46 DB_CURRENT | DB_FIRST | DB_LAST | DB_NEXT | DB_PREV | DB_SET)
47 if ((ret
= __db_fchk(dblp
->dbenv
, "log_get", flags
, OKFLAGS
)) != 0)
59 return (__db_ferr(dblp
->dbenv
, "log_get", 1));
62 if (F_ISSET(dblp
, DB_AM_THREAD
)) {
63 if (LF_ISSET(DB_NEXT
| DB_PREV
| DB_CURRENT
))
64 return (__db_ferr(dblp
->dbenv
, "log_get", 1));
65 if (!F_ISSET(dbt
, DB_DBT_USERMEM
| DB_DBT_MALLOC
))
66 return (__db_ferr(dblp
->dbenv
, "threaded data", 1));
74 * If we get one of the log's header records, repeat the operation.
75 * This assumes that applications don't ever request the log header
76 * records by LSN, but that seems reasonable to me.
78 ret
= __log_get(dblp
, alsn
, dbt
, flags
, 0);
79 if (ret
== 0 && alsn
->offset
== 0) {
88 ret
= __log_get(dblp
, alsn
, dbt
, flags
, 0);
91 UNLOCK_LOGREGION(dblp
);
98 * Get a log record; internal version.
100 * PUBLIC: int __log_get __P((DB_LOG *, DB_LSN *, DBT *, int, int));
103 __log_get(dblp
, alsn
, dbt
, flags
, silent
)
120 fail
= np
= tbuf
= NULL
;
125 nlsn
= dblp
->lp
->c_lsn
;
126 if (IS_ZERO_LSN(nlsn
)) {
127 __db_err(dblp
->dbenv
,
128 "log_get: unable to find checkpoint record: no checkpoint set.");
133 case DB_NEXT
: /* Next log record. */
134 if (!IS_ZERO_LSN(nlsn
)) {
135 /* Increment the cursor by the cursor record size. */
136 nlsn
.offset
+= dblp
->c_len
;
140 case DB_FIRST
: /* Find the first log record. */
142 * Find any log file. Note, we may have only entered records
143 * in the buffer, and not yet written a log file.
145 if ((ret
= __log_find(dblp
, &cnt
)) != 0) {
146 __db_err(dblp
->dbenv
,
147 "log_get: unable to find the first record: no log files found.");
151 /* If there's anything in the buffer, it belongs to file 1. */
155 /* Now go backwards to find the smallest one. */
156 for (; cnt
> 1; --cnt
)
157 if (__log_valid(dblp
, NULL
, cnt
) != 0) {
164 case DB_CURRENT
: /* Current log record. */
166 case DB_PREV
: /* Previous log record. */
167 if (!IS_ZERO_LSN(nlsn
)) {
168 /* If at start-of-file, move to the previous file. */
169 if (nlsn
.offset
== 0) {
170 if (nlsn
.file
== 1 ||
171 __log_valid(dblp
, NULL
, nlsn
.file
- 1) != 0)
172 return (DB_NOTFOUND
);
175 nlsn
.offset
= dblp
->c_off
;
177 nlsn
.offset
= dblp
->c_off
;
181 case DB_LAST
: /* Last log record. */
182 nlsn
.file
= lp
->lsn
.file
;
183 nlsn
.offset
= lp
->lsn
.offset
- lp
->len
;
185 case DB_SET
: /* Set log record. */
191 /* Return 1 if the request is past end-of-file. */
192 if (nlsn
.file
> lp
->lsn
.file
||
193 (nlsn
.file
== lp
->lsn
.file
&& nlsn
.offset
>= lp
->lsn
.offset
))
194 return (DB_NOTFOUND
);
196 /* If we've switched files, discard the current fd. */
197 if (dblp
->c_lsn
.file
!= nlsn
.file
&& dblp
->c_fd
!= -1) {
198 (void)__db_close(dblp
->c_fd
);
202 /* If the entire record is in the in-memory buffer, copy it out. */
203 if (nlsn
.file
== lp
->lsn
.file
&& nlsn
.offset
>= lp
->w_off
) {
204 /* Copy the header. */
205 p
= lp
->buf
+ (nlsn
.offset
- lp
->w_off
);
206 memcpy(&hdr
, p
, sizeof(HDR
));
208 /* Copy the record. */
209 len
= hdr
.len
- sizeof(HDR
);
210 if ((ret
= __db_retcopy(dbt
, (u_int8_t
*)p
+ sizeof(HDR
),
211 len
, &dblp
->c_dbt
.data
, &dblp
->c_dbt
.ulen
, NULL
)) != 0)
216 /* Acquire a file descriptor. */
217 if (dblp
->c_fd
== -1) {
218 if ((ret
= __log_name(dblp
, nlsn
.file
, &np
)) != 0)
220 if ((ret
= __db_open(np
, DB_RDONLY
| DB_SEQUENTIAL
,
221 DB_RDONLY
| DB_SEQUENTIAL
, 0, &dblp
->c_fd
)) != 0) {
229 /* Seek to the header offset and read the header. */
230 if ((ret
= __db_seek(dblp
->c_fd
, 0, 0, nlsn
.offset
, SEEK_SET
)) != 0) {
234 if ((ret
= __db_read(dblp
->c_fd
, &hdr
, sizeof(HDR
), &nr
)) != 0) {
238 if (nr
== sizeof(HDR
))
241 /* If read returns EOF, try the next file. */
243 if (flags
!= DB_NEXT
|| nlsn
.file
== lp
->lsn
.file
)
246 /* Move to the next file. */
253 * If read returns a short count the rest of the record has
254 * to be in the in-memory buffer.
256 if (lp
->b_off
< sizeof(HDR
) - nr
)
259 /* Get the rest of the header from the in-memory buffer. */
260 memcpy((u_int8_t
*)&hdr
+ nr
, lp
->buf
, sizeof(HDR
) - nr
);
261 shortp
= lp
->buf
+ (sizeof(HDR
) - nr
);
265 * Check for buffers of 0's, that's what we usually see during
266 * recovery, although it's certainly not something on which we
269 if (hdr
.len
<= sizeof(HDR
))
271 len
= hdr
.len
- sizeof(HDR
);
273 /* If we've already moved to the in-memory buffer, fill from there. */
274 if (shortp
!= NULL
) {
275 if (lp
->b_off
< ((u_int8_t
*)shortp
- lp
->buf
) + len
)
277 if ((ret
= __db_retcopy(dbt
, shortp
, len
,
278 &dblp
->c_dbt
.data
, &dblp
->c_dbt
.ulen
, NULL
)) != 0)
283 /* Allocate temporary memory to hold the record. */
284 if ((tbuf
= (char *)__db_malloc(len
)) == NULL
) {
290 * Read the record into the buffer. If read returns a short count,
291 * there was an error or the rest of the record is in the in-memory
292 * buffer. Note, the information may be garbage if we're in recovery,
293 * so don't read past the end of the buffer's memory.
295 if ((ret
= __db_read(dblp
->c_fd
, tbuf
, len
, &nr
)) != 0) {
299 if (len
- nr
> sizeof(lp
->buf
))
301 if (nr
!= (ssize_t
)len
) {
302 if (lp
->b_off
< len
- nr
)
305 /* Get the rest of the record from the in-memory buffer. */
306 memcpy((u_int8_t
*)tbuf
+ nr
, lp
->buf
, len
- nr
);
309 /* Copy the record into the user's DBT. */
310 if ((ret
= __db_retcopy(dbt
, tbuf
, len
,
311 &dblp
->c_dbt
.data
, &dblp
->c_dbt
.ulen
, NULL
)) != 0)
316 cksum
: if (hdr
.cksum
!= __ham_func4(dbt
->data
, dbt
->size
)) {
318 __db_err(dblp
->dbenv
, "log_get: checksum mismatch");
322 /* Update the cursor and the return lsn. */
323 dblp
->c_off
= hdr
.prev
;
324 dblp
->c_len
= hdr
.len
;
325 dblp
->c_lsn
= *alsn
= nlsn
;
330 * This is the catchall -- for some reason we didn't find enough
331 * information or it wasn't reasonable information, and it wasn't
332 * because a system call failed.
339 __db_err(dblp
->dbenv
, "log_get: %s", strerror(ret
));
341 __db_err(dblp
->dbenv
,
342 "log_get: %s: %s", fail
, strerror(ret
));
343 err2
: if (np
!= NULL
)