Add BSD license file
[platform/upstream/db4.git] / log / log.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996-2009 Oracle.  All rights reserved.
5  *
6  * $Id$
7  */
8
9 #include "db_config.h"
10
11 #include "db_int.h"
12 #include "dbinc/crypto.h"
13 #include "dbinc/hmac.h"
14 #include "dbinc/log.h"
15 #include "dbinc/txn.h"
16
17 static int      __log_init __P((ENV *, DB_LOG *));
18 static int      __log_recover __P((DB_LOG *));
19 static size_t   __log_region_size __P((ENV *));
20
21 /*
22  * __log_open --
23  *      Internal version of log_open: only called from ENV->open.
24  *
25  * PUBLIC: int __log_open __P((ENV *, int));
26  */
27 int
28 __log_open(env, create_ok)
29         ENV *env;
30         int create_ok;
31 {
32         DB_ENV *dbenv;
33         DB_LOG *dblp;
34         LOG *lp;
35         u_int8_t *bulk;
36         int region_locked, ret;
37
38         dbenv = env->dbenv;
39         region_locked = 0;
40
41         /* Create/initialize the DB_LOG structure. */
42         if ((ret = __os_calloc(env, 1, sizeof(DB_LOG), &dblp)) != 0)
43                 return (ret);
44         dblp->env = env;
45
46         /* Set the default buffer size, if not otherwise configured. */
47         if (dbenv->lg_bsize == 0)
48                 dbenv->lg_bsize = FLD_ISSET(dbenv->lg_flags, DB_LOG_IN_MEMORY) ?
49                     LG_BSIZE_INMEM : LG_BSIZE_DEFAULT;
50
51         /* Join/create the log region. */
52         dblp->reginfo.env = env;
53         dblp->reginfo.type = REGION_TYPE_LOG;
54         dblp->reginfo.id = INVALID_REGION_ID;
55         dblp->reginfo.flags = REGION_JOIN_OK;
56
57         if (create_ok)
58                 F_SET(&dblp->reginfo, REGION_CREATE_OK);
59         if ((ret = __env_region_attach(
60             env, &dblp->reginfo, __log_region_size(env))) != 0)
61                 goto err;
62
63         /* If we created the region, initialize it. */
64         if (F_ISSET(&dblp->reginfo, REGION_CREATE))
65                 if ((ret = __log_init(env, dblp)) != 0)
66                         goto err;
67
68         /* Set the local addresses. */
69         lp = dblp->reginfo.primary =
70             R_ADDR(&dblp->reginfo, dblp->reginfo.rp->primary);
71         dblp->bufp = R_ADDR(&dblp->reginfo, lp->buffer_off);
72
73         /*
74          * If the region is threaded, we have to lock the DBREG list, and we
75          * need to allocate a mutex for that purpose.
76          */
77         if ((ret = __mutex_alloc(env,
78             MTX_LOG_REGION, DB_MUTEX_PROCESS_ONLY, &dblp->mtx_dbreg)) != 0)
79                 goto err;
80
81         /*
82          * Set the handle -- we may be about to run recovery, which allocates
83          * log cursors.  Log cursors require logging be already configured,
84          * and the handle being set is what demonstrates that.
85          *
86          * If we created the region, run recovery.  If that fails, make sure
87          * we reset the log handle before cleaning up, otherwise we will try
88          * and clean up again in the mainline ENV initialization code.
89          */
90         env->lg_handle = dblp;
91
92         if (F_ISSET(&dblp->reginfo, REGION_CREATE)) {
93                 /*
94                  * We first take the log file size from the environment, if
95                  * specified.  If that wasn't set, default it.  Regardless,
96                  * recovery may set it from the persistent information in a
97                  * log file header.
98                  */
99                 if (lp->log_size == 0)
100                         lp->log_size =
101                             FLD_ISSET(dbenv->lg_flags, DB_LOG_IN_MEMORY) ?
102                             LG_MAX_INMEM : LG_MAX_DEFAULT;
103
104                 if ((ret = __log_recover(dblp)) != 0)
105                         goto err;
106
107                 /*
108                  * If the next log file size hasn't been set yet, default it
109                  * to the current log file size.
110                  */
111                 if (lp->log_nsize == 0)
112                         lp->log_nsize = lp->log_size;
113
114                 /*
115                  * If we haven't written any log files, write the first one
116                  * so that checkpoint gets a valid ckp_lsn value.
117                  */
118                 if (IS_INIT_LSN(lp->lsn) &&
119                     (ret = __log_newfile(dblp, NULL, 0, 0)) != 0)
120                         goto err;
121
122                 /*
123                  * Initialize replication's next-expected LSN value
124                  * and replication's bulk buffer.  In __env_open, we
125                  * always create/open the replication region before
126                  * the log region so we're assured that our rep_handle
127                  * is valid at this point, if replication is being used.
128                  */
129                 lp->ready_lsn = lp->lsn;
130                 if (IS_ENV_REPLICATED(env)) {
131                         if ((ret =
132                             __env_alloc(&dblp->reginfo, MEGABYTE, &bulk)) != 0)
133                                 goto err;
134                         lp->bulk_buf = R_OFFSET(&dblp->reginfo, bulk);
135                         lp->bulk_len = MEGABYTE;
136                         lp->bulk_off = 0;
137                         lp->wait_ts = env->rep_handle->request_gap;
138                         __os_gettime(env, &lp->rcvd_ts, 1);
139                 } else {
140                         lp->bulk_buf = INVALID_ROFF;
141                         lp->bulk_len = 0;
142                         lp->bulk_off = 0;
143                 }
144                 dblp->reginfo.mtx_alloc = lp->mtx_region;
145         } else {
146                 /*
147                  * A process joining the region may have reset the log file
148                  * size, too.  If so, it only affects the next log file we
149                  * create.  We need to check that the size is reasonable given
150                  * the buffer size in the region.
151                  */
152                 LOG_SYSTEM_LOCK(env);
153                 region_locked = 1;
154
155                  if (dbenv->lg_size != 0) {
156                         if ((ret =
157                             __log_check_sizes(env, dbenv->lg_size, 0)) != 0)
158                                 goto err;
159
160                         lp->log_nsize = dbenv->lg_size;
161                  }
162
163                 LOG_SYSTEM_UNLOCK(env);
164                 region_locked = 0;
165         }
166
167         return (0);
168
169 err:    if (dblp->reginfo.addr != NULL) {
170                 if (region_locked)
171                         LOG_SYSTEM_UNLOCK(env);
172                 (void)__env_region_detach(env, &dblp->reginfo, 0);
173         }
174         env->lg_handle = NULL;
175
176         (void)__mutex_free(env, &dblp->mtx_dbreg);
177         __os_free(env, dblp);
178
179         return (ret);
180 }
181
182 /*
183  * __log_init --
184  *      Initialize a log region in shared memory.
185  */
186 static int
187 __log_init(env, dblp)
188         ENV *env;
189         DB_LOG *dblp;
190 {
191         DB_ENV *dbenv;
192         LOG *lp;
193         int ret;
194         void *p;
195
196         dbenv = env->dbenv;
197
198         /*
199          * This is the first point where we can validate the buffer size,
200          * because we know all three settings have been configured (file size,
201          * buffer size and the in-memory flag).
202          */
203         if ((ret =
204            __log_check_sizes(env, dbenv->lg_size, dbenv->lg_bsize)) != 0)
205                 return (ret);
206
207         if ((ret = __env_alloc(&dblp->reginfo,
208             sizeof(*lp), &dblp->reginfo.primary)) != 0)
209                 goto mem_err;
210         dblp->reginfo.rp->primary =
211             R_OFFSET(&dblp->reginfo, dblp->reginfo.primary);
212         lp = dblp->reginfo.primary;
213         memset(lp, 0, sizeof(*lp));
214
215         if ((ret =
216             __mutex_alloc(env, MTX_LOG_REGION, 0, &lp->mtx_region)) != 0)
217                 return (ret);
218
219         lp->fid_max = 0;
220         SH_TAILQ_INIT(&lp->fq);
221         lp->free_fid_stack = INVALID_ROFF;
222         lp->free_fids = lp->free_fids_alloced = 0;
223
224         /* Initialize LOG LSNs. */
225         INIT_LSN(lp->lsn);
226         INIT_LSN(lp->t_lsn);
227
228         /*
229          * It's possible to be waiting for an LSN of [1][0], if a replication
230          * client gets the first log record out of order.  An LSN of [0][0]
231          * signifies that we're not waiting.
232          */
233         ZERO_LSN(lp->waiting_lsn);
234
235         /*
236          * Log makes note of the fact that it ran into a checkpoint on
237          * startup if it did so, as a recovery optimization.  A zero
238          * LSN signifies that it hasn't found one [yet].
239          */
240         ZERO_LSN(lp->cached_ckp_lsn);
241
242         if ((ret =
243             __mutex_alloc(env, MTX_LOG_FILENAME, 0, &lp->mtx_filelist)) != 0)
244                 return (ret);
245         if ((ret = __mutex_alloc(env, MTX_LOG_FLUSH, 0, &lp->mtx_flush)) != 0)
246                 return (ret);
247
248         /* Initialize the buffer. */
249         if ((ret = __env_alloc(&dblp->reginfo, dbenv->lg_bsize, &p)) != 0) {
250 mem_err:        __db_errx( env, "unable to allocate log region memory");
251                 return (ret);
252         }
253         lp->regionmax = dbenv->lg_regionmax;
254         lp->buffer_off = R_OFFSET(&dblp->reginfo, p);
255         lp->buffer_size = dbenv->lg_bsize;
256         lp->filemode = dbenv->lg_filemode;
257         lp->log_size = lp->log_nsize = dbenv->lg_size;
258
259         /* Initialize the commit Queue. */
260         SH_TAILQ_INIT(&lp->free_commits);
261         SH_TAILQ_INIT(&lp->commits);
262         lp->ncommit = 0;
263
264         /* Initialize the logfiles list for in-memory logs. */
265         SH_TAILQ_INIT(&lp->logfiles);
266         SH_TAILQ_INIT(&lp->free_logfiles);
267
268         /*
269          * Fill in the log's persistent header.  Don't fill in the log file
270          * sizes, as they may change at any time and so have to be filled in
271          * as each log file is created.
272          */
273         lp->persist.magic = DB_LOGMAGIC;
274         /*
275          * Don't use __log_set_version because env->dblp isn't set up yet.
276          */
277         lp->persist.version = DB_LOGVERSION;
278         lp->persist.notused = 0;
279         env->lg_handle = dblp;
280
281         /* Migrate persistent flags from the ENV into the region. */
282         if (dbenv->lg_flags != 0 &&
283             (ret = __log_set_config_int(dbenv, dbenv->lg_flags, 1, 1)) != 0)
284                 return (ret);
285
286         (void)time(&lp->timestamp);
287         return (0);
288 }
289
290 /*
291  * __log_recover --
292  *      Recover a log.
293  */
294 static int
295 __log_recover(dblp)
296         DB_LOG *dblp;
297 {
298         DBT dbt;
299         DB_ENV *dbenv;
300         DB_LOGC *logc;
301         DB_LSN lsn;
302         ENV *env;
303         LOG *lp;
304         u_int32_t cnt, rectype;
305         int ret;
306         logfile_validity status;
307
308         env = dblp->env;
309         dbenv = env->dbenv;
310         logc = NULL;
311         lp = dblp->reginfo.primary;
312
313         /*
314          * Find a log file.  If none exist, we simply return, leaving
315          * everything initialized to a new log.
316          */
317         if ((ret = __log_find(dblp, 0, &cnt, &status)) != 0)
318                 return (ret);
319         if (cnt == 0)
320                 return (0);
321
322         /*
323          * If the last file is an old, unreadable version, start a new
324          * file.  Don't bother finding the end of the last log file;
325          * we assume that it's valid in its entirety, since the user
326          * should have shut down cleanly or run recovery before upgrading.
327          */
328         if (status == DB_LV_OLD_UNREADABLE) {
329                 lp->lsn.file = lp->s_lsn.file = cnt + 1;
330                 lp->lsn.offset = lp->s_lsn.offset = 0;
331                 goto skipsearch;
332         }
333         DB_ASSERT(env,
334             (status == DB_LV_NORMAL || status == DB_LV_OLD_READABLE));
335
336         /*
337          * We have the last useful log file and we've loaded any persistent
338          * information.  Set the end point of the log past the end of the last
339          * file. Read the last file, looking for the last checkpoint and
340          * the log's end.
341          */
342         lp->lsn.file = cnt + 1;
343         lp->lsn.offset = 0;
344         lsn.file = cnt;
345         lsn.offset = 0;
346
347         /*
348          * Allocate a cursor and set it to the first record.  This shouldn't
349          * fail, leave error messages on.
350          */
351         if ((ret = __log_cursor(env, &logc)) != 0)
352                 return (ret);
353         F_SET(logc, DB_LOG_LOCKED);
354         memset(&dbt, 0, sizeof(dbt));
355         if ((ret = __logc_get(logc, &lsn, &dbt, DB_SET)) != 0)
356                 goto err;
357
358         /*
359          * Read to the end of the file.  This may fail at some point, so
360          * turn off error messages.
361          */
362         F_SET(logc, DB_LOG_SILENT_ERR);
363         while (__logc_get(logc, &lsn, &dbt, DB_NEXT) == 0) {
364                 if (dbt.size < sizeof(u_int32_t))
365                         continue;
366                 LOGCOPY_32(env, &rectype, dbt.data);
367                 if (rectype == DB___txn_ckp)
368                         /*
369                          * If we happen to run into a checkpoint, cache its
370                          * LSN so that the transaction system doesn't have
371                          * to walk this log file again looking for it.
372                          */
373                         lp->cached_ckp_lsn = lsn;
374         }
375         F_CLR(logc, DB_LOG_SILENT_ERR);
376
377         /*
378          * We now know where the end of the log is.  Set the first LSN that
379          * we want to return to an application and the LSN of the last known
380          * record on disk.
381          */
382         lp->lsn = lsn;
383         lp->s_lsn = lsn;
384         lp->lsn.offset += logc->len;
385         lp->s_lsn.offset += logc->len;
386
387         /* Set up the current buffer information, too. */
388         lp->len = logc->len;
389         lp->a_off = 0;
390         lp->b_off = 0;
391         lp->w_off = lp->lsn.offset;
392
393 skipsearch:
394         if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY))
395                 __db_msg(env,
396                     "Finding last valid log LSN: file: %lu offset %lu",
397                     (u_long)lp->lsn.file, (u_long)lp->lsn.offset);
398
399 err:    if (logc != NULL)
400                 (void)__logc_close(logc);
401
402         return (ret);
403 }
404
405 /*
406  * __log_find --
407  *      Try to find a log file.  If find_first is set, valp will contain
408  * the number of the first readable log file, else it will contain the number
409  * of the last log file (which may be too old to read).
410  *
411  * PUBLIC: int __log_find __P((DB_LOG *, int, u_int32_t *, logfile_validity *));
412  */
413 int
414 __log_find(dblp, find_first, valp, statusp)
415         DB_LOG *dblp;
416         int find_first;
417         u_int32_t *valp;
418         logfile_validity *statusp;
419 {
420         ENV *env;
421         LOG *lp;
422         logfile_validity logval_status, status;
423         struct __db_filestart *filestart;
424         u_int32_t clv, logval;
425         int cnt, fcnt, ret;
426         const char *dir;
427         char *c, **names, *p, *q;
428
429         env = dblp->env;
430         lp = dblp->reginfo.primary;
431         logval_status = status = DB_LV_NONEXISTENT;
432
433         /* Return a value of 0 as the log file number on failure. */
434         *valp = 0;
435
436         if (lp->db_log_inmemory) {
437                 filestart = find_first ?
438                     SH_TAILQ_FIRST(&lp->logfiles, __db_filestart) :
439                     SH_TAILQ_LAST(&lp->logfiles, links, __db_filestart);
440                 if (filestart != NULL) {
441                         *valp = filestart->file;
442                         logval_status = DB_LV_NORMAL;
443                 }
444                 *statusp = logval_status;
445                 return (0);
446         }
447
448         /* Find the directory name. */
449         if ((ret = __log_name(dblp, 1, &p, NULL, 0)) != 0) {
450                 __os_free(env, p);
451                 return (ret);
452         }
453         if ((q = __db_rpath(p)) == NULL)
454                 dir = PATH_DOT;
455         else {
456                 *q = '\0';
457                 dir = p;
458         }
459
460         /* Get the list of file names. */
461 retry:  if ((ret = __os_dirlist(env, dir, 0, &names, &fcnt)) != 0) {
462                 __db_err(env, ret, "%s", dir);
463                 __os_free(env, p);
464                 return (ret);
465         }
466
467         /* Search for a valid log file name. */
468         for (cnt = fcnt, clv = logval = 0; --cnt >= 0;) {
469                 if (strncmp(names[cnt], LFPREFIX, sizeof(LFPREFIX) - 1) != 0)
470                         continue;
471
472                 /*
473                  * Names of the form log\.[0-9]* are reserved for DB.  Other
474                  * names sharing LFPREFIX, such as "log.db", are legal.
475                  */
476                 for (c = names[cnt] + sizeof(LFPREFIX) - 1; *c != '\0'; c++)
477                         if (!isdigit((int)*c))
478                                 break;
479                 if (*c != '\0')
480                         continue;
481
482                 /*
483                  * Use atol, not atoi; if an "int" is 16-bits, the largest
484                  * log file name won't fit.
485                  */
486                 clv = (u_int32_t)atol(names[cnt] + (sizeof(LFPREFIX) - 1));
487
488                 /*
489                  * If searching for the first log file, we want to return the
490                  * oldest log file we can read, or, if no readable log files
491                  * exist, the newest log file we can't read (the crossover
492                  * point between the old and new versions of the log file).
493                  *
494                  * If we're searching for the last log file, we want to return
495                  * the newest log file, period.
496                  *
497                  * Readable log files should never precede unreadable log
498                  * files, that would mean the admin seriously screwed up.
499                  */
500                 if (find_first) {
501                         if (logval != 0 &&
502                             status != DB_LV_OLD_UNREADABLE && clv > logval)
503                                 continue;
504                 } else
505                         if (logval != 0 && clv < logval)
506                                 continue;
507
508                 if ((ret = __log_valid(dblp, clv, 1, NULL, 0,
509                     &status, NULL)) != 0) {
510                         /*
511                          * If we have raced with removal of a log file since
512                          * the call to __os_dirlist, it may no longer exist.
513                          * In that case, just go on to the next one.  If we're
514                          * at the end of the list, all of the log files we saw
515                          * initially are gone and we need to get the list again.
516                          */
517                         if (ret == ENOENT) {
518                                 ret = 0;
519                                 if (cnt == 0) {
520                                         __os_dirfree(env, names, fcnt);
521                                         goto retry;
522                                 }
523                                 continue;
524                         }
525                         __db_err(
526                             env, ret, "Invalid log file: %s", names[cnt]);
527                         goto err;
528                 }
529                 switch (status) {
530                 case DB_LV_NONEXISTENT:
531                         /* __log_valid never returns DB_LV_NONEXISTENT. */
532                         DB_ASSERT(env, 0);
533                         break;
534                 case DB_LV_INCOMPLETE:
535                         /*
536                          * The last log file may not have been initialized --
537                          * it's possible to create a log file but not write
538                          * anything to it.  If performing recovery (that is,
539                          * if find_first isn't set), ignore the file, it's
540                          * not interesting.  If we're searching for the first
541                          * log record, return the file (assuming we don't find
542                          * something better), as the "real" first log record
543                          * is likely to be in the log buffer, and we want to
544                          * set the file LSN for our return.
545                          */
546                         if (find_first)
547                                 goto found;
548                         break;
549                 case DB_LV_OLD_UNREADABLE:
550                         /*
551                          * If we're searching for the first log file, then we
552                          * only want this file if we don't yet have a file or
553                          * already have an unreadable file and this one is
554                          * newer than that one.  If we're searching for the
555                          * last log file, we always want this file because we
556                          * wouldn't be here if it wasn't newer than our current
557                          * choice.
558                          */
559                         if (!find_first || logval == 0 ||
560                             (status == DB_LV_OLD_UNREADABLE && clv > logval))
561                                 goto found;
562                         break;
563                 case DB_LV_NORMAL:
564                 case DB_LV_OLD_READABLE:
565 found:                  logval = clv;
566                         logval_status = status;
567                         break;
568                 }
569         }
570
571         *valp = logval;
572
573 err:    __os_dirfree(env, names, fcnt);
574         __os_free(env, p);
575         *statusp = logval_status;
576
577         return (ret);
578 }
579
580 /*
581  * log_valid --
582  *      Validate a log file.  Returns an error code in the event of
583  *      a fatal flaw in a the specified log file;  returns success with
584  *      a code indicating the currentness and completeness of the specified
585  *      log file if it is not unexpectedly flawed (that is, if it's perfectly
586  *      normal, if it's zero-length, or if it's an old version).
587  *
588  * PUBLIC: int __log_valid __P((DB_LOG *, u_int32_t, int,
589  * PUBLIC:     DB_FH **, u_int32_t, logfile_validity *, u_int32_t *));
590  */
591 int
592 __log_valid(dblp, number, set_persist, fhpp, flags, statusp, versionp)
593         DB_LOG *dblp;
594         u_int32_t number;
595         int set_persist;
596         DB_FH **fhpp;
597         u_int32_t flags;
598         logfile_validity *statusp;
599         u_int32_t *versionp;
600 {
601         DB_CIPHER *db_cipher;
602         DB_FH *fhp;
603         ENV *env;
604         HDR *hdr;
605         LOG *lp;
606         LOGP *persist;
607         logfile_validity status;
608         size_t hdrsize, nr, recsize;
609         int is_hmac, ret;
610         u_int8_t *tmp;
611         char *fname;
612
613         env = dblp->env;
614         db_cipher = env->crypto_handle;
615         fhp = NULL;
616         persist = NULL;
617         status = DB_LV_NORMAL;
618         tmp = NULL;
619
620         /* Return the file handle to our caller, on request */
621         if (fhpp != NULL)
622                 *fhpp = NULL;
623
624         if (flags == 0)
625                 flags = DB_OSO_RDONLY | DB_OSO_SEQ;
626         /* Try to open the log file. */
627         if ((ret = __log_name(dblp, number, &fname, &fhp, flags)) != 0) {
628                 __os_free(env, fname);
629                 return (ret);
630         }
631
632         hdrsize = HDR_NORMAL_SZ;
633         is_hmac = 0;
634         recsize = sizeof(LOGP);
635         if (CRYPTO_ON(env)) {
636                 hdrsize = HDR_CRYPTO_SZ;
637                 recsize = sizeof(LOGP);
638                 recsize += db_cipher->adj_size(recsize);
639                 is_hmac = 1;
640         }
641         if ((ret = __os_calloc(env, 1, recsize + hdrsize, &tmp)) != 0)
642                 goto err;
643
644         hdr = (HDR *)tmp;
645         persist = (LOGP *)(tmp + hdrsize);
646
647         /*
648          * Try to read the header.  This can fail if the log is truncated, or
649          * if we find a preallocated log file where the header has not yet been
650          * written, so we need to check whether the header is zero-filled.
651          */
652         if ((ret = __os_read(env, fhp, tmp, recsize + hdrsize, &nr)) != 0 ||
653             nr != recsize + hdrsize ||
654             (hdr->len == 0 && persist->magic == 0 && persist->log_size == 0)) {
655                 if (ret == 0)
656                         status = DB_LV_INCOMPLETE;
657                 else
658                         /*
659                          * The error was a fatal read error, not just an
660                          * incompletely initialized log file.
661                          */
662                         __db_err(env, ret, "ignoring log file: %s", fname);
663                 goto err;
664         }
665
666         if (LOG_SWAPPED(env))
667                 __log_hdrswap(hdr, CRYPTO_ON(env));
668
669         /*
670          * Now we have to validate the persistent record.  We have
671          * several scenarios we have to deal with:
672          *
673          * 1.  User has crypto turned on:
674          *      - They're reading an old, unencrypted log file
675          *        .  We will fail the record size match check below.
676          *      - They're reading a current, unencrypted log file
677          *        .  We will fail the record size match check below.
678          *      - They're reading an old, encrypted log file [NOT YET]
679          *        .  After decryption we'll fail the version check.  [NOT YET]
680          *      - They're reading a current, encrypted log file
681          *        .  We should proceed as usual.
682          * 2.  User has crypto turned off:
683          *      - They're reading an old, unencrypted log file
684          *        .  We will fail the version check.
685          *      - They're reading a current, unencrypted log file
686          *        .  We should proceed as usual.
687          *      - They're reading an old, encrypted log file [NOT YET]
688          *        .  We'll fail the magic number check (it is encrypted).
689          *      - They're reading a current, encrypted log file
690          *        .  We'll fail the magic number check (it is encrypted).
691          */
692         if (CRYPTO_ON(env)) {
693                 /*
694                  * If we are trying to decrypt an unencrypted log
695                  * we can only detect that by having an unreasonable
696                  * data length for our persistent data.
697                  */
698                 if ((hdr->len - hdrsize) != sizeof(LOGP)) {
699                         __db_errx(env, "log record size mismatch");
700                         goto err;
701                 }
702                 /* Check the checksum and decrypt. */
703                 if ((ret = __db_check_chksum(env, hdr, db_cipher,
704                     &hdr->chksum[0], (u_int8_t *)persist,
705                     hdr->len - hdrsize, is_hmac)) != 0) {
706                         __db_errx(env, "log record checksum mismatch");
707                         goto err;
708                 }
709
710                 if ((ret = db_cipher->decrypt(env, db_cipher->data,
711                     &hdr->iv[0], (u_int8_t *)persist, hdr->len - hdrsize)) != 0)
712                         goto err;
713         }
714
715         /* Swap the header, if necessary. */
716         if (LOG_SWAPPED(env)) {
717                 /*
718                  * If the magic number is not byte-swapped, we're looking at an
719                  * old log that we can no longer read.
720                  */
721                 if (persist->magic == DB_LOGMAGIC) {
722                         __db_errx(env,
723                             "Ignoring log file: %s historic byte order", fname);
724                         status = DB_LV_OLD_UNREADABLE;
725                         goto err;
726                 }
727
728                 __log_persistswap(persist);
729         }
730
731         /* Validate the header. */
732         if (persist->magic != DB_LOGMAGIC) {
733                 __db_errx(env,
734                     "Ignoring log file: %s: magic number %lx, not %lx",
735                     fname, (u_long)persist->magic, (u_long)DB_LOGMAGIC);
736                 ret = EINVAL;
737                 goto err;
738         }
739
740         /*
741          * Set our status code to indicate whether the log file belongs to an
742          * unreadable or readable old version; leave it alone if and only if
743          * the log file version is the current one.
744          */
745         if (persist->version > DB_LOGVERSION) {
746                 /* This is a fatal error--the log file is newer than DB. */
747                 __db_errx(env,
748                     "Unacceptable log file %s: unsupported log version %lu",
749                     fname, (u_long)persist->version);
750                 ret = EINVAL;
751                 goto err;
752         } else if (persist->version < DB_LOGOLDVER) {
753                 status = DB_LV_OLD_UNREADABLE;
754                 /* This is a non-fatal error, but give some feedback. */
755                 __db_errx(env,
756                     "Skipping log file %s: historic log version %lu",
757                     fname, (u_long)persist->version);
758                 /*
759                  * We don't want to set persistent info based on an unreadable
760                  * region, so jump to "err".
761                  */
762                 goto err;
763         } else if (persist->version < DB_LOGVERSION)
764                 status = DB_LV_OLD_READABLE;
765
766         /*
767          * Only if we have a current log do we verify the checksum.  We could
768          * not check the checksum before checking the magic and version because
769          * old log headers put the length and checksum in a different location.
770          * The checksum was calculated with the swapped byte order, so we need
771          * to check it with the same bytes.
772          */
773         if (!CRYPTO_ON(env)) {
774                 if (LOG_SWAPPED(env))
775                         __log_persistswap(persist);
776
777                 if ((ret = __db_check_chksum(env,
778                     hdr, db_cipher, &hdr->chksum[0], (u_int8_t *)persist,
779                     hdr->len - hdrsize, is_hmac)) != 0) {
780                         __db_errx(env, "log record checksum mismatch");
781                         goto err;
782                 }
783
784                 if (LOG_SWAPPED(env))
785                         __log_persistswap(persist);
786         }
787
788         /*
789          * If the log is readable so far and we're doing system initialization,
790          * set the region's persistent information based on the headers.
791          *
792          * Override the current log file size.
793          */
794         if (set_persist) {
795                 lp = dblp->reginfo.primary;
796                 lp->log_size = persist->log_size;
797                 lp->persist.version = persist->version;
798         }
799         if (versionp != NULL)
800                 *versionp = persist->version;
801
802 err:    if (fname != NULL)
803                 __os_free(env, fname);
804         if (ret == 0 && fhpp != NULL)
805                 *fhpp = fhp;
806         else
807                 /* Must close on error or if we only used it locally. */
808                 (void)__os_closehandle(env, fhp);
809         if (tmp != NULL)
810                 __os_free(env, tmp);
811
812         if (statusp != NULL)
813                 *statusp = status;
814
815         return (ret);
816 }
817
818 /*
819  * __log_env_refresh --
820  *      Clean up after the log system on a close or failed open.
821  *
822  * PUBLIC: int __log_env_refresh __P((ENV *));
823  */
824 int
825 __log_env_refresh(env)
826         ENV *env;
827 {
828         DB_LOG *dblp;
829         LOG *lp;
830         REGINFO *reginfo;
831         struct __fname *fnp;
832         struct __db_commit *commit;
833         struct __db_filestart *filestart;
834         int ret, t_ret;
835
836         dblp = env->lg_handle;
837         reginfo = &dblp->reginfo;
838         lp = reginfo->primary;
839         ret = 0;
840
841         /*
842          * Flush the log if it's private -- there's no Berkeley DB guarantee
843          * that this gets done, but in case the application has forgotten to
844          * flush for durability, it's the polite thing to do.
845          */
846         if (F_ISSET(env, ENV_PRIVATE) &&
847             (t_ret = __log_flush(env, NULL)) != 0 && ret == 0)
848                 ret = t_ret;
849
850         if ((t_ret = __dbreg_close_files(env, 0)) != 0 && ret == 0)
851                 ret = t_ret;
852
853         /*
854          * After we close the files, check for any unlogged closes left in
855          * the shared memory queue.  If we find any, try to log it, otherwise
856          * return the error.  We cannot say the environment was closed
857          * cleanly.
858          */
859         MUTEX_LOCK(env, lp->mtx_filelist);
860         SH_TAILQ_FOREACH(fnp, &lp->fq, q, __fname)
861                 if (F_ISSET(fnp, DB_FNAME_NOTLOGGED) &&
862                     (t_ret = __dbreg_close_id_int(
863                     env, fnp, DBREG_CLOSE, 1)) != 0)
864                         ret = t_ret;
865         MUTEX_UNLOCK(env, lp->mtx_filelist);
866
867         /*
868          * If a private region, return the memory to the heap.  Not needed for
869          * filesystem-backed or system shared memory regions, that memory isn't
870          * owned by any particular process.
871          */
872         if (F_ISSET(env, ENV_PRIVATE)) {
873                 reginfo->mtx_alloc = MUTEX_INVALID;
874                 /* Discard the flush mutex. */
875                 if ((t_ret =
876                     __mutex_free(env, &lp->mtx_flush)) != 0 && ret == 0)
877                         ret = t_ret;
878
879                 /* Discard the buffer. */
880                 __env_alloc_free(reginfo, R_ADDR(reginfo, lp->buffer_off));
881
882                 /* Discard stack of free file IDs. */
883                 if (lp->free_fid_stack != INVALID_ROFF)
884                         __env_alloc_free(reginfo,
885                             R_ADDR(reginfo, lp->free_fid_stack));
886
887                 /* Discard the list of in-memory log file markers. */
888                 while ((filestart = SH_TAILQ_FIRST(&lp->logfiles,
889                     __db_filestart)) != NULL) {
890                         SH_TAILQ_REMOVE(&lp->logfiles, filestart, links,
891                             __db_filestart);
892                         __env_alloc_free(reginfo, filestart);
893                 }
894
895                 while ((filestart = SH_TAILQ_FIRST(&lp->free_logfiles,
896                     __db_filestart)) != NULL) {
897                         SH_TAILQ_REMOVE(&lp->free_logfiles, filestart, links,
898                             __db_filestart);
899                         __env_alloc_free(reginfo, filestart);
900                 }
901
902                 /* Discord commit queue elements. */
903                 while ((commit = SH_TAILQ_FIRST(&lp->free_commits,
904                     __db_commit)) != NULL) {
905                         SH_TAILQ_REMOVE(&lp->free_commits, commit, links,
906                             __db_commit);
907                         __env_alloc_free(reginfo, commit);
908                 }
909
910                 /* Discard replication bulk buffer. */
911                 if (lp->bulk_buf != INVALID_ROFF) {
912                         __env_alloc_free(reginfo,
913                             R_ADDR(reginfo, lp->bulk_buf));
914                         lp->bulk_buf = INVALID_ROFF;
915                 }
916         }
917
918         /* Discard the per-thread DBREG mutex. */
919         if ((t_ret = __mutex_free(env, &dblp->mtx_dbreg)) != 0 && ret == 0)
920                 ret = t_ret;
921
922         /* Detach from the region. */
923         if ((t_ret = __env_region_detach(env, reginfo, 0)) != 0 && ret == 0)
924                 ret = t_ret;
925
926         /* Close open files, release allocated memory. */
927         if (dblp->lfhp != NULL) {
928                 if ((t_ret =
929                     __os_closehandle(env, dblp->lfhp)) != 0 && ret == 0)
930                         ret = t_ret;
931                 dblp->lfhp = NULL;
932         }
933         if (dblp->dbentry != NULL)
934                 __os_free(env, dblp->dbentry);
935
936         __os_free(env, dblp);
937
938         env->lg_handle = NULL;
939         return (ret);
940 }
941
942 /*
943  * __log_get_cached_ckp_lsn --
944  *      Retrieve any last checkpoint LSN that we may have found on startup.
945  *
946  * PUBLIC: int __log_get_cached_ckp_lsn __P((ENV *, DB_LSN *));
947  */
948 int
949 __log_get_cached_ckp_lsn(env, ckp_lsnp)
950         ENV *env;
951         DB_LSN *ckp_lsnp;
952 {
953         DB_LOG *dblp;
954         LOG *lp;
955
956         dblp = env->lg_handle;
957         lp = (LOG *)dblp->reginfo.primary;
958
959         LOG_SYSTEM_LOCK(env);
960         *ckp_lsnp = lp->cached_ckp_lsn;
961         LOG_SYSTEM_UNLOCK(env);
962
963         return (0);
964 }
965
966 /*
967  * __log_region_mutex_count --
968  *      Return the number of mutexes the log region will need.
969  *
970  * PUBLIC: u_int32_t __log_region_mutex_count __P((ENV *));
971  */
972 u_int32_t
973 __log_region_mutex_count(env)
974         ENV *env;
975 {
976         /*
977          * We need a few assorted mutexes, and one per transaction waiting
978          * on the group commit list.  We can't know how many that will be,
979          * but it should be bounded by the maximum active transactions.
980          */
981         return (env->dbenv->tx_max + 5);
982 }
983
984 /*
985  * __log_region_size --
986  *      Return the amount of space needed for the log region.
987  *      Make the region large enough to hold txn_max transaction
988  *      detail structures  plus some space to hold thread handles
989  *      and the beginning of the alloc region and anything we
990  *      need for mutex system resource recording.
991  */
992 static size_t
993 __log_region_size(env)
994         ENV *env;
995 {
996         DB_ENV *dbenv;
997         size_t s;
998
999         dbenv = env->dbenv;
1000
1001         s = dbenv->lg_regionmax + dbenv->lg_bsize;
1002
1003         /*
1004          * If running with replication, add in space for bulk buffer.
1005          * Allocate a megabyte and a little bit more space.
1006          */
1007         if (IS_ENV_REPLICATED(env))
1008                 s += MEGABYTE;
1009
1010         return (s);
1011 }
1012
1013 /*
1014  * __log_vtruncate
1015  *      This is a virtual truncate.  We set up the log indicators to
1016  * make everyone believe that the given record is the last one in the
1017  * log.  Returns with the next valid LSN (i.e., the LSN of the next
1018  * record to be written). This is used in replication to discard records
1019  * in the log file that do not agree with the master.
1020  *
1021  * PUBLIC: int __log_vtruncate __P((ENV *, DB_LSN *, DB_LSN *, DB_LSN *));
1022  */
1023 int
1024 __log_vtruncate(env, lsn, ckplsn, trunclsn)
1025         ENV *env;
1026         DB_LSN *lsn, *ckplsn, *trunclsn;
1027 {
1028         DBT log_dbt;
1029         DB_LOG *dblp;
1030         DB_LOGC *logc;
1031         LOG *lp;
1032         u_int32_t bytes, len;
1033         int ret, t_ret;
1034
1035         /* Need to find out the length of this soon-to-be-last record. */
1036         if ((ret = __log_cursor(env, &logc)) != 0)
1037                 return (ret);
1038         memset(&log_dbt, 0, sizeof(log_dbt));
1039         ret = __logc_get(logc, lsn, &log_dbt, DB_SET);
1040         len = logc->len;
1041         if ((t_ret = __logc_close(logc)) != 0 && ret == 0)
1042                 ret = t_ret;
1043         if (ret != 0)
1044                 return (ret);
1045
1046         /* Now do the truncate. */
1047         dblp = env->lg_handle;
1048         lp = (LOG *)dblp->reginfo.primary;
1049
1050         LOG_SYSTEM_LOCK(env);
1051
1052         /*
1053          * Flush the log so we can simply initialize the in-memory buffer
1054          * after the truncate.
1055          */
1056         if ((ret = __log_flush_int(dblp, NULL, 0)) != 0)
1057                 goto err;
1058
1059         lp->lsn = *lsn;
1060         lp->len = len;
1061         lp->lsn.offset += lp->len;
1062
1063         if (lp->db_log_inmemory &&
1064             (ret = __log_inmem_lsnoff(dblp, &lp->lsn, &lp->b_off)) != 0)
1065                 goto err;
1066
1067         /*
1068          * I am going to assume that the number of bytes written since
1069          * the last checkpoint doesn't exceed a 32-bit number.
1070          */
1071         DB_ASSERT(env, lp->lsn.file >= ckplsn->file);
1072         bytes = 0;
1073         if (ckplsn->file != lp->lsn.file) {
1074                 bytes = lp->log_size - ckplsn->offset;
1075                 if (lp->lsn.file > ckplsn->file + 1)
1076                         bytes += lp->log_size *
1077                             ((lp->lsn.file - ckplsn->file) - 1);
1078                 bytes += lp->lsn.offset;
1079         } else
1080                 bytes = lp->lsn.offset - ckplsn->offset;
1081
1082         lp->stat.st_wc_mbytes += bytes / MEGABYTE;
1083         lp->stat.st_wc_bytes += bytes % MEGABYTE;
1084
1085         /*
1086          * If the synced lsn is greater than our new end of log, reset it
1087          * to our current end of log.
1088          */
1089         MUTEX_LOCK(env, lp->mtx_flush);
1090         if (LOG_COMPARE(&lp->s_lsn, lsn) > 0)
1091                 lp->s_lsn = lp->lsn;
1092         MUTEX_UNLOCK(env, lp->mtx_flush);
1093
1094         /* Initialize the in-region buffer to a pristine state. */
1095         ZERO_LSN(lp->f_lsn);
1096         lp->w_off = lp->lsn.offset;
1097
1098         if (trunclsn != NULL)
1099                 *trunclsn = lp->lsn;
1100
1101         /* Truncate the log to the new point. */
1102         if ((ret = __log_zero(env, &lp->lsn)) != 0)
1103                 goto err;
1104
1105 err:    LOG_SYSTEM_UNLOCK(env);
1106         return (ret);
1107 }
1108
1109 /*
1110  * __log_is_outdated --
1111  *      Used by the replication system to identify if a client's logs are too
1112  *      old.
1113  *
1114  * PUBLIC: int __log_is_outdated __P((ENV *, u_int32_t, int *));
1115  */
1116 int
1117 __log_is_outdated(env, fnum, outdatedp)
1118         ENV *env;
1119         u_int32_t fnum;
1120         int *outdatedp;
1121 {
1122         DB_LOG *dblp;
1123         LOG *lp;
1124         char *name;
1125         int ret;
1126         u_int32_t cfile;
1127         struct __db_filestart *filestart;
1128
1129         dblp = env->lg_handle;
1130
1131         /*
1132          * The log represented by env is compared to the file number passed
1133          * in fnum.  If the log file fnum does not exist and is lower-numbered
1134          * than the current logs, return *outdatedp non-zero, else we return 0.
1135          */
1136         if (FLD_ISSET(env->dbenv->lg_flags, DB_LOG_IN_MEMORY)) {
1137                 LOG_SYSTEM_LOCK(env);
1138                 lp = (LOG *)dblp->reginfo.primary;
1139                 filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);
1140                 *outdatedp = filestart == NULL ? 0 : (fnum < filestart->file);
1141                 LOG_SYSTEM_UNLOCK(env);
1142                 return (0);
1143         }
1144
1145         *outdatedp = 0;
1146         if ((ret = __log_name(dblp, fnum, &name, NULL, 0)) != 0) {
1147                 __os_free(env, name);
1148                 return (ret);
1149         }
1150
1151         /* If the file exists, we're just fine. */
1152         if (__os_exists(env, name, NULL) == 0)
1153                 goto out;
1154
1155         /*
1156          * It didn't exist, decide if the file number is too big or
1157          * too little.  If it's too little, then we need to indicate
1158          * that the LSN is outdated.
1159          */
1160         LOG_SYSTEM_LOCK(env);
1161         lp = (LOG *)dblp->reginfo.primary;
1162         cfile = lp->lsn.file;
1163         LOG_SYSTEM_UNLOCK(env);
1164
1165         if (cfile > fnum)
1166                 *outdatedp = 1;
1167 out:    __os_free(env, name);
1168         return (ret);
1169 }
1170
1171 /*
1172  * __log_zero --
1173  *      Zero out the tail of a log after a truncate.
1174  *
1175  * PUBLIC: int __log_zero __P((ENV *, DB_LSN *));
1176  */
1177 int
1178 __log_zero(env, from_lsn)
1179         ENV *env;
1180         DB_LSN *from_lsn;
1181 {
1182         DB_FH *fhp;
1183         DB_LOG *dblp;
1184         LOG *lp;
1185         struct __db_filestart *filestart, *nextstart;
1186         size_t nbytes, len, nw;
1187         u_int32_t fn, mbytes, bytes;
1188         u_int8_t buf[4096];
1189         int ret;
1190         char *fname;
1191
1192         dblp = env->lg_handle;
1193         lp = (LOG *)dblp->reginfo.primary;
1194         DB_ASSERT(env, LOG_COMPARE(from_lsn, &lp->lsn) <= 0);
1195         if (LOG_COMPARE(from_lsn, &lp->lsn) > 0) {
1196                 __db_errx(env,
1197                     "Warning: truncating to point beyond end of log");
1198                 return (0);
1199         }
1200
1201         if (lp->db_log_inmemory) {
1202                 /*
1203                  * Remove the files that are invalidated by this truncate.
1204                  */
1205                 for (filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);
1206                     filestart != NULL; filestart = nextstart) {
1207                         nextstart = SH_TAILQ_NEXT(filestart,
1208                             links, __db_filestart);
1209                         if (filestart->file > from_lsn->file) {
1210                                 SH_TAILQ_REMOVE(&lp->logfiles,
1211                                     filestart, links, __db_filestart);
1212                                 SH_TAILQ_INSERT_HEAD(&lp->free_logfiles,
1213                                     filestart, links, __db_filestart);
1214                         }
1215                 }
1216
1217                 return (0);
1218         }
1219
1220         /* Close any open file handles so unlinks don't fail. */
1221         if (dblp->lfhp != NULL) {
1222                 (void)__os_closehandle(env, dblp->lfhp);
1223                 dblp->lfhp = NULL;
1224         }
1225
1226         /* Throw away any extra log files that we have around. */
1227         for (fn = from_lsn->file + 1;; fn++) {
1228                 if (__log_name(dblp, fn, &fname, &fhp, DB_OSO_RDONLY) != 0) {
1229                         __os_free(env, fname);
1230                         break;
1231                 }
1232                 (void)__os_closehandle(env, fhp);
1233                 (void)time(&lp->timestamp);
1234                 ret = __os_unlink(env, fname, 0);
1235                 __os_free(env, fname);
1236                 if (ret != 0)
1237                         return (ret);
1238         }
1239
1240         /* We removed some log files; have to 0 to end of file. */
1241         if ((ret =
1242             __log_name(dblp, from_lsn->file, &fname, &dblp->lfhp, 0)) != 0) {
1243                 __os_free(env, fname);
1244                 return (ret);
1245         }
1246         __os_free(env, fname);
1247         if ((ret = __os_ioinfo(env,
1248             NULL, dblp->lfhp, &mbytes, &bytes, NULL)) != 0)
1249                 goto err;
1250         DB_ASSERT(env, (mbytes * MEGABYTE + bytes) >= from_lsn->offset);
1251         len = (mbytes * MEGABYTE + bytes) - from_lsn->offset;
1252
1253         memset(buf, 0, sizeof(buf));
1254
1255         /* Initialize the write position. */
1256         if ((ret = __os_seek(env, dblp->lfhp, 0, 0, from_lsn->offset)) != 0)
1257                 goto err;
1258
1259         while (len > 0) {
1260                 nbytes = len > sizeof(buf) ? sizeof(buf) : len;
1261                 if ((ret =
1262                     __os_write(env, dblp->lfhp, buf, nbytes, &nw)) != 0)
1263                         goto err;
1264                 len -= nbytes;
1265         }
1266
1267 err:    (void)__os_closehandle(env, dblp->lfhp);
1268         dblp->lfhp = NULL;
1269
1270         return (ret);
1271 }
1272
1273 /*
1274  * __log_inmem_lsnoff --
1275  *      Find the offset in the buffer of a given LSN.
1276  *
1277  * PUBLIC: int __log_inmem_lsnoff __P((DB_LOG *, DB_LSN *, size_t *));
1278  */
1279 int
1280 __log_inmem_lsnoff(dblp, lsnp, offsetp)
1281         DB_LOG *dblp;
1282         DB_LSN *lsnp;
1283         size_t *offsetp;
1284 {
1285         LOG *lp;
1286         struct __db_filestart *filestart;
1287
1288         lp = (LOG *)dblp->reginfo.primary;
1289
1290         SH_TAILQ_FOREACH(filestart, &lp->logfiles, links, __db_filestart)
1291                 if (filestart->file == lsnp->file) {
1292                         *offsetp =
1293                             (filestart->b_off + lsnp->offset) % lp->buffer_size;
1294                         return (0);
1295                 }
1296
1297         return (DB_NOTFOUND);
1298 }
1299
1300 /*
1301  * __log_inmem_newfile --
1302  *      Records the offset of the beginning of a new file in the in-memory
1303  *      buffer.
1304  *
1305  * PUBLIC: int __log_inmem_newfile __P((DB_LOG *, u_int32_t));
1306  */
1307 int
1308 __log_inmem_newfile(dblp, file)
1309         DB_LOG *dblp;
1310         u_int32_t file;
1311 {
1312         HDR hdr;
1313         LOG *lp;
1314         struct __db_filestart *filestart;
1315         int ret;
1316 #ifdef DIAGNOSTIC
1317         struct __db_filestart *first, *last;
1318 #endif
1319
1320         lp = (LOG *)dblp->reginfo.primary;
1321
1322         /*
1323          * If the log buffer is empty, reuse the filestart entry.
1324          */
1325         filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);
1326         if (filestart != NULL &&
1327             RINGBUF_LEN(lp, filestart->b_off, lp->b_off) <=
1328             sizeof(HDR) + sizeof(LOGP)) {
1329                 filestart->file = file;
1330                 filestart->b_off = lp->b_off;
1331                 return (0);
1332         }
1333
1334         /*
1335          * We write an empty header at the end of every in-memory log file.
1336          * This is used during cursor traversal to indicate when to switch the
1337          * LSN to the next file.
1338          */
1339         if (file > 1) {
1340                 memset(&hdr, 0, sizeof(HDR));
1341                 __log_inmem_copyin(dblp, lp->b_off, &hdr, sizeof(HDR));
1342                 lp->b_off = (lp->b_off + sizeof(HDR)) % lp->buffer_size;
1343         }
1344
1345         filestart = SH_TAILQ_FIRST(&lp->free_logfiles, __db_filestart);
1346         if (filestart == NULL) {
1347                 if ((ret = __env_alloc(&dblp->reginfo,
1348                     sizeof(struct __db_filestart), &filestart)) != 0)
1349                         return (ret);
1350                 memset(filestart, 0, sizeof(*filestart));
1351         } else
1352                 SH_TAILQ_REMOVE(&lp->free_logfiles, filestart,
1353                     links, __db_filestart);
1354
1355         filestart->file = file;
1356         filestart->b_off = lp->b_off;
1357
1358 #ifdef DIAGNOSTIC
1359         first = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);
1360         last = SH_TAILQ_LAST(&(lp)->logfiles, links, __db_filestart);
1361
1362         /* Check that we don't wrap. */
1363         DB_ASSERT(dblp->env, !first || first == last ||
1364             RINGBUF_LEN(lp, first->b_off, lp->b_off) ==
1365             RINGBUF_LEN(lp, first->b_off, last->b_off) +
1366             RINGBUF_LEN(lp, last->b_off, lp->b_off));
1367 #endif
1368
1369         SH_TAILQ_INSERT_TAIL(&lp->logfiles, filestart, links);
1370         return (0);
1371 }
1372
1373 /*
1374  * __log_inmem_chkspace --
1375  *      Ensure that the requested amount of space is available in the buffer,
1376  *      and invalidate the region.
1377  *      Note: assumes that the region lock is held on entry.
1378  *
1379  * PUBLIC: int __log_inmem_chkspace __P((DB_LOG *, size_t));
1380  */
1381 int
1382 __log_inmem_chkspace(dblp, len)
1383         DB_LOG *dblp;
1384         size_t len;
1385 {
1386         DB_LSN active_lsn, old_active_lsn;
1387         ENV *env;
1388         LOG *lp;
1389         struct __db_filestart *filestart;
1390         int ret;
1391
1392         env = dblp->env;
1393         lp = dblp->reginfo.primary;
1394
1395         DB_ASSERT(env, lp->db_log_inmemory);
1396
1397         /*
1398          * Allow room for an extra header so that we don't need to check for
1399          * space when switching files.
1400          */
1401         len += sizeof(HDR);
1402
1403         /*
1404          * If transactions are enabled and we're about to fill available space,
1405          * update the active LSN and recheck.  If transactions aren't enabled,
1406          * don't even bother checking: in that case we can always overwrite old
1407          * log records, because we're never going to abort.
1408          */
1409         while (TXN_ON(env) &&
1410             RINGBUF_LEN(lp, lp->b_off, lp->a_off) <= len) {
1411                 old_active_lsn = lp->active_lsn;
1412                 active_lsn = lp->lsn;
1413
1414                 /*
1415                  * Drop the log region lock so we don't hold it while
1416                  * taking the transaction region lock.
1417                  */
1418                 LOG_SYSTEM_UNLOCK(env);
1419                 ret = __txn_getactive(env, &active_lsn);
1420                 LOG_SYSTEM_LOCK(env);
1421                 if (ret != 0)
1422                         return (ret);
1423                 active_lsn.offset = 0;
1424
1425                 /* If we didn't make any progress, give up. */
1426                 if (LOG_COMPARE(&active_lsn, &old_active_lsn) == 0) {
1427                         __db_errx(env,
1428       "In-memory log buffer is full (an active transaction spans the buffer)");
1429                         return (DB_LOG_BUFFER_FULL);
1430                 }
1431
1432                 /* Make sure we're moving the region LSN forwards. */
1433                 if (LOG_COMPARE(&active_lsn, &lp->active_lsn) > 0) {
1434                         lp->active_lsn = active_lsn;
1435                         (void)__log_inmem_lsnoff(dblp, &active_lsn,
1436                             &lp->a_off);
1437                 }
1438         }
1439
1440         /*
1441          * Remove the first file if it is invalidated by this write.
1442          * Log records can't be bigger than a file, so we only need to
1443          * check the first file.
1444          */
1445         filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);
1446         if (filestart != NULL &&
1447             RINGBUF_LEN(lp, lp->b_off, filestart->b_off) <= len) {
1448                 SH_TAILQ_REMOVE(&lp->logfiles, filestart,
1449                     links, __db_filestart);
1450                 SH_TAILQ_INSERT_HEAD(&lp->free_logfiles, filestart,
1451                     links, __db_filestart);
1452                 lp->f_lsn.file = filestart->file + 1;
1453         }
1454
1455         return (0);
1456 }
1457
1458 /*
1459  * __log_inmem_copyout --
1460  *      Copies the given number of bytes from the buffer -- no checking.
1461  *      Note: assumes that the region lock is held on entry.
1462  *
1463  * PUBLIC: void __log_inmem_copyout __P((DB_LOG *, size_t, void *, size_t));
1464  */
1465 void
1466 __log_inmem_copyout(dblp, offset, buf, size)
1467         DB_LOG *dblp;
1468         size_t offset;
1469         void *buf;
1470         size_t size;
1471 {
1472         LOG *lp;
1473         size_t nbytes;
1474
1475         lp = (LOG *)dblp->reginfo.primary;
1476         nbytes = (offset + size < lp->buffer_size) ?
1477             size : lp->buffer_size - offset;
1478         memcpy(buf, dblp->bufp + offset, nbytes);
1479         if (nbytes < size)
1480                 memcpy((u_int8_t *)buf + nbytes, dblp->bufp, size - nbytes);
1481 }
1482
1483 /*
1484  * __log_inmem_copyin --
1485  *      Copies the given number of bytes into the buffer -- no checking.
1486  *      Note: assumes that the region lock is held on entry.
1487  *
1488  * PUBLIC: void __log_inmem_copyin __P((DB_LOG *, size_t, void *, size_t));
1489  */
1490 void
1491 __log_inmem_copyin(dblp, offset, buf, size)
1492         DB_LOG *dblp;
1493         size_t offset;
1494         void *buf;
1495         size_t size;
1496 {
1497         LOG *lp;
1498         size_t nbytes;
1499
1500         lp = (LOG *)dblp->reginfo.primary;
1501         nbytes = (offset + size < lp->buffer_size) ?
1502             size : lp->buffer_size - offset;
1503         memcpy(dblp->bufp + offset, buf, nbytes);
1504         if (nbytes < size)
1505                 memcpy(dblp->bufp, (u_int8_t *)buf + nbytes, size - nbytes);
1506 }
1507
1508 /*
1509  * __log_set_version --
1510  *      Sets the current version of the log subsystem to the given version.
1511  *      Essentially this modifies the lp->persist.version field in the
1512  *      shared memory region.  Called when region is initially created
1513  *      and when replication is starting up or finds a new master.
1514  *
1515  * PUBLIC: void __log_set_version __P((ENV *, u_int32_t));
1516  */
1517 void
1518 __log_set_version(env, newver)
1519         ENV *env;
1520         u_int32_t newver;
1521 {
1522         DB_LOG *dblp;
1523         LOG *lp;
1524
1525         dblp = env->lg_handle;
1526         lp = (LOG *)dblp->reginfo.primary;
1527         /*
1528          * We should be able to update this atomically without locking.
1529          */
1530         lp->persist.version = newver;
1531 }
1532
1533 /*
1534  * __log_get_oldversion --
1535  *      Returns the last version of log that this environment was working
1536  *      with.  Since there could be several versions of log files, if
1537  *      the user upgraded and didn't log archive, we check the version
1538  *      of the first log file, compare it to the last log file.  If those
1539  *      are different, then there is an older log existing, and we then
1540  *      walk backward in the log files looking for the version of the
1541  *      most recent older log file.
1542  *
1543  * PUBLIC: int __log_get_oldversion __P((ENV *, u_int32_t *));
1544  */
1545 int
1546 __log_get_oldversion(env, ver)
1547         ENV *env;
1548         u_int32_t *ver;
1549 {
1550         DBT rec;
1551         DB_LOG *dblp;
1552         DB_LOGC *logc;
1553         DB_LSN lsn;
1554         LOG *lp;
1555         u_int32_t firstfnum, fnum, lastver, oldver;
1556         int ret, t_ret;
1557
1558         dblp = env->lg_handle;
1559         lp = dblp->reginfo.primary;
1560
1561         logc = NULL;
1562         ret = 0;
1563         oldver = DB_LOGVERSION;
1564         /*
1565          * If we're in-memory logs we're always the current version.
1566          */
1567         if (lp->db_log_inmemory) {
1568                 *ver = oldver;
1569                 return (0);
1570         }
1571         memset(&rec, 0, sizeof(rec));
1572         if ((ret = __log_cursor(env, &logc)) != 0)
1573                 goto err;
1574         /*
1575          * Get the version numbers of the first and last log files.
1576          */
1577         if ((ret = __logc_get(logc, &lsn, &rec, DB_FIRST)) != 0) {
1578                 /*
1579                  * If there is no log file, we'll get DB_NOTFOUND.
1580                  * If we get that, set the version to the current.
1581                  */
1582                 if (ret == DB_NOTFOUND)
1583                         ret = 0;
1584                 goto err;
1585         }
1586         firstfnum = lsn.file;
1587         if ((ret = __logc_get(logc, &lsn, &rec, DB_LAST)) != 0)
1588                 goto err;
1589         if ((ret = __log_valid(dblp, firstfnum, 0, NULL, 0,
1590             NULL, &oldver)) != 0)
1591                 goto err;
1592         /*
1593          * If the first and last LSN are in the same file, then we
1594          * already have the version in oldver.  Return it.
1595          */
1596         if (firstfnum == lsn.file)
1597                 goto err;
1598
1599         /*
1600          * Otherwise they're in different files and we call __log_valid
1601          * to get the version numbers in both files.
1602          */
1603         if ((ret = __log_valid(dblp, lsn.file, 0, NULL, 0,
1604             NULL, &lastver)) != 0)
1605                 goto err;
1606         /*
1607          * If the version numbers are different, walk backward getting
1608          * the version of each log file until we find one that is
1609          * different than the last.
1610          */
1611         if (oldver != lastver) {
1612                 for (fnum = lsn.file - 1; fnum >= firstfnum; fnum--) {
1613                         if ((ret = __log_valid(dblp, fnum, 0, NULL, 0,
1614                             NULL, &oldver)) != 0)
1615                                 goto err;
1616                         if (oldver != lastver)
1617                                 break;
1618                 }
1619         }
1620 err:    if (logc != NULL && ((t_ret = __logc_close(logc)) != 0) && ret == 0)
1621                 ret = t_ret;
1622         if (ret == 0 && ver != NULL)
1623                 *ver = oldver;
1624         return (ret);
1625 }