LCOV - code coverage report
Current view: top level - lib - ovsdb-error.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 65 104 62.5 %
Date: 2016-09-14 01:02:56 Functions: 11 13 84.6 %
Branches: 21 38 55.3 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2009, 2010, 2011, 2012, 2016 Nicira, Inc.
       2                 :            :  *
       3                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       4                 :            :  * you may not use this file except in compliance with the License.
       5                 :            :  * You may obtain a copy of the License at:
       6                 :            :  *
       7                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       8                 :            :  *
       9                 :            :  * Unless required by applicable law or agreed to in writing, software
      10                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      11                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :            :  * See the License for the specific language governing permissions and
      13                 :            :  * limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <config.h>
      17                 :            : 
      18                 :            : #include "ovsdb-error.h"
      19                 :            : 
      20                 :            : #include <inttypes.h>
      21                 :            : 
      22                 :            : #include "backtrace.h"
      23                 :            : #include "openvswitch/dynamic-string.h"
      24                 :            : #include "openvswitch/json.h"
      25                 :            : #include "util.h"
      26                 :            : #include "openvswitch/vlog.h"
      27                 :            : 
      28                 :      22484 : VLOG_DEFINE_THIS_MODULE(ovsdb_error);
      29                 :            : 
      30                 :            : struct ovsdb_error {
      31                 :            :     const char *tag;            /* String for "error" member. */
      32                 :            :     char *details;              /* String for "details" member. */
      33                 :            :     char *syntax;               /* String for "syntax" member. */
      34                 :            :     int errno_;                 /* Unix errno value, 0 if none. */
      35                 :            : };
      36                 :            : 
      37                 :            : static struct ovsdb_error *
      38                 :      12611 : ovsdb_error_valist(const char *tag, const char *details, va_list args)
      39                 :            : {
      40                 :      12611 :     struct ovsdb_error *error = xmalloc(sizeof *error);
      41         [ +  + ]:      12611 :     error->tag = tag ? tag : "ovsdb error";
      42         [ +  - ]:      12611 :     error->details = details ? xvasprintf(details, args) : NULL;
      43                 :      12611 :     error->syntax = NULL;
      44                 :      12611 :     error->errno_ = 0;
      45                 :      12611 :     return error;
      46                 :            : }
      47                 :            : 
      48                 :            : struct ovsdb_error *
      49                 :        320 : ovsdb_error(const char *tag, const char *details, ...)
      50                 :            : {
      51                 :            :     struct ovsdb_error *error;
      52                 :            :     va_list args;
      53                 :            : 
      54                 :        320 :     va_start(args, details);
      55                 :        320 :     error = ovsdb_error_valist(tag, details, args);
      56                 :        320 :     va_end(args);
      57                 :            : 
      58                 :        320 :     return error;
      59                 :            : }
      60                 :            : 
      61                 :            : struct ovsdb_error *
      62                 :          3 : ovsdb_io_error(int errno_, const char *details, ...)
      63                 :            : {
      64                 :            :     struct ovsdb_error *error;
      65                 :            :     va_list args;
      66                 :            : 
      67                 :          3 :     va_start(args, details);
      68                 :          3 :     error = ovsdb_error_valist("I/O error", details, args);
      69                 :          3 :     va_end(args);
      70                 :            : 
      71                 :          3 :     error->errno_ = errno_;
      72                 :            : 
      73                 :          3 :     return error;
      74                 :            : }
      75                 :            : 
      76                 :            : struct ovsdb_error *
      77                 :      12288 : ovsdb_syntax_error(const struct json *json, const char *tag,
      78                 :            :                    const char *details, ...)
      79                 :            : {
      80                 :            :     struct ovsdb_error *error;
      81                 :            :     va_list args;
      82                 :            : 
      83                 :      12288 :     va_start(args, details);
      84         [ +  + ]:      12288 :     error = ovsdb_error_valist(tag ? tag : "syntax error", details, args);
      85                 :      12288 :     va_end(args);
      86                 :            : 
      87         [ +  + ]:      12288 :     if (json) {
      88                 :            :         /* XXX this is much too much information in some cases */
      89                 :      12281 :         error->syntax = json_to_string(json, JSSF_SORT);
      90                 :            :     }
      91                 :            : 
      92                 :      12288 :     return error;
      93                 :            : }
      94                 :            : 
      95                 :            : struct ovsdb_error *
      96                 :          0 : ovsdb_wrap_error(struct ovsdb_error *error, const char *details, ...)
      97                 :            : {
      98                 :            :     va_list args;
      99                 :            :     char *msg;
     100                 :            : 
     101                 :          0 :     va_start(args, details);
     102                 :          0 :     msg = xvasprintf(details, args);
     103                 :          0 :     va_end(args);
     104                 :            : 
     105         [ #  # ]:          0 :     if (error->details) {
     106                 :          0 :         char *new = xasprintf("%s: %s", msg, error->details);
     107                 :          0 :         free(error->details);
     108                 :          0 :         error->details = new;
     109                 :          0 :         free(msg);
     110                 :            :     } else {
     111                 :          0 :         error->details = msg;
     112                 :            :     }
     113                 :            : 
     114                 :          0 :     return error;
     115                 :            : }
     116                 :            : 
     117                 :            : /* Returns an ovsdb_error that represents an internal error for file name
     118                 :            :  * 'file' and line number 'line', with 'details' (formatted as with printf())
     119                 :            :  * as the associated message.  The caller is responsible for freeing the
     120                 :            :  * returned error.
     121                 :            :  *
     122                 :            :  * If 'inner_error' is nonnull then the returned error is wrapped around
     123                 :            :  * 'inner_error'.  Takes ownership of 'inner_error'.  */
     124                 :            : struct ovsdb_error *
     125                 :          0 : ovsdb_internal_error(struct ovsdb_error *inner_error,
     126                 :            :                      const char *file, int line, const char *details, ...)
     127                 :            : {
     128                 :          0 :     struct ds ds = DS_EMPTY_INITIALIZER;
     129                 :            :     struct backtrace backtrace;
     130                 :            :     struct ovsdb_error *error;
     131                 :            :     va_list args;
     132                 :            : 
     133                 :          0 :     ds_put_format(&ds, "%s:%d:", file, line);
     134                 :            : 
     135         [ #  # ]:          0 :     if (details) {
     136                 :          0 :         ds_put_char(&ds, ' ');
     137                 :          0 :         va_start(args, details);
     138                 :          0 :         ds_put_format_valist(&ds, details, args);
     139                 :          0 :         va_end(args);
     140                 :            :     }
     141                 :            : 
     142                 :          0 :     backtrace_capture(&backtrace);
     143         [ #  # ]:          0 :     if (backtrace.n_frames) {
     144                 :            :         int i;
     145                 :            : 
     146                 :          0 :         ds_put_cstr(&ds, " (backtrace:");
     147         [ #  # ]:          0 :         for (i = 0; i < backtrace.n_frames; i++) {
     148                 :          0 :             ds_put_format(&ds, " 0x%08"PRIxPTR, backtrace.frames[i]);
     149                 :            :         }
     150                 :          0 :         ds_put_char(&ds, ')');
     151                 :            :     }
     152                 :            : 
     153                 :          0 :     ds_put_format(&ds, " (%s %s)", program_name, VERSION);
     154                 :            : 
     155         [ #  # ]:          0 :     if (inner_error) {
     156                 :          0 :         char *s = ovsdb_error_to_string(inner_error);
     157                 :          0 :         ds_put_format(&ds, " (generated from: %s)", s);
     158                 :          0 :         free(s);
     159                 :            : 
     160                 :          0 :         ovsdb_error_destroy(inner_error);
     161                 :            :     }
     162                 :            : 
     163                 :          0 :     error = ovsdb_error("internal error", "%s", ds_cstr(&ds));
     164                 :            : 
     165                 :          0 :     ds_destroy(&ds);
     166                 :            : 
     167                 :          0 :     return error;
     168                 :            : }
     169                 :            : 
     170                 :            : void
     171                 :      27789 : ovsdb_error_destroy(struct ovsdb_error *error)
     172                 :            : {
     173         [ +  + ]:      27789 :     if (error) {
     174                 :      12618 :         free(error->details);
     175                 :      12618 :         free(error->syntax);
     176                 :      12618 :         free(error);
     177                 :            :     }
     178                 :      27789 : }
     179                 :            : 
     180                 :            : struct ovsdb_error *
     181                 :       1531 : ovsdb_error_clone(const struct ovsdb_error *old)
     182                 :            : {
     183         [ +  + ]:       1531 :     if (old) {
     184                 :          7 :         struct ovsdb_error *new = xmalloc(sizeof *new);
     185                 :          7 :         new->tag = old->tag;
     186                 :          7 :         new->details = nullable_xstrdup(old->details);
     187                 :          7 :         new->syntax = nullable_xstrdup(old->syntax);
     188                 :          7 :         new->errno_ = old->errno_;
     189                 :          7 :         return new;
     190                 :            :     } else {
     191                 :       1524 :         return NULL;
     192                 :            :     }
     193                 :            : }
     194                 :            : 
     195                 :            : struct json *
     196                 :        240 : ovsdb_error_to_json(const struct ovsdb_error *error)
     197                 :            : {
     198                 :        240 :     struct json *json = json_object_create();
     199                 :        240 :     json_object_put_string(json, "error", error->tag);
     200         [ +  - ]:        240 :     if (error->details) {
     201                 :        240 :         json_object_put_string(json, "details", error->details);
     202                 :            :     }
     203         [ +  + ]:        240 :     if (error->syntax) {
     204                 :         32 :         json_object_put_string(json, "syntax", error->syntax);
     205                 :            :     }
     206         [ -  + ]:        240 :     if (error->errno_) {
     207                 :          0 :         json_object_put_string(json, "io-error",
     208                 :            :                                ovs_retval_to_string(error->errno_));
     209                 :            :     }
     210                 :        240 :     return json;
     211                 :            : }
     212                 :            : 
     213                 :            : char *
     214                 :        178 : ovsdb_error_to_string(const struct ovsdb_error *error)
     215                 :            : {
     216                 :        178 :     struct ds ds = DS_EMPTY_INITIALIZER;
     217         [ +  + ]:        178 :     if (error->syntax) {
     218                 :         68 :         ds_put_format(&ds, "syntax \"%s\": ", error->syntax);
     219                 :            :     }
     220                 :        178 :     ds_put_cstr(&ds, error->tag);
     221         [ +  - ]:        178 :     if (error->details) {
     222                 :        178 :         ds_put_format(&ds, ": %s", error->details);
     223                 :            :     }
     224         [ +  + ]:        178 :     if (error->errno_) {
     225                 :          3 :         ds_put_format(&ds, " (%s)", ovs_retval_to_string(error->errno_));
     226                 :            :     }
     227                 :        178 :     return ds_steal_cstr(&ds);
     228                 :            : }
     229                 :            : 
     230                 :            : const char *
     231                 :         98 : ovsdb_error_get_tag(const struct ovsdb_error *error)
     232                 :            : {
     233                 :         98 :     return error->tag;
     234                 :            : }
     235                 :            : 
     236                 :            : /* If 'error' is nonnull, logs it as an error and frees it.  To be used in
     237                 :            :  * situations where an error should never occur, but an 'ovsdb_error *' gets
     238                 :            :  * passed back anyhow. */
     239                 :            : void
     240                 :      27809 : ovsdb_error_assert(struct ovsdb_error *error)
     241                 :            : {
     242         [ -  + ]:      27809 :     if (error) {
     243                 :            :         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
     244                 :          0 :         char *s = ovsdb_error_to_string(error);
     245         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "unexpected ovsdb error: %s", s);
     246                 :          0 :         free(s);
     247                 :          0 :         ovsdb_error_destroy(error);
     248                 :            :     }
     249                 :      27809 : }

Generated by: LCOV version 1.12