1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: 1; c-basic-offset: 2 -*- */
2 /*
3 *
4 * Copyright (c) 2007 The Regents of the University of California. All
5 * rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * - Neither the name of the University nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32 #include "diskmanager_i.h"
33
34 char diskmanager_main_c_cvsid[] = "$Id: diskmanager_main.c,v 1.18 2009-06-11 06:04:35 mlukac Exp $";
35
36 static void diskmanager_shutdown(void *data)
37 {
38 //Do cleanup if necessary
39 exit(0);
40 }
41
42 int diskmanager_update(ssync_sub_t *sub, diskmanager_table_t *table, int count, void *data)
43 {
44 int i = 0;
45 diskmanager_state_t *dms = (diskmanager_state_t *) ssync_sub_data(sub);
46
47 for (i = 0; i < count; ++i) {
48 if (table[i].header.flow_id.src == my_node_id) {
49 elog(LOG_DEBUG(5), "pub from self... skipping");
50 continue;
51 }
52 diskmanager_global_state_t *dgs = &(table[i].diskmanager);
53 _dqueue_get_or_init(dms, table[i].header.flow_id.src, dgs->seqno, dgs->diskfull_percent);
54 elog(LOG_NOTICE,"Got seqno = %-6i from %d",dgs->seqno,table[i].header.flow_id.src);
55 }
56
57 return EVENT_RENEW;
58 }
59
60 float get_free_diskspace_percent(diskmanager_state_t *d)
61 {
62 struct statvfs fiData;
63 // struct statvfs *fpData;
64 char fnPath[10]=COMPACT_FLASH_DIRECTORY;
65
66 if((statvfs(fnPath,&fiData)) < 0 ) {
67 elog(LOG_WARNING,"Failed to stat %s:\n", fnPath);
68 return -1;
69 }
70 else
71 {
72 elog(LOG_DEBUG(15),"Disk %s: \n", fnPath);
73 elog(LOG_DEBUG(15),"\tblock size: %ld\n", fiData.f_bsize);
74 elog(LOG_DEBUG(15),"\ttotal no blocks: %ld\n", fiData.f_blocks);
75 elog(LOG_DEBUG(15),"\tfree blocks: %ld\n", fiData.f_bfree);
76 elog(LOG_DEBUG(10),"Free diskspace = %f%%",100*(float)(fiData.f_bfree)/(float)(fiData.f_blocks));
77 /*sysman_log(SYSMAN_DISKMAN_SPACE,"free-diskspace=%.2f%% free-diskspace-threshold=%.2f%% free-diskspace-delete-threshold=%.2f%%",
78 100*(float)(fiData.f_bfree)/(float)(fiData.f_blocks),
79 d->free_diskspace_threshold,d->free_diskspace_delete_threshold); */
80 return 100*(float)(fiData.f_bfree)/(float)(fiData.f_blocks);
81 }
82 }
83
84 float get_diskspace(void)
85 {
86 struct statvfs fiData;
87 // struct statvfs *fpData;
88 char fnPath[10]=COMPACT_FLASH_DIRECTORY;
89
90 if((statvfs(fnPath,&fiData)) < 0 ) {
91 elog(LOG_WARNING,"Failed to stat %s:\n", fnPath);
92 return -1;
93 }
94 else
95 return (float)(fiData.f_blocks)* ((fiData.f_bsize + 0.0)/(ONE_GIGABYTE + 0.0));
96 }
97
98 float get_free_diskspace(void)
99 {
100 struct statvfs fiData;
101 // struct statvfs *fpData;
102 char fnPath[10]=COMPACT_FLASH_DIRECTORY;
103
104 if((statvfs(fnPath,&fiData)) < 0 ) {
105 elog(LOG_WARNING,"Failed to stat %s:\n", fnPath);
106 return -1;
107 }
108 else
109 {
110 elog(LOG_DEBUG(15),"Disk %s: \n", fnPath);
111 elog(LOG_DEBUG(15),"\tblock size: %ld\n", fiData.f_bsize);
112 elog(LOG_DEBUG(15),"\ttotal no blocks: %ld\n", fiData.f_blocks);
113 elog(LOG_DEBUG(15),"\tfree blocks: %ld\n", fiData.f_bfree);
114 elog(LOG_DEBUG(10),"Free disk space = %fGB",(float)(fiData.f_bfree) *((fiData.f_bsize + 0.0)/ (ONE_GIGABYTE +0.0)));
115 return (float)(fiData.f_bfree) * ((fiData.f_bsize + 0.0)/ (ONE_GIGABYTE +0.0)) ;
116 }
117 }
118
119 int diskmanager_publish_timer(void *data, int interval, g_event_t *ev)
120 {
121 diskmanager_state_t *d = (diskmanager_state_t *) data;
122 float free_diskspace = get_free_diskspace_percent(d);
123
124 //Publish ID of the self
125 if(free_diskspace >= 0)
126 {
127 // COMMENTED OUT ON 06/10/09 -> MLL -> Chaning operation of diskman to always provide availability to neighborss
128 // if((d->provide_neighborhood == 0 && free_diskspace <= d->free_diskspace_threshold) || d->provide_neighborhood == 1)
129 {
130 //Publish if it is for the first time after booting or it has 5 minutes since the last publication
131 if(misc_tv_usec_l(&d->last_published) == 0 || msec_since(&d->last_published) >= 5*60*1000)
132 {
133 flow_id_t fid = {
134 src: my_node_id,
135 dst: LINK_BROADCAST,
136 max_hops: 1,
137 };
138 diskmanager_table_t thetable[1] = {};
139 thetable[0].diskmanager.seqno = d->seqno;
140 thetable[0].diskmanager.diskfull_percent = 100.00 - get_free_diskspace_percent(d);
141 //memmove(&(thetable[0].diskmanager), &(d->seqno), sizeof(diskmanager_global_state_t));
142
143 if (diskmanager_pub(DISKMANAGER_SSYNC_DEFAULT_PREFIX, thetable, 1, &fid) < 0) {
144 elog(LOG_WARNING, "Unable to publish! %m");
145 exit(1);
146 }
147 gettimeofday(&(d->last_published), NULL);
148 (d->seqno)++;
149 /*
150 sysman_log(SYSMAN_DISKMAN_SPACE,"free-ds=%.2f%/%.2f%% "
151 "total-ds=%.2f "
152 "thresh=%.2f%% "
153 "del-thresh=%.2f%%",
154 (fiData.f_bfree*fiData.f_bsize + 0.0)/(ONE_MEGABYTE + 0.0),
155 (fiData.f_blocks*fiData.f_bsize + 0.0),
156 100*(float)(fiData.f_bfree)/(float)(fiData.f_blocks),
157 d->free_diskspace_threshold,
158 d->free_diskspace_delete_threshold);
159 */
160 }
161 }
162 }
163 elog(LOG_DEBUG(10),"Publish: Free disk space = %f%% Threshold = %f%%",free_diskspace,d->free_diskspace_threshold);
164 //sysman_log(SYSMAN_DISKMAN_ALERT,"Published diskspace to neighbors.");
165
166 //For testing only
167 /*if(d-> seqno == 10)
168 return TIMER_DONE;
169 else*/
170 return EVENT_RENEW;
171 }
172
173 /*int diskmanager_diskspace_timer(void *data, int interval, g_event_t *ev)
174 {
175 diskmanager_state_t *d = (diskmanager_state_t *) data;
176
177 get_free_diskspace();
178
179 return EVENT_RENEW;
180 }*/
181
182 /*
183 // REMOVED ON 06/10/09 -> MLL -> don't need this anymore since everyone always publishes
184 int diskmanager_diskfree_timer(void *data, int interval, g_event_t *ev)
185 {
186 //Traverse the entire dqueue and trash elements, which are older than 30 minutes
187 diskmanager_state_t *d = (diskmanager_state_t *) data;
188 diskfull_state_t *dfs;
189 int length = dqueue_qlen(d);
190 int i;
191 int updated = 0;
192
193 for (i = 0; i < length; ++i) {
194 dfs = dqueue_pop(d);
195 if(msec_since(&dfs->last_heard) <= FULL_DISKSPACE_ENTRY_TIMEOUT) //Temporarily changed from 30 to 2 for the testing purposes
196 dqueue_push(d,dfs);
197 else
198 {
199 elog(LOG_NOTICE,"Removed diskfull record for %d",dfs->node_id);
200 free(dfs);
201 updated = 1;
202 }
203 }
204 if (updated) {
205 g_status_dev_notify(d->diskmanager_status);
206 //elog(LOG_WARNING, "Calling notify in main!");
207 }
208
209 return EVENT_RENEW;
210 }
211 */
212
213 int diskmanager_report_diskspace(void *data, int interval, g_event_t *ev)
214 {
215 diskmanager_state_t *d = (diskmanager_state_t *) data;
216 struct statvfs fiData = {};
217 char fnPath[10]=COMPACT_FLASH_DIRECTORY;
218
219 if((statvfs(fnPath,&fiData)) < 0 ) {
220 elog(LOG_WARNING,"Failed to stat %s:\n", fnPath);
221 sysman_log(SYSMAN_DISKMAN_SPACE,"STAT-ERR");
222 } else {
223
224 // elog(LOG_DEBUG(15),"\tblock size: %ld\n", fiData.f_bsize);
225 // elog(LOG_DEBUG(15),"\ttotal no blocks: %ld\n", fiData.f_blocks);
226 // elog(LOG_DEBUG(15),"\tfree blocks: %ld\n", fiData.f_bfree);
227 // elog(LOG_DEBUG(10),"Free disk space = %fGB",(float)(fiData.f_bfree*fiData.f_bsize)/ONE_GIGABYTE);
228
229 sysman_log(SYSMAN_DISKMAN_SPACE,
230 // "free-ds=%.2f/%.2f%% "
231 // "used-ds=%.2f/%.2f%% "
232 // "total-ds=%.2f "
233 // "thresh=%.2f%% "
234 // "del-thresh=%.2f%%",
235 "%.2f %.2f "
236 "%.2f %.2f "
237 "%.2f "
238 "%.2f "
239 "%.2f",
240 fiData.f_bfree * ((fiData.f_bsize + 0.0)/(ONE_MEGABYTE + 0.0)),
241 100*(fiData.f_bfree + 0.0)/(fiData.f_blocks + 0.0),
242 (fiData.f_blocks - fiData.f_bfree) * ((fiData.f_bsize + 0.0)/(ONE_MEGABYTE + 0.0)),
243 100*(fiData.f_blocks - fiData.f_bfree + 0.0)/(fiData.f_blocks + 0.0),
244 fiData.f_blocks* ((fiData.f_bsize + 0.0)/(ONE_MEGABYTE + 0.0)),
245 d->free_diskspace_threshold,
246 d->free_diskspace_delete_threshold);
247
248 }
249
250 return TIMER_RENEW;
251 }
252
253
254 int main(int argc, char **argv)
255 {
256 diskmanager_state_t diskmanager_state = {};
257 uint32_t free_diskspace_threshold, free_diskspace_delete_threshold;
258
259 misc_init(&argc, argv, CVSTAG);
260
261 emrun_opts_t eopts = {
262 shutdown: diskmanager_shutdown,
263 data: &diskmanager_state,
264 };
265
266 if(misc_parse_option_as_uint(&argc, argv, "free-diskspace-threshold", 'F', &free_diskspace_threshold) < 0)
267 diskmanager_state.free_diskspace_threshold = FREE_DISKSPACE_THRESHOLD;
268 else
269 diskmanager_state.free_diskspace_threshold = (float)free_diskspace_threshold;
270
271 if(misc_parse_option_as_uint(&argc, argv, "free-diskspace-delete-threshold", 'D', &free_diskspace_delete_threshold) < 0)
272 diskmanager_state.free_diskspace_delete_threshold = FREE_DISKSPACE_DELETE_THRESHOLD;
273 else
274 diskmanager_state.free_diskspace_delete_threshold = (float)free_diskspace_delete_threshold;
275
276 diskmanager_state.provide_neighborhood = misc_parse_out_switch(&argc, argv, "provide-neighborhood", 0);
277
278 /* register with statesync for the updates */
279 // Changed 2 header files in devel/state
280 // The name "diskmanager" was too long. So changed to "diskman".
281 if (diskmanager_sub_open(DISKMANAGER_SSYNC_DEFAULT_PREFIX, diskmanager_update, &diskmanager_state, &(diskmanager_state.global_state_sub)) < 0) {
282 elog(LOG_WARNING, "Unable to connect to state sync dev: %s", strerror(errno));
283 exit(1);
284 }
285
286 /* setup the status dev */
287 status_dev_opts_t sdo = {
288 device: {
289 devname: sim_path(DISKMANAGER_STATUS_DEVICE),
290 device_info: &diskmanager_state
291 },
292 binary: diskmanager_diskfull_nodes_binary,
293 printable: diskmanager_status_print
294 };
295 if (g_status_dev(&sdo, &diskmanager_state.diskmanager_status) < 0) {
296 elog(LOG_CRIT, "Unable to create status device: %s %m", sdo.device.devname);
297 exit(1);
298 }
299
300 if(diskmanager_state.provide_neighborhood == 1)
301 {
302 /* setup the neighbor dev */
303 status_dev_opts_t sdo = {
304 device: {
305 devname: sim_path(DISKMANAGER_NEIGHBORHOOD_DEVICE),
306 device_info: &diskmanager_state
307 },
308 binary: diskmanager_neighborhood_nodes_binary,
309 //printable: diskmanager_status_print
310 };
311 if (g_status_dev(&sdo, &diskmanager_state.diskmanager_neighborhood) < 0) {
312 elog(LOG_CRIT, "Unable to create status device: %s %m", sdo.device.devname);
313 exit(1);
314 }
315 }
316
317 //Timer to read the available free diskspace on the compact flash card and if necessary publish the disk space
318 // CHANGED TO 30 seconds on 06/10/09 by MLL
319 if (g_timer_add(30000, diskmanager_publish_timer, &diskmanager_state, NULL, NULL) < 0) {
320 elog(LOG_WARNING, "Unable to set pub timer!");
321 exit(1);
322 }
323
324 //Timer to read the available free diskspace on the compact flash card
325 /*if (g_timer_add(10000, diskmanager_diskspace_timer, &diskmanager_state, NULL, NULL) < 0) {
326 elog(LOG_WARNING, "Unable to set diskspace timer!");
327 exit(1);
328 }*/
329
330 //Timer to delete the old entires about diskfree space
331 // REMOVED ON 06/10/09 -> MLL -> don't need this anymore since everyone always publishes
332 /*
333 if (g_timer_add(10000, diskmanager_diskfree_timer, &diskmanager_state, NULL, NULL) < 0) {
334 elog(LOG_WARNING, "Unable to set diskfree timer!");
335 exit(1);
336 }
337 */
338
339 //Timer to delete old files if the disk is full
340 if (g_timer_add(10000, diskmanager_delete_timer, &diskmanager_state, NULL,&(diskmanager_state.delete_timer)) < 0) {
341 elog(LOG_WARNING, "Unable to set delete timer!");
342 exit(1);
343 }
344
345 //Timer to report space to syslog every 10 minutes - CHANGED TO 10 min on 06/10/09
346 if (g_timer_add(600000, diskmanager_report_diskspace, &diskmanager_state, NULL,&(diskmanager_state.report_timer)) < 0) {
347 elog(LOG_WARNING, "Unable to set delete timer!");
348 exit(1);
349 }
350
351 emrun_init(&eopts);
352
353 g_main();
354
355 return 1;
356 }
357
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.