multipath-tools: Introducing multipath C API
[multipath-tools/.git] / libdmmp / libdmmp_private.h
1 /*
2  * Copyright (C) 2015 - 2016 Red Hat, Inc.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Author: Gris Ge <fge@redhat.com>
18  *         Todd Gill <tgill@redhat.com>
19  */
20
21 #ifndef _LIB_DMMP_PRIVATE_H_
22 #define _LIB_DMMP_PRIVATE_H_
23
24 /*
25  * Notes:
26  *      Internal/Private functions does not check input argument but using
27  *      assert() to abort if NULL pointer found in argument.
28  */
29
30 #include <stdint.h>
31 #include <string.h>
32 #include <assert.h>
33 #include <json.h>
34
35 #include "libdmmp/libdmmp.h"
36
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40
41 #define _good(rc, rc_val, out) \
42         do { \
43                 rc_val = rc; \
44                 if (rc_val != DMMP_OK) \
45                         goto out; \
46         } while(0)
47
48 #define _DMMP_PATH_GROUP_ID_UNKNOWN     0
49
50 DMMP_DLL_LOCAL struct _num_str_conv {
51         const uint32_t value;
52         const char *str;
53 };
54
55 #define _dmmp_str_func_gen(func_name, var_type, var, conv_array) \
56 const char *func_name(var_type var) { \
57         size_t i = 0; \
58         uint32_t tmp_var = var & UINT32_MAX; \
59         /* In the whole libdmmp, we don't have negative value */ \
60         for (; i < sizeof(conv_array)/sizeof(conv_array[0]); ++i) { \
61                 if ((conv_array[i].value) == tmp_var) \
62                         return conv_array[i].str; \
63         } \
64         return "Invalid argument"; \
65 }
66
67 #define _dmmp_str_conv_func_gen(func_name, ctx, var_name, out_type, \
68                                 unknown_value, conv_array) \
69 static out_type func_name(struct dmmp_context *ctx, const char *var_name) { \
70         size_t i = 0; \
71         for (; i < sizeof(conv_array)/sizeof(conv_array[0]); ++i) { \
72                 if (strcmp(conv_array[i].str, var_name) == 0) \
73                         return conv_array[i].value; \
74         } \
75         _warn(ctx, "Got unknown " #var_name ": '%s'", var_name); \
76         return unknown_value; \
77 }
78
79 #define _json_obj_get_value(ctx, j_obj, out_value, key, value_type, \
80                             value_func, rc, out) \
81 do { \
82         json_type j_type = json_type_null; \
83         json_object *j_obj_tmp = NULL; \
84         if (json_object_object_get_ex(j_obj, key, &j_obj_tmp) != TRUE) { \
85                 _error(ctx, "Invalid JSON output from multipathd IPC: " \
86                        "key '%s' not found", key); \
87                 rc = DMMP_ERR_IPC_ERROR; \
88                 goto out; \
89         } \
90         if (j_obj_tmp == NULL) { \
91                 _error(ctx, "BUG: Got NULL j_obj_tmp from " \
92                        "json_object_object_get_ex() while it return TRUE"); \
93                 rc = DMMP_ERR_BUG; \
94                 goto out; \
95         } \
96         j_type = json_object_get_type(j_obj_tmp); \
97         if (j_type != value_type) { \
98                 _error(ctx, "Invalid value type for key'%s' of JSON output " \
99                        "from multipathd IPC. Should be %s(%d), " \
100                        "but got %s(%d)", key, json_type_to_name(value_type), \
101                        value_type, json_type_to_name(j_type), j_type); \
102                 rc = DMMP_ERR_IPC_ERROR; \
103                 goto out; \
104         } \
105         out_value = value_func(j_obj_tmp); \
106 } while(0);
107
108 DMMP_DLL_LOCAL int _dmmp_ipc_exec(struct dmmp_context *ctx, const char *cmd,
109                                   char **output);
110
111 DMMP_DLL_LOCAL struct dmmp_mpath *_dmmp_mpath_new(void);
112 DMMP_DLL_LOCAL struct dmmp_path_group *_dmmp_path_group_new(void);
113 DMMP_DLL_LOCAL struct dmmp_path *_dmmp_path_new(void);
114
115 DMMP_DLL_LOCAL int _dmmp_mpath_update(struct dmmp_context *ctx,
116                                       struct dmmp_mpath *dmmp_mp,
117                                       json_object *j_obj_map);
118 DMMP_DLL_LOCAL int _dmmp_path_group_update(struct dmmp_context *ctx,
119                                            struct dmmp_path_group *dmmp_pg,
120                                            json_object *j_obj_pg);
121 DMMP_DLL_LOCAL int _dmmp_path_update(struct dmmp_context *ctx,
122                                      struct dmmp_path *dmmp_p,
123                                      json_object *j_obj_p);
124
125 DMMP_DLL_LOCAL void _dmmp_mpath_free(struct dmmp_mpath *dmmp_mp);
126 DMMP_DLL_LOCAL void _dmmp_path_group_free(struct dmmp_path_group *dmmp_pg);
127 DMMP_DLL_LOCAL void _dmmp_path_group_array_free
128         (struct dmmp_path_group **dmmp_pgs, uint32_t dmmp_pg_count);
129 DMMP_DLL_LOCAL void _dmmp_path_free(struct dmmp_path *dmmp_p);
130 DMMP_DLL_LOCAL void _dmmp_log(struct dmmp_context *ctx, int priority,
131                               const char *file, int line,
132                               const char *func_name,
133                               const char *format, ...);
134 DMMP_DLL_LOCAL void _dmmp_log_err_str(struct dmmp_context *ctx, int rc);
135
136 DMMP_DLL_LOCAL void _dmmp_log_stderr(struct dmmp_context *ctx, int priority,
137                                      const char *file, int line,
138                                      const char *func_name, const char *format,
139                                      va_list args);
140
141
142 #define _dmmp_log_cond(ctx, prio, arg...) \
143         do { \
144                 if (dmmp_context_log_priority_get(ctx) >= prio) \
145                         _dmmp_log(ctx, prio, __FILE__, __LINE__, __FUNCTION__, \
146                                   ## arg); \
147         } while (0)
148
149 #define _debug(ctx, arg...) \
150         _dmmp_log_cond(ctx, DMMP_LOG_PRIORITY_DEBUG, ## arg)
151 #define _info(ctx, arg...) \
152         _dmmp_log_cond(ctx, DMMP_LOG_PRIORITY_INFO, ## arg)
153 #define _warn(ctx, arg...) \
154         _dmmp_log_cond(ctx, DMMP_LOG_PRIORITY_WARNING, ## arg)
155 #define _error(ctx, arg...) \
156         _dmmp_log_cond(ctx, DMMP_LOG_PRIORITY_ERROR, ## arg)
157
158 /*
159  * Check pointer returned by malloc() or strdup(), if NULL, set
160  * rc as DMMP_ERR_NO_MEMORY, report error and goto goto_out.
161  */
162 #define _dmmp_alloc_null_check(ctx, ptr, rc, goto_out) \
163         do { \
164                 if (ptr == NULL) { \
165                         rc = DMMP_ERR_NO_MEMORY; \
166                         _error(ctx, dmmp_strerror(rc)); \
167                         goto goto_out; \
168                 } \
169         } while(0)
170
171 #define _dmmp_null_or_empty_str_check(ctx, var, rc, goto_out) \
172         do { \
173                 if (var == NULL) { \
174                         rc = DMMP_ERR_BUG; \
175                         _error(ctx, "BUG: Got NULL " #var); \
176                         goto goto_out; \
177                 } \
178                 if (strlen(var) == 0) { \
179                         rc = DMMP_ERR_BUG; \
180                         _error(ctx, "BUG: Got empty " #var); \
181                         goto goto_out; \
182                 } \
183         } while(0)
184
185 #define _dmmp_getter_func_gen(func_name, struct_name, struct_data, \
186                               prop_name, prop_type) \
187         prop_type func_name(struct_name *struct_data) \
188         { \
189                 assert(struct_data != NULL); \
190                 return struct_data->prop_name; \
191         }
192
193 #define _dmmp_array_free_func_gen(func_name, struct_name, struct_free_func) \
194         void func_name(struct_name **ptr_array, uint32_t ptr_count) \
195         { \
196                 uint32_t i = 0; \
197                 if (ptr_array == NULL) \
198                         return; \
199                 for (; i < ptr_count; ++i) \
200                         struct_free_func(ptr_array[i]); \
201                 free(ptr_array); \
202         }
203
204 #ifdef __cplusplus
205 } /* End of extern "C" */
206 #endif
207
208 #endif /* End of _LIB_DMMP_PRIVATE_H_ */