Add BSD license file
[platform/upstream/db4.git] / log / log_method.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1999-2009 Oracle.  All rights reserved.
5  *
6  * $Id$
7  */
8
9 #include "db_config.h"
10
11 #include "db_int.h"
12 #include "dbinc/log.h"
13
14 /*
15  * __log_env_create --
16  *      Log specific initialization of the DB_ENV structure.
17  *
18  * PUBLIC: int __log_env_create __P((DB_ENV *));
19  */
20 int
21 __log_env_create(dbenv)
22         DB_ENV *dbenv;
23 {
24         /*
25          * !!!
26          * Our caller has not yet had the opportunity to reset the panic
27          * state or turn off mutex locking, and so we can neither check
28          * the panic state or acquire a mutex in the DB_ENV create path.
29          */
30         dbenv->lg_bsize = 0;
31         dbenv->lg_regionmax = LG_BASE_REGION_SIZE;
32
33         return (0);
34 }
35
36 /*
37  * __log_env_destroy --
38  *      Log specific destruction of the DB_ENV structure.
39  *
40  * PUBLIC: void __log_env_destroy __P((DB_ENV *));
41  */
42 void
43 __log_env_destroy(dbenv)
44         DB_ENV *dbenv;
45 {
46         COMPQUIET(dbenv, NULL);
47 }
48
49 /*
50  * PUBLIC: int __log_get_lg_bsize __P((DB_ENV *, u_int32_t *));
51  */
52 int
53 __log_get_lg_bsize(dbenv, lg_bsizep)
54         DB_ENV *dbenv;
55         u_int32_t *lg_bsizep;
56 {
57         ENV *env;
58
59         env = dbenv->env;
60
61         ENV_NOT_CONFIGURED(env,
62             env->lg_handle, "DB_ENV->get_lg_bsize", DB_INIT_LOG);
63
64         if (LOGGING_ON(env)) {
65                 /* Cannot be set after open, no lock required to read. */
66                 *lg_bsizep =
67                     ((LOG *)env->lg_handle->reginfo.primary)->buffer_size;
68         } else
69                 *lg_bsizep = dbenv->lg_bsize;
70         return (0);
71 }
72
73 /*
74  * __log_set_lg_bsize --
75  *      DB_ENV->set_lg_bsize.
76  *
77  * PUBLIC: int __log_set_lg_bsize __P((DB_ENV *, u_int32_t));
78  */
79 int
80 __log_set_lg_bsize(dbenv, lg_bsize)
81         DB_ENV *dbenv;
82         u_int32_t lg_bsize;
83 {
84         ENV *env;
85
86         env = dbenv->env;
87
88         ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_lg_bsize");
89
90         dbenv->lg_bsize = lg_bsize;
91         return (0);
92 }
93
94 /*
95  * PUBLIC: int __log_get_lg_filemode __P((DB_ENV *, int *));
96  */
97 int
98 __log_get_lg_filemode(dbenv, lg_modep)
99         DB_ENV *dbenv;
100         int *lg_modep;
101 {
102         DB_LOG *dblp;
103         DB_THREAD_INFO *ip;
104         ENV *env;
105
106         env = dbenv->env;
107
108         ENV_NOT_CONFIGURED(env,
109             env->lg_handle, "DB_ENV->get_lg_filemode", DB_INIT_LOG);
110
111         if (LOGGING_ON(env)) {
112                 dblp = env->lg_handle;
113                 ENV_ENTER(env, ip);
114                 LOG_SYSTEM_LOCK(env);
115                 *lg_modep = ((LOG *)dblp->reginfo.primary)->filemode;
116                 LOG_SYSTEM_UNLOCK(env);
117                 ENV_LEAVE(env, ip);
118         } else
119                 *lg_modep = dbenv->lg_filemode;
120
121         return (0);
122 }
123
124 /*
125  * __log_set_lg_filemode --
126  *      DB_ENV->set_lg_filemode.
127  *
128  * PUBLIC: int __log_set_lg_filemode __P((DB_ENV *, int));
129  */
130 int
131 __log_set_lg_filemode(dbenv, lg_mode)
132         DB_ENV *dbenv;
133         int lg_mode;
134 {
135         DB_LOG *dblp;
136         DB_THREAD_INFO *ip;
137         ENV *env;
138         LOG *lp;
139
140         env = dbenv->env;
141
142         ENV_NOT_CONFIGURED(env,
143             env->lg_handle, "DB_ENV->set_lg_filemode", DB_INIT_LOG);
144
145         if (LOGGING_ON(env)) {
146                 dblp = env->lg_handle;
147                 lp = dblp->reginfo.primary;
148                 ENV_ENTER(env, ip);
149                 LOG_SYSTEM_LOCK(env);
150                 lp->filemode = lg_mode;
151                 LOG_SYSTEM_UNLOCK(env);
152                 ENV_LEAVE(env, ip);
153         } else
154                 dbenv->lg_filemode = lg_mode;
155
156         return (0);
157 }
158
159 /*
160  * PUBLIC: int __log_get_lg_max __P((DB_ENV *, u_int32_t *));
161  */
162 int
163 __log_get_lg_max(dbenv, lg_maxp)
164         DB_ENV *dbenv;
165         u_int32_t *lg_maxp;
166 {
167         DB_LOG *dblp;
168         DB_THREAD_INFO *ip;
169         ENV *env;
170
171         env = dbenv->env;
172
173         ENV_NOT_CONFIGURED(env,
174             env->lg_handle, "DB_ENV->get_lg_max", DB_INIT_LOG);
175
176         if (LOGGING_ON(env)) {
177                 dblp = env->lg_handle;
178                 ENV_ENTER(env, ip);
179                 LOG_SYSTEM_LOCK(env);
180                 *lg_maxp = ((LOG *)dblp->reginfo.primary)->log_nsize;
181                 LOG_SYSTEM_UNLOCK(env);
182                 ENV_LEAVE(env, ip);
183         } else
184                 *lg_maxp = dbenv->lg_size;
185
186         return (0);
187 }
188
189 /*
190  * __log_set_lg_max --
191  *      DB_ENV->set_lg_max.
192  *
193  * PUBLIC: int __log_set_lg_max __P((DB_ENV *, u_int32_t));
194  */
195 int
196 __log_set_lg_max(dbenv, lg_max)
197         DB_ENV *dbenv;
198         u_int32_t lg_max;
199 {
200         DB_LOG *dblp;
201         DB_THREAD_INFO *ip;
202         ENV *env;
203         LOG *lp;
204         int ret;
205
206         env = dbenv->env;
207         ret = 0;
208
209         ENV_NOT_CONFIGURED(env,
210             env->lg_handle, "DB_ENV->set_lg_max", DB_INIT_LOG);
211
212         if (LOGGING_ON(env)) {
213                 dblp = env->lg_handle;
214                 lp = dblp->reginfo.primary;
215                 ENV_ENTER(env, ip);
216                 if ((ret = __log_check_sizes(env, lg_max, 0)) == 0) {
217                         LOG_SYSTEM_LOCK(env);
218                         lp->log_nsize = lg_max;
219                         LOG_SYSTEM_UNLOCK(env);
220                 }
221                 ENV_LEAVE(env, ip);
222         } else
223                 dbenv->lg_size = lg_max;
224
225         return (ret);
226 }
227
228 /*
229  * PUBLIC: int __log_get_lg_regionmax __P((DB_ENV *, u_int32_t *));
230  */
231 int
232 __log_get_lg_regionmax(dbenv, lg_regionmaxp)
233         DB_ENV *dbenv;
234         u_int32_t *lg_regionmaxp;
235 {
236         ENV *env;
237
238         env = dbenv->env;
239
240         ENV_NOT_CONFIGURED(env,
241             env->lg_handle, "DB_ENV->get_lg_regionmax", DB_INIT_LOG);
242
243         if (LOGGING_ON(env)) {
244                 /* Cannot be set after open, no lock required to read. */
245                 *lg_regionmaxp =
246                     ((LOG *)env->lg_handle->reginfo.primary)->regionmax;
247         } else
248                 *lg_regionmaxp = dbenv->lg_regionmax;
249         return (0);
250 }
251
252 /*
253  * __log_set_lg_regionmax --
254  *      DB_ENV->set_lg_regionmax.
255  *
256  * PUBLIC: int __log_set_lg_regionmax __P((DB_ENV *, u_int32_t));
257  */
258 int
259 __log_set_lg_regionmax(dbenv, lg_regionmax)
260         DB_ENV *dbenv;
261         u_int32_t lg_regionmax;
262 {
263         ENV *env;
264
265         env = dbenv->env;
266
267         ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_lg_regionmax");
268
269                                         /* Let's not be silly. */
270         if (lg_regionmax != 0 && lg_regionmax < LG_BASE_REGION_SIZE) {
271                 __db_errx(env,
272                     "log region size must be >= %d", LG_BASE_REGION_SIZE);
273                 return (EINVAL);
274         }
275
276         dbenv->lg_regionmax = lg_regionmax;
277         return (0);
278 }
279
280 /*
281  * PUBLIC: int __log_get_lg_dir __P((DB_ENV *, const char **));
282  */
283 int
284 __log_get_lg_dir(dbenv, dirp)
285         DB_ENV *dbenv;
286         const char **dirp;
287 {
288         *dirp = dbenv->db_log_dir;
289         return (0);
290 }
291
292 /*
293  * __log_set_lg_dir --
294  *      DB_ENV->set_lg_dir.
295  *
296  * PUBLIC: int __log_set_lg_dir __P((DB_ENV *, const char *));
297  */
298 int
299 __log_set_lg_dir(dbenv, dir)
300         DB_ENV *dbenv;
301         const char *dir;
302 {
303         ENV *env;
304
305         env = dbenv->env;
306
307         if (dbenv->db_log_dir != NULL)
308                 __os_free(env, dbenv->db_log_dir);
309         return (__os_strdup(env, dir, &dbenv->db_log_dir));
310 }
311
312 /*
313  * __log_get_flags --
314  *      DB_ENV->get_flags.
315  *
316  * PUBLIC: void __log_get_flags __P((DB_ENV *, u_int32_t *));
317  */
318 void
319 __log_get_flags(dbenv, flagsp)
320         DB_ENV *dbenv;
321         u_int32_t *flagsp;
322 {
323         DB_LOG *dblp;
324         ENV *env;
325         LOG *lp;
326         u_int32_t flags;
327
328         env = dbenv->env;
329
330         if ((dblp = env->lg_handle) == NULL)
331                 return;
332
333         lp = dblp->reginfo.primary;
334
335         flags = *flagsp;
336         if (lp->db_log_autoremove)
337                 LF_SET(DB_LOG_AUTO_REMOVE);
338         else
339                 LF_CLR(DB_LOG_AUTO_REMOVE);
340         if (lp->db_log_inmemory)
341                 LF_SET(DB_LOG_IN_MEMORY);
342         else
343                 LF_CLR(DB_LOG_IN_MEMORY);
344         *flagsp = flags;
345 }
346
347 /*
348  * __log_set_flags --
349  *      DB_ENV->set_flags.
350  *
351  * PUBLIC: void __log_set_flags __P((ENV *, u_int32_t, int));
352  */
353 void
354 __log_set_flags(env, flags, on)
355         ENV *env;
356         u_int32_t flags;
357         int on;
358 {
359         DB_LOG *dblp;
360         LOG *lp;
361
362         if ((dblp = env->lg_handle) == NULL)
363                 return;
364
365         lp = dblp->reginfo.primary;
366
367         if (LF_ISSET(DB_LOG_AUTO_REMOVE))
368                 lp->db_log_autoremove = on ? 1 : 0;
369         if (LF_ISSET(DB_LOG_IN_MEMORY))
370                 lp->db_log_inmemory = on ? 1 : 0;
371 }
372
373 /*
374  * List of flags we can handle here.  DB_LOG_INMEMORY must be
375  * processed before creating the region, leave it out for now.
376  */
377 #undef  OK_FLAGS
378 #define OK_FLAGS                                                        \
379     (DB_LOG_AUTO_REMOVE | DB_LOG_DIRECT |                               \
380     DB_LOG_DSYNC | DB_LOG_IN_MEMORY | DB_LOG_ZERO)
381 #ifndef BREW
382 static
383 #endif
384 const FLAG_MAP LogMap[] = {
385         { DB_LOG_AUTO_REMOVE,   DBLOG_AUTOREMOVE},
386         { DB_LOG_DIRECT,        DBLOG_DIRECT},
387         { DB_LOG_DSYNC,         DBLOG_DSYNC},
388         { DB_LOG_IN_MEMORY,     DBLOG_INMEMORY},
389         { DB_LOG_ZERO,          DBLOG_ZERO}
390 };
391 /*
392  * __log_get_config --
393  *      Configure the logging subsystem.
394  *
395  * PUBLIC: int __log_get_config __P((DB_ENV *, u_int32_t, int *));
396  */
397 int
398 __log_get_config(dbenv, which, onp)
399         DB_ENV *dbenv;
400         u_int32_t which;
401         int *onp;
402 {
403         ENV *env;
404         DB_LOG *dblp;
405         u_int32_t flags;
406
407         env = dbenv->env;
408         if (FLD_ISSET(which, ~OK_FLAGS))
409                 return (__db_ferr(env, "DB_ENV->log_get_config", 0));
410         dblp = env->lg_handle;
411         ENV_REQUIRES_CONFIG(env, dblp, "DB_ENV->log_get_config", DB_INIT_LOG);
412
413         __env_fetch_flags(LogMap, sizeof(LogMap), &dblp->flags, &flags);
414         __log_get_flags(dbenv, &flags);
415         if (LF_ISSET(which))
416                 *onp = 1;
417         else
418                 *onp = 0;
419
420         return (0);
421 }
422
423 /*
424  * __log_set_config --
425  *      Configure the logging subsystem.
426  *
427  * PUBLIC: int __log_set_config __P((DB_ENV *, u_int32_t, int));
428  */
429 int
430 __log_set_config(dbenv, flags, on)
431         DB_ENV *dbenv;
432         u_int32_t flags;
433         int on;
434 {
435         return (__log_set_config_int(dbenv, flags, on, 0));
436 }
437 /*
438  * __log_set_config_int --
439  *      Configure the logging subsystem.
440  *
441  * PUBLIC: int __log_set_config_int __P((DB_ENV *, u_int32_t, int, int));
442  */
443 int
444 __log_set_config_int(dbenv, flags, on, in_open)
445         DB_ENV *dbenv;
446         u_int32_t flags;
447         int on;
448         int in_open;
449 {
450         ENV *env;
451         DB_LOG *dblp;
452         u_int32_t mapped_flags;
453
454         env = dbenv->env;
455         dblp = env->lg_handle;
456         if (FLD_ISSET(flags, ~OK_FLAGS))
457                 return (__db_ferr(env, "DB_ENV->log_set_config", 0));
458         ENV_NOT_CONFIGURED(env, dblp, "DB_ENV->log_set_config", DB_INIT_LOG);
459         if (LF_ISSET(DB_LOG_DIRECT) && __os_support_direct_io() == 0) {
460                 __db_errx(env,
461 "DB_ENV->log_set_config: direct I/O either not configured or not supported");
462                 return (EINVAL);
463         }
464
465         if (LOGGING_ON(env)) {
466                 if (!in_open && LF_ISSET(DB_LOG_IN_MEMORY))
467                         ENV_ILLEGAL_AFTER_OPEN(env,
468                              "DB_ENV->log_set_config: DB_LOG_IN_MEMORY");
469                 __log_set_flags(env, flags, on);
470                 mapped_flags = 0;
471                 __env_map_flags(LogMap, sizeof(LogMap), &flags, &mapped_flags);
472                 if (on)
473                         F_SET(dblp, mapped_flags);
474                 else
475                         F_CLR(dblp, mapped_flags);
476         } else {
477                 /*
478                  * DB_LOG_IN_MEMORY, DB_TXN_NOSYNC and DB_TXN_WRITE_NOSYNC
479                  * are mutually incompatible.  If we're setting one of them,
480                  * clear all current settings.
481                  */
482                 if (on && LF_ISSET(DB_LOG_IN_MEMORY))
483                         F_CLR(dbenv,
484                              DB_ENV_TXN_NOSYNC | DB_ENV_TXN_WRITE_NOSYNC);
485
486                 if (on)
487                         FLD_SET(dbenv->lg_flags, flags);
488                 else
489                         FLD_CLR(dbenv->lg_flags, flags);
490         }
491
492         return (0);
493 }
494
495 /*
496  * __log_check_sizes --
497  *      Makes sure that the log file size and log buffer size are compatible.
498  *
499  * PUBLIC: int __log_check_sizes __P((ENV *, u_int32_t, u_int32_t));
500  */
501 int
502 __log_check_sizes(env, lg_max, lg_bsize)
503         ENV *env;
504         u_int32_t lg_max;
505         u_int32_t lg_bsize;
506 {
507         DB_ENV *dbenv;
508         LOG *lp;
509         int inmem;
510
511         dbenv = env->dbenv;
512
513         if (LOGGING_ON(env)) {
514                 lp = env->lg_handle->reginfo.primary;
515                 inmem = lp->db_log_inmemory;
516                 lg_bsize = lp->buffer_size;
517         } else
518                 inmem = (FLD_ISSET(dbenv->lg_flags, DB_LOG_IN_MEMORY) != 0);
519
520         if (inmem) {
521                 if (lg_bsize == 0)
522                         lg_bsize = LG_BSIZE_INMEM;
523                 if (lg_max == 0)
524                         lg_max = LG_MAX_INMEM;
525
526                 if (lg_bsize <= lg_max) {
527                         __db_errx(env,
528                   "in-memory log buffer must be larger than the log file size");
529                         return (EINVAL);
530                 }
531         }
532
533         return (0);
534 }