1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3 #ident "$Id$"
4 /*======
5 This file is part of PerconaFT.
6 
7 
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9 
10     PerconaFT is free software: you can redistribute it and/or modify
11     it under the terms of the GNU General Public License, version 2,
12     as published by the Free Software Foundation.
13 
14     PerconaFT is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18 
19     You should have received a copy of the GNU General Public License
20     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
21 
22 ----------------------------------------
23 
24     PerconaFT is free software: you can redistribute it and/or modify
25     it under the terms of the GNU Affero General Public License, version 3,
26     as published by the Free Software Foundation.
27 
28     PerconaFT is distributed in the hope that it will be useful,
29     but WITHOUT ANY WARRANTY; without even the implied warranty of
30     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31     GNU Affero General Public License for more details.
32 
33     You should have received a copy of the GNU Affero General Public License
34     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
35 ======= */
36 
37 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38 
39 /**
40   \file errors.c
41   \brief Error handling
42 
43   The error handling routines for ydb
44 */
45 
46 #include <toku_portability.h>
47 #include <stdio.h>
48 #include <stdarg.h>
49 
50 #include "ydb-internal.h"
51 
52 /** Checks whether the environment has panicked */
toku_env_is_panicked(DB_ENV * dbenv)53 int toku_env_is_panicked(DB_ENV *dbenv /**< The environment to check */) {
54     if (dbenv==0) return 0;
55     return dbenv->i->is_panicked;
56 }
57 
58 /* Prints an error message to a file specified by env (or stderr),
59    preceded by the environment's error prefix. */
toku__ydb_error_file(const DB_ENV * env,bool use_stderr,char errmsg[])60 static void toku__ydb_error_file(const DB_ENV *env, bool use_stderr,
61                                   char errmsg[]) {
62     /* Determine the error file to use */
63     FILE *CAST_FROM_VOIDP(efile, env->i->errfile);
64     if (efile==NULL && env->i->errcall==0 && use_stderr) efile = stderr;
65 
66     /* Print out on a file */
67     if (efile) {
68         if (env->i->errpfx) fprintf(efile, "%s: ", env->i->errpfx);
69 	fprintf(efile, "%s", errmsg);
70     }
71 }
72 
73 /**
74 
75      Prints out environment errors, adjusting to a variety of options
76      and formats.
77      The printout format can be controlled to print the following optional
78      messages:
79      - The environment error message prefix
80      - User-supplied prefix obtained by printing ap with the
81        fmt string
82      - The standard db error string
83      The print out takes place via errcall (if set), errfile (if set),
84      or stderr if neither is set (and the user so toggles the printout).
85      Both errcall and errfile can be set.
86      The error message is truncated to approximately 4,000 characters.
87 
88      \param env   The environment that the error refers to.
89      \param error The error code
90      \param include_stderrstring Controls whether the standard db error
91                   string should be included in the print out
92      \param use_stderr_if_nothing_else Toggles the use of stderr.
93      \param fmt   Output format for optional prefix arguments (must be NULL
94                   if the prefix is empty)
95      \param ap    Optional prefix
96 */
toku_ydb_error_all_cases(const DB_ENV * env,int error,bool include_stderrstring,bool use_stderr_if_nothing_else,const char * fmt,va_list ap)97 void toku_ydb_error_all_cases(const DB_ENV * env,
98                               int error,
99                               bool include_stderrstring,
100                               bool use_stderr_if_nothing_else,
101                               const char *fmt, va_list ap) {
102     /* Construct the error message */
103     char buf [4000];
104     int count=0;
105     if (fmt) count=vsnprintf(buf, sizeof(buf), fmt, ap);
106     if (include_stderrstring) {
107         count+=snprintf(&buf[count], sizeof(buf)-count, ": %s",
108                         db_strerror(error));
109     }
110 
111     /* Print via errcall */
112     if (env->i->errcall) env->i->errcall(env, env->i->errpfx, buf);
113 
114     /* Print out on a file */
115     toku__ydb_error_file(env, use_stderr_if_nothing_else, buf);
116 }
117 
118 /** Handle all the error cases (but don't do the default thing.)
119     \param dbenv  The environment that is subject to errors
120     \param error  The error code
121     \param fmt    The format string for additional variable arguments to
122                   be printed   */
toku_ydb_do_error(const DB_ENV * dbenv,int error,const char * fmt,...)123 int toku_ydb_do_error (const DB_ENV *dbenv, int error, const char *fmt, ...) {
124     va_list ap;
125     va_start(ap, fmt);
126     toku_ydb_error_all_cases(dbenv, error, false, false, fmt, ap);
127     va_end(ap);
128     return error;
129 }
130 
131 /** Handle errors on an environment,
132     \param dbenv  The environment that is subject to errors
133     \param error  The error code
134     \param fmt    The format string for additional variable arguments to
135                   be printed   */
toku_env_err(const DB_ENV * env,int error,const char * fmt,...)136 void toku_env_err(const DB_ENV * env, int error, const char *fmt, ...) {
137     va_list ap;
138     va_start(ap, fmt);
139     toku_ydb_error_all_cases(env, error, false, true, fmt, ap);
140     va_end(ap);
141 }
142