00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #include <signal.h>
00062
00063 #include "gwlib/gwlib.h"
00064 #include "msg.h"
00065 #include "heartbeat.h"
00066
00067
00068
00069
00070
00071 struct hb_info {
00072 hb_send_func_t *send_func;
00073 double freq;
00074 hb_load_func_t *load_func;
00075 long thread;
00076 volatile sig_atomic_t running;
00077 };
00078
00079
00080 static List *heartbeats = NULL;
00081
00082
00083
00084
00085 static int find_hb(void *item, void *pattern)
00086 {
00087 long *threadnrp;
00088 struct hb_info *info;
00089
00090 info = item;
00091 threadnrp = pattern;
00092
00093 return info->thread == *threadnrp;
00094 }
00095
00096 static void heartbeat_thread(void *arg)
00097 {
00098 struct hb_info *info;
00099 time_t last_hb;
00100
00101 info = arg;
00102 last_hb = 0;
00103
00104 while (info->running) {
00105 Msg *msg;
00106
00107 gwthread_sleep(info->freq);
00108
00109
00110
00111
00112
00113
00114
00115 if (difftime(time(NULL), last_hb) < info->freq / 2)
00116 continue;
00117
00118 msg = msg_create(heartbeat);
00119 if (NULL != info->load_func)
00120 msg->heartbeat.load = info->load_func();
00121 info->send_func(msg);
00122 last_hb = time(NULL);
00123 }
00124 }
00125
00126 long heartbeat_start(hb_send_func_t *send_func, double freq,
00127 hb_load_func_t *load_func)
00128 {
00129 struct hb_info *info;
00130
00131
00132 if (send_func == NULL)
00133 return -1;
00134
00135 info = gw_malloc(sizeof(*info));
00136 info->send_func = send_func;
00137 info->freq = (freq <= 0 ? DEFAULT_HEARTBEAT : freq);
00138 info->load_func = load_func;
00139 info->running = 1;
00140 info->thread = gwthread_create(heartbeat_thread, info);
00141 if (info->thread >= 0) {
00142 if (heartbeats == NULL)
00143 heartbeats = gwlist_create();
00144 gwlist_append(heartbeats, info);
00145 return info->thread;
00146 } else {
00147 gw_free(info);
00148 return -1;
00149 }
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 void heartbeat_stop(long hb_thread)
00161 {
00162 List *matching_info;
00163 struct hb_info *info;
00164
00165
00166
00167
00168
00169 if (heartbeats == NULL)
00170 return;
00171
00172 if (hb_thread == ALL_HEARTBEATS) {
00173 while (NULL != (info = gwlist_extract_first(heartbeats))) {
00174 gw_assert(info);
00175 info->running = 0;
00176 gwthread_wakeup(info->thread);
00177 gwthread_join(info->thread);
00178 gw_free(info);
00179 }
00180 } else {
00181 matching_info = gwlist_extract_matching(heartbeats, &hb_thread, find_hb);
00182 if (matching_info == NULL) {
00183 warning(0, "Could not stop heartbeat %ld: not found.", hb_thread);
00184 return;
00185 }
00186 gw_assert(gwlist_len(matching_info) == 1);
00187 info = gwlist_extract_first(matching_info);
00188 gwlist_destroy(matching_info, NULL);
00189
00190 info->running = 0;
00191 gwthread_wakeup(hb_thread);
00192 gwthread_join(hb_thread);
00193 gw_free(info);
00194 }
00195 if (gwlist_len(heartbeats) == 0) {
00196 gwlist_destroy(heartbeats, NULL);
00197 heartbeats = NULL;
00198 }
00199 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.