X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Futils_ovs.c;h=0ee05e0044344fe818b135d65631a49240f1a674;hp=2f7baea00129df218df3e8bf1cdce29d1a36d686;hb=a9e50e9e30ecde17e167e271060c8183bfcbf407;hpb=9655d4a6d9fa2c4f02032759b831e93933d68bd9 diff --git a/src/utils_ovs.c b/src/utils_ovs.c index 2f7baea0..0ee05e00 100644 --- a/src/utils_ovs.c +++ b/src/utils_ovs.c @@ -3,14 +3,17 @@ * * Copyright(c) 2016 Intel Corporation. All rights reserved. * - * Permission is hereby granted, free of charge, to any person obtaining a copy of + * Permission is hereby granted, free of charge, to any person obtaining a copy + *of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is furnished to do + * of the Software, and to permit persons to whom the Software is furnished to + *do * so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in all + * The above copyright notice and this permission notice shall be included in + *all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR @@ -102,6 +105,7 @@ #define OVS_DB_POLL_READ_BLOCK_SIZE 512 /* read block size (bytes) */ #define OVS_DB_DEFAULT_DB_NAME "Open_vSwitch" +#define OVS_DB_EVENT_NONE 0 #define OVS_DB_EVENT_TIMEOUT 5 /* event thread timeout (sec) */ #define OVS_DB_EVENT_TERMINATE 1 #define OVS_DB_EVENT_CONN_ESTABLISHED 2 @@ -260,12 +264,11 @@ static void ovs_db_callback_remove(ovs_db_t *pdb, ovs_callback_t *del_cb) { /* Remove all callbacks form OVS DB object */ static void ovs_db_callback_remove_all(ovs_db_t *pdb) { pthread_mutex_lock(&pdb->mutex); - for (ovs_callback_t *del_cb = pdb->remote_cb; pdb->remote_cb; - del_cb = pdb->remote_cb) { + while (pdb->remote_cb != NULL) { + ovs_callback_t *del_cb = pdb->remote_cb; pdb->remote_cb = del_cb->next; - free(del_cb); + sfree(del_cb); } - pdb->remote_cb = NULL; pthread_mutex_unlock(&pdb->mutex); } @@ -314,8 +317,7 @@ static int ovs_db_data_send(const ovs_db_t *pdb, const char *data, size_t len) { */ static yajl_gen_status ovs_yajl_gen_tstring(yajl_gen hander, const char *string) { - return yajl_gen_string(hander, (const unsigned char *)string, - strlen(string)); + return yajl_gen_string(hander, (const unsigned char *)string, strlen(string)); } /* Add YAJL value into YAJL generator handle (JSON object) @@ -558,7 +560,7 @@ static int ovs_db_json_data_process(ovs_db_t *pdb, const char *data, return -1; sstrncpy(sjson, data, len + 1); - OVS_DEBUG("[len=%zu] %s", len, sjson); + OVS_DEBUG("[len=%" PRIsz "] %s", len, sjson); /* parse json data */ jnode = yajl_tree_parse(sjson, yajl_errbuf, sizeof(yajl_errbuf)); @@ -749,21 +751,18 @@ static void ovs_db_reconnect(ovs_db_t *pdb) { } /* try to connect to the server */ for (struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next) { - char errbuff[OVS_ERROR_BUFF_SIZE]; int sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sock < 0) { - sstrerror(errno, errbuff, sizeof(errbuff)); - OVS_DEBUG("socket(): %s", errbuff); + OVS_DEBUG("socket(): %s", STRERRNO); continue; } if (connect(sock, rp->ai_addr, rp->ai_addrlen) < 0) { close(sock); - sstrerror(errno, errbuff, sizeof(errbuff)); - OVS_DEBUG("connect(): %s [family=%d]", errbuff, rp->ai_family); + OVS_DEBUG("connect(): %s [family=%d]", STRERRNO, rp->ai_family); } else { /* send notification to event thread */ - ovs_db_event_post(pdb, OVS_DB_EVENT_CONN_ESTABLISHED); pdb->sock = sock; + ovs_db_event_post(pdb, OVS_DB_EVENT_CONN_ESTABLISHED); break; } } @@ -794,12 +793,10 @@ static void *ovs_poll_worker(void *arg) { /* poll data */ while (ovs_db_poll_is_running(pdb)) { - char errbuff[OVS_ERROR_BUFF_SIZE]; poll_fd.fd = pdb->sock; int poll_ret = poll(&poll_fd, 1, /* ms */ OVS_DB_POLL_TIMEOUT * 1000); if (poll_ret < 0) { - sstrerror(errno, errbuff, sizeof(errbuff)); - OVS_ERROR("poll(): %s", errbuff); + OVS_ERROR("poll(): %s", STRERRNO); break; } else if (poll_ret == 0) { OVS_DEBUG("poll(): timeout"); @@ -825,8 +822,7 @@ static void *ovs_poll_worker(void *arg) { char buff[OVS_DB_POLL_READ_BLOCK_SIZE]; ssize_t nbytes = recv(poll_fd.fd, buff, sizeof(buff), 0); if (nbytes < 0) { - sstrerror(errno, errbuff, sizeof(errbuff)); - OVS_ERROR("recv(): %s", errbuff); + OVS_ERROR("recv(): %s", STRERRNO); /* read error? Try to reconnect */ close(poll_fd.fd); continue; @@ -867,26 +863,30 @@ static void *ovs_event_worker(void *arg) { ts.tv_sec += (OVS_DB_EVENT_TIMEOUT); int ret = pthread_cond_timedwait(&pdb->event_thread.cond, &pdb->event_thread.mutex, &ts); - if (!ret) { + if (!ret || ret == ETIMEDOUT) { /* handle the event */ OVS_DEBUG("handle event %d", pdb->event_thread.value); switch (pdb->event_thread.value) { case OVS_DB_EVENT_CONN_ESTABLISHED: if (pdb->cb.post_conn_init) pdb->cb.post_conn_init(pdb); + /* reset event */ + pdb->event_thread.value = OVS_DB_EVENT_NONE; break; case OVS_DB_EVENT_CONN_TERMINATED: if (pdb->cb.post_conn_terminate) pdb->cb.post_conn_terminate(); + /* reset event */ + pdb->event_thread.value = OVS_DB_EVENT_NONE; + break; + case OVS_DB_EVENT_NONE: + /* wait timeout */ + OVS_DEBUG("no event received (timeout)"); break; default: OVS_DEBUG("unknown event received"); break; } - } else if (ret == ETIMEDOUT) { - /* wait timeout */ - OVS_DEBUG("no event received (timeout)"); - continue; } else { /* unexpected error */ OVS_ERROR("pthread_cond_timedwait() failed"); @@ -900,7 +900,7 @@ static void *ovs_event_worker(void *arg) { /* Initialize EVENT thread */ static int ovs_db_event_thread_init(ovs_db_t *pdb) { - pdb->event_thread.tid = (pthread_t)-1; + pdb->event_thread.tid = (pthread_t){0}; /* init event thread condition variable */ if (pthread_cond_init(&pdb->event_thread.cond, NULL)) { return -1; @@ -932,11 +932,12 @@ static int ovs_db_event_thread_init(ovs_db_t *pdb) { return 0; } -/* Destroy EVENT thread */ -static int ovs_db_event_thread_destroy(ovs_db_t *pdb) { - if (pdb->event_thread.tid == (pthread_t)-1) - /* already destroyed */ +/* Terminate EVENT thread */ +static int ovs_db_event_thread_terminate(ovs_db_t *pdb) { + if (pthread_equal(pdb->event_thread.tid, (pthread_t){0})) { + /* already terminated */ return 0; + } ovs_db_event_post(pdb, OVS_DB_EVENT_TERMINATE); if (pthread_join(pdb->event_thread.tid, NULL) != 0) return -1; @@ -944,16 +945,21 @@ static int ovs_db_event_thread_destroy(ovs_db_t *pdb) { * performs some task (handles event) and releases it when * while sleeping. Thus, if event thread exits, the mutex * remains locked */ + pdb->event_thread.tid = (pthread_t){0}; pthread_mutex_unlock(&pdb->event_thread.mutex); + return 0; +} + +/* Destroy EVENT thread private data */ +static void ovs_db_event_thread_data_destroy(ovs_db_t *pdb) { + /* destroy mutex */ pthread_mutex_destroy(&pdb->event_thread.mutex); pthread_cond_destroy(&pdb->event_thread.cond); - pdb->event_thread.tid = (pthread_t)-1; - return 0; } /* Initialize POLL thread */ static int ovs_db_poll_thread_init(ovs_db_t *pdb) { - pdb->poll_thread.tid = (pthread_t)-1; + pdb->poll_thread.tid = (pthread_t){0}; /* init event thread mutex */ if (pthread_mutex_init(&pdb->poll_thread.mutex, NULL)) { return -1; @@ -971,10 +977,12 @@ static int ovs_db_poll_thread_init(ovs_db_t *pdb) { } /* Destroy POLL thread */ +/* XXX: Must hold pdb->mutex when calling! */ static int ovs_db_poll_thread_destroy(ovs_db_t *pdb) { - if (pdb->poll_thread.tid == (pthread_t)-1) + if (pthread_equal(pdb->poll_thread.tid, (pthread_t){0})) { /* already destroyed */ return 0; + } /* change thread state */ pthread_mutex_lock(&pdb->poll_thread.mutex); pdb->poll_thread.state = OVS_DB_POLL_STATE_EXITING; @@ -983,7 +991,7 @@ static int ovs_db_poll_thread_destroy(ovs_db_t *pdb) { if (pthread_join(pdb->poll_thread.tid, NULL) != 0) return -1; pthread_mutex_destroy(&pdb->poll_thread.mutex); - pdb->poll_thread.tid = (pthread_t)-1; + pdb->poll_thread.tid = (pthread_t){0}; return 0; } @@ -998,9 +1006,10 @@ ovs_db_t *ovs_db_init(const char *node, const char *service, return NULL; /* allocate db data & fill it */ - ovs_db_t *pdb = pdb = calloc(1, sizeof(*pdb)); + ovs_db_t *pdb = calloc(1, sizeof(*pdb)); if (pdb == NULL) return NULL; + pdb->sock = -1; /* store the OVS DB address */ sstrncpy(pdb->node, node, sizeof(pdb->node)); @@ -1042,7 +1051,6 @@ ovs_db_t *ovs_db_init(const char *node, const char *service, } /* init polling thread */ - pdb->sock = -1; if (ovs_db_poll_thread_init(pdb) < 0) { ovs_db_destroy(pdb); return NULL; @@ -1091,7 +1099,7 @@ int ovs_db_send_request(ovs_db_t *pdb, const char *method, const char *params, /* generate id field */ OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, "id"); uid = ovs_uid_generate(); - ssnprintf(uid_buff, sizeof(uid_buff), "%" PRIX64, uid); + snprintf(uid_buff, sizeof(uid_buff), "%" PRIX64, uid); OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, uid_buff); OVS_YAJL_CALL(yajl_gen_map_close, jgen); @@ -1177,7 +1185,7 @@ int ovs_db_table_cb_register(ovs_db_t *pdb, const char *tb_name, OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, OVS_DB_DEFAULT_DB_NAME); /* uid string */ - ssnprintf(uid_str, sizeof(uid_str), "%" PRIX64, new_cb->uid); + snprintf(uid_str, sizeof(uid_str), "%" PRIX64, new_cb->uid); OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, uid_str); /* */ @@ -1248,23 +1256,28 @@ int ovs_db_destroy(ovs_db_t *pdb) { if (pdb == NULL) return -1; + /* stop event thread */ + if (ovs_db_event_thread_terminate(pdb) < 0) { + OVS_ERROR("stop event thread failed"); + ovs_db_ret = -1; + } + /* try to lock the structure before releasing */ if ((ret = pthread_mutex_lock(&pdb->mutex))) { OVS_ERROR("pthread_mutex_lock() DB mutex lock failed (%d)", ret); return -1; } - /* stop poll thread */ - if (ovs_db_event_thread_destroy(pdb) < 0) { + /* stop poll thread and destroy thread's private data */ + if (ovs_db_poll_thread_destroy(pdb) < 0) { OVS_ERROR("destroy poll thread failed"); - ovs_db_ret = (-1); + ovs_db_ret = -1; } - /* stop event thread */ - if (ovs_db_poll_thread_destroy(pdb) < 0) { - OVS_ERROR("stop event thread failed"); - ovs_db_ret = (-1); - } + /* destroy event thread private data */ + ovs_db_event_thread_data_destroy(pdb); + + pthread_mutex_unlock(&pdb->mutex); /* unsubscribe callbacks */ ovs_db_callback_remove_all(pdb); @@ -1274,7 +1287,6 @@ int ovs_db_destroy(ovs_db_t *pdb) { close(pdb->sock); /* release DB handler */ - pthread_mutex_unlock(&pdb->mutex); pthread_mutex_destroy(&pdb->mutex); sfree(pdb); return ovs_db_ret;