root/attrd/attrd_common.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. attrd_shutting_down
  2. attrd_shutdown
  3. attrd_init_mainloop
  4. attrd_run_mainloop
  5. attrd_mainloop_running
  6. attrd_quit_mainloop
  7. attrd_ipc_accept
  8. attrd_ipc_created
  9. attrd_ipc_closed
  10. attrd_ipc_destroy
  11. attrd_init_ipc
  12. attrd_cib_disconnect
  13. attrd_value_needs_expansion
  14. attrd_expand_value
  15. attrd_failure_regex

   1 /*
   2  * Copyright (C) 2004-2017 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This source code is licensed under the GNU General Public License version 2
   5  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   6  */
   7 
   8 #include <crm_internal.h>
   9 
  10 #include <stdio.h>
  11 #include <errno.h>
  12 #include <glib.h>
  13 #include <regex.h>
  14 #include <sys/types.h>
  15 
  16 #include <crm/crm.h>
  17 #include <crm/common/ipcs.h>
  18 #include <crm/common/mainloop.h>
  19 
  20 #include <attrd_common.h>
  21 
  22 cib_t *the_cib = NULL;
  23 
  24 static gboolean shutting_down = FALSE;
  25 static GMainLoop *mloop = NULL;
  26 
  27 /*!
  28  * \internal
  29  * \brief Check whether we're currently shutting down
  30  *
  31  * \return TRUE if shutting down, FALSE otherwise
  32  */
  33 gboolean
  34 attrd_shutting_down()
     /* [previous][next][first][last][top][bottom][index][help] */
  35 {
  36     return shutting_down;
  37 }
  38 
  39 /*!
  40  * \internal
  41  * \brief  Exit (using mainloop or not, as appropriate)
  42  *
  43  * \param[in] nsig  Ignored
  44  */
  45 void
  46 attrd_shutdown(int nsig) {
     /* [previous][next][first][last][top][bottom][index][help] */
  47     crm_info("Shutting down");
  48 
  49     shutting_down = TRUE;
  50 
  51     if ((mloop != NULL) && g_main_is_running(mloop)) {
  52         g_main_quit(mloop);
  53     } else {
  54         crm_exit(pcmk_ok);
  55     }
  56 }
  57 
  58 /*!
  59  * \internal
  60  * \brief Create a main loop for attrd
  61  */
  62 void
  63 attrd_init_mainloop()
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65     mloop = g_main_new(FALSE);
  66 }
  67 
  68 /*!
  69  * \internal
  70  * \brief Run attrd main loop
  71  */
  72 void
  73 attrd_run_mainloop()
     /* [previous][next][first][last][top][bottom][index][help] */
  74 {
  75     g_main_run(mloop);
  76 }
  77 
  78 /*!
  79  * \internal
  80  * \brief Check whether attrd main loop is running
  81  *
  82  * \return TRUE if main loop is running, FALSE otherwise
  83  */
  84 gboolean
  85 attrd_mainloop_running()
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87     return (mloop != NULL) && g_main_is_running(mloop);
  88 }
  89 
  90 /*!
  91  * \internal
  92  * \brief Quit attrd mainloop
  93  */
  94 void
  95 attrd_quit_mainloop()
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97     g_main_quit(mloop);
  98 }
  99 
 100 /*!
 101  * \internal
 102  * \brief Accept a new client IPC connection
 103  *
 104  * \param[in] c    New connection
 105  * \param[in] uid  Client user id
 106  * \param[in] gid  Client group id
 107  *
 108  * \return pcmk_ok on success, -errno otherwise
 109  */
 110 static int32_t
 111 attrd_ipc_accept(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
     /* [previous][next][first][last][top][bottom][index][help] */
 112 {
 113     crm_trace("New client connection %p", c);
 114     if (shutting_down) {
 115         crm_info("Ignoring new connection from pid %d during shutdown",
 116                  crm_ipcs_client_pid(c));
 117         return -EPERM;
 118     }
 119 
 120     if (crm_client_new(c, uid, gid) == NULL) {
 121         return -EIO;
 122     }
 123     return pcmk_ok;
 124 }
 125 
 126 /*!
 127  * \internal
 128  * \brief Callback for successful client connection
 129  *
 130  * \param[in] c  New connection
 131  */
 132 static void
 133 attrd_ipc_created(qb_ipcs_connection_t *c)
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135     crm_trace("Client connection %p accepted", c);
 136 }
 137 
 138 /*!
 139  * \internal
 140  * \brief Destroy a client IPC connection
 141  *
 142  * \param[in] c  Connection to destroy
 143  *
 144  * \return FALSE (i.e. do not re-run this callback)
 145  */
 146 static int32_t
 147 attrd_ipc_closed(qb_ipcs_connection_t *c)
     /* [previous][next][first][last][top][bottom][index][help] */
 148 {
 149     crm_client_t *client = crm_client_get(c);
 150 
 151     if (client == NULL) {
 152         crm_trace("Ignoring request to clean up unknown connection %p", c);
 153     } else {
 154         crm_trace("Cleaning up closed client connection %p", c);
 155         crm_client_destroy(client);
 156     }
 157     return FALSE;
 158 }
 159 
 160 /*!
 161  * \internal
 162  * \brief Destroy a client IPC connection
 163  *
 164  * \param[in] c  Connection to destroy
 165  *
 166  * \note We handle a destroyed connection the same as a closed one,
 167  *       but we need a separate handler because the return type is different.
 168  */
 169 static void
 170 attrd_ipc_destroy(qb_ipcs_connection_t *c)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172     crm_trace("Destroying client connection %p", c);
 173     attrd_ipc_closed(c);
 174 }
 175 
 176 /*!
 177  * \internal
 178  * \brief Set up attrd IPC communication
 179  *
 180  * \param[out] ipcs         Will be set to newly allocated server connection
 181  * \param[in]  dispatch_fn  Handler for new messages on connection
 182  */
 183 void
 184 attrd_init_ipc(qb_ipcs_service_t **ipcs, qb_ipcs_msg_process_fn dispatch_fn)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186 
 187     static struct qb_ipcs_service_handlers ipc_callbacks = {
 188         .connection_accept = attrd_ipc_accept,
 189         .connection_created = attrd_ipc_created,
 190         .msg_process = NULL,
 191         .connection_closed = attrd_ipc_closed,
 192         .connection_destroyed = attrd_ipc_destroy
 193     };
 194 
 195     ipc_callbacks.msg_process = dispatch_fn;
 196     attrd_ipc_server_init(ipcs, &ipc_callbacks);
 197 }
 198 
 199 void
 200 attrd_cib_disconnect()
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202     if (the_cib) {
 203         the_cib->cmds->signoff(the_cib);
 204         cib_delete(the_cib);
 205         the_cib = NULL;
 206     }
 207 }
 208 
 209 /* strlen("value") */
 210 #define plus_plus_len (5)
 211 
 212 /*!
 213  * \internal
 214  * \brief  Check whether an attribute value should be expanded
 215  *
 216  * \param[in] value  Attribute value to check
 217  *
 218  * \return TRUE if value needs expansion, FALSE otherwise
 219  */
 220 gboolean
 221 attrd_value_needs_expansion(const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
 222 {
 223     return ((strlen(value) >= (plus_plus_len + 2))
 224            && (value[plus_plus_len] == '+')
 225            && ((value[plus_plus_len + 1] == '+')
 226                || (value[plus_plus_len + 1] == '=')));
 227 }
 228 
 229 /*!
 230  * \internal
 231  * \brief Expand an increment expression into an integer
 232  *
 233  * \param[in] value      Attribute increment expression to expand
 234  * \param[in] old_value  Previous value of attribute
 235  *
 236  * \return Expanded value
 237  */
 238 int
 239 attrd_expand_value(const char *value, const char *old_value)
     /* [previous][next][first][last][top][bottom][index][help] */
 240 {
 241     int offset = 1;
 242     int int_value = char2score(old_value);
 243 
 244     if (value[plus_plus_len + 1] != '+') {
 245         const char *offset_s = value + (plus_plus_len + 2);
 246 
 247         offset = char2score(offset_s);
 248     }
 249     int_value += offset;
 250 
 251     if (int_value > INFINITY) {
 252         int_value = INFINITY;
 253     }
 254     return int_value;
 255 }
 256 
 257 /*!
 258  * \internal
 259  * \brief Create regular expression matching failure-related attributes
 260  *
 261  * \param[out] regex  Where to store created regular expression
 262  * \param[in]  rsc    Name of resource to clear (or NULL for all)
 263  * \param[in]  op     Operation to clear if rsc is specified (or NULL for all)
 264  * \param[in]  interval  Interval of operation to clear if op is specified
 265  *
 266  * \return pcmk_ok on success, -EINVAL if arguments are invalid
 267  *
 268  * \note The caller is responsible for freeing the result with regfree().
 269  */
 270 int
 271 attrd_failure_regex(regex_t *regex, const char *rsc, const char *op,
     /* [previous][next][first][last][top][bottom][index][help] */
 272                     int interval)
 273 {
 274     char *pattern = NULL;
 275     int rc;
 276 
 277     /* Create a pattern that matches desired attributes */
 278 
 279     if (rsc == NULL) {
 280         pattern = strdup(ATTRD_RE_CLEAR_ALL);
 281     } else if (op == NULL) {
 282         pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc);
 283     } else {
 284         pattern = crm_strdup_printf(ATTRD_RE_CLEAR_OP,
 285                                     rsc, op, interval);
 286     }
 287 
 288     /* Compile pattern into regular expression */
 289     crm_trace("Clearing attributes matching %s", pattern);
 290     rc = regcomp(regex, pattern, REG_EXTENDED|REG_NOSUB);
 291     free(pattern);
 292 
 293     return (rc == 0)? pcmk_ok : -EINVAL;
 294 }

/* [previous][next][first][last][top][bottom][index][help] */