]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/status.c
Add heap stats to Dir and SD -- eliminate #ifdefs
[bacula/bacula] / bacula / src / filed / status.c
1 /*
2  *  Bacula File Daemon Status routines
3  *
4  *    Kern Sibbald, August MMI
5  *
6  *   Version $Id$
7  *
8  */
9 /*
10    Copyright (C) 2000-2003 Kern Sibbald and John Walker
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of
15    the License, or (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20    General Public License for more details.
21
22    You should have received a copy of the GNU General Public
23    License along with this program; if not, write to the Free
24    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25    MA 02111-1307, USA.
26
27  */
28
29 #include "bacula.h"
30 #include "filed.h"
31
32 extern char my_name[];
33 extern int num_jobs_run;
34 extern time_t daemon_start_time;
35
36 /* Forward referenced functions */
37 static void  list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg);
38 static void bsock_sendit(const char *msg, int len, void *arg);
39 static const char *level_to_str(int level);
40
41
42 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
43 static int privs = 0;
44 #endif
45
46 /*
47  * General status generator
48  */
49 static void do_status(void sendit(const char *msg, int len, void *sarg), void *arg) 
50 {
51    int sec, bps;
52    char *msg, b1[32], b2[32], b3[32], b4[32];
53    int found, len;
54    JCR *njcr;
55    char dt[MAX_TIME_LENGTH];
56
57    msg = (char *)get_pool_memory(PM_MESSAGE);
58    found = 0;
59    len = Mmsg(&msg, "%s Version: " VERSION " (" BDATE ") %s %s %s\n", my_name,
60               HOST_OS, DISTNAME, DISTVER);
61    sendit(msg, len, arg);
62    bstrftime_nc(dt, sizeof(dt), daemon_start_time);
63    len = Mmsg(&msg, _("Daemon started %s, %d Job%s run since started.\n"), 
64         dt, num_jobs_run, num_jobs_run == 1 ? "" : "s");
65    sendit(msg, len, arg);
66 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
67    if (debug_level > 0) {
68       if (!privs) {
69          privs = enable_backup_privileges(NULL, 1);
70       }
71       len = Mmsg(&msg, 
72          _(" Priv 0x%x APIs=%sOPT,%sATP,%sLPV,%sGFAE,%sBR,%sBW,%sSPSP\n"), privs,
73          p_OpenProcessToken?"":"!",
74          p_AdjustTokenPrivileges?"":"!",
75          p_LookupPrivilegeValue?"":"!",
76          p_GetFileAttributesEx?"":"!",
77          p_BackupRead?"":"!",
78          p_BackupWrite?"":"!",
79          p_SetProcessShutdownParameters?"":"!");
80       sendit(msg, len, arg);
81    }
82 #endif
83    if (debug_level > 0) {
84       len = Mmsg(&msg, _(" Heap: bytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
85             edit_uint64_with_commas(sm_bytes, b1),
86             edit_uint64_with_commas(sm_max_bytes, b2),
87             edit_uint64_with_commas(sm_buffers, b3),
88             edit_uint64_with_commas(sm_max_buffers, b4));
89        sendit(msg, len, arg);
90     }
91    if (debug_level > 0) {
92       len = Mmsg(&msg, _(" Sizeof: off_t=%d size_t=%d\n"), sizeof(off_t),
93             sizeof(size_t));
94       sendit(msg, len, arg);
95    }
96
97    list_terminated_jobs(sendit, arg);
98
99    /*
100     * List running jobs  
101     */
102    Dmsg0(1000, "Begin status jcr loop.\n");
103    len = Mmsg(&msg, _("Running Jobs:\n"));
104    sendit(msg, len, arg);
105    lock_jcr_chain();
106    foreach_jcr(njcr) {
107       bstrftime_nc(dt, sizeof(dt), njcr->start_time);
108       if (njcr->JobId == 0) {
109          len = Mmsg(&msg, _("Director connected at: %s\n"), dt);
110       } else {
111          len = Mmsg(&msg, _("JobId %d Job %s is running.\n"), 
112                     njcr->JobId, njcr->Job);
113          sendit(msg, len, arg);
114          len = Mmsg(&msg, _("    %s Job started: %s\n"), 
115                     job_type_to_str(njcr->JobType), dt);
116       }
117       sendit(msg, len, arg);
118       if (njcr->JobId == 0) {
119          free_locked_jcr(njcr);
120          continue;
121       }
122       sec = time(NULL) - njcr->start_time;
123       if (sec <= 0) {
124          sec = 1;
125       }
126       bps = (int)(njcr->JobBytes / sec);
127       len = Mmsg(&msg,  _("    Files=%s Bytes=%s Bytes/sec=%s\n"), 
128            edit_uint64_with_commas(njcr->JobFiles, b1),
129            edit_uint64_with_commas(njcr->JobBytes, b2),
130            edit_uint64_with_commas(bps, b3));
131       sendit(msg, len, arg);
132       len = Mmsg(&msg, _("    Files Examined=%s\n"), 
133            edit_uint64_with_commas(njcr->num_files_examined, b1));
134       sendit(msg, len, arg);
135       if (njcr->JobFiles > 0) {
136          P(njcr->mutex);
137          len = Mmsg(&msg, _("    Processing file: %s\n"), njcr->last_fname);
138          V(njcr->mutex);
139          sendit(msg, len, arg);
140       }
141
142       found = 1;
143       if (njcr->store_bsock) {
144          len = Mmsg(&msg, "    SDReadSeqNo=%" lld " fd=%d\n",
145              njcr->store_bsock->read_seqno, njcr->store_bsock->fd);
146          sendit(msg, len, arg);
147       } else {
148          len = Mmsg(&msg, _("    SDSocket closed.\n"));
149          sendit(msg, len, arg);
150       }
151       free_locked_jcr(njcr);
152    }
153    unlock_jcr_chain();
154    Dmsg0(1000, "Begin status jcr loop.\n");
155    if (!found) {
156       len = Mmsg(&msg, _("No Jobs running.\n"));
157       sendit(msg, len, arg);
158    }
159    len = Mmsg(&msg, _("====\n"));
160    sendit(msg, len, arg);
161    free_pool_memory(msg);
162 }
163
164 static void  list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg) 
165 {
166    char dt[MAX_TIME_LENGTH], b1[30], b2[30];
167    char level[10];
168    struct s_last_job *je;
169    const char *msg;
170
171    if (last_jobs->size() == 0) {
172       msg = _("No Terminated Jobs.\n"); 
173       sendit(msg, strlen(msg), arg);
174       return;
175    }
176    lock_last_jobs_list();
177    sendit("\n", 1, arg);               /* send separately */
178    msg =  _("Terminated Jobs:\n"); 
179    sendit(msg, strlen(msg), arg);
180    msg =  _(" JobId  Level     Files         Bytes  Status   Finished        Name \n");
181    sendit(msg, strlen(msg), arg);
182    msg = _("======================================================================\n"); 
183    sendit(msg, strlen(msg), arg);
184    foreach_dlist(je, last_jobs) {
185       char JobName[MAX_NAME_LENGTH];
186       const char *termstat;
187       char buf[1000];
188
189       bstrftime_nc(dt, sizeof(dt), je->end_time);
190       switch (je->JobType) {
191       case JT_ADMIN:
192       case JT_RESTORE:
193          bstrncpy(level, "    ", sizeof(level));
194          break;
195       default:
196          bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
197          level[4] = 0;
198          break;
199       }
200       switch (je->JobStatus) {
201       case JS_Created:
202          termstat = "Created";
203          break;
204       case JS_FatalError:
205       case JS_ErrorTerminated:
206          termstat = "Error";
207          break;
208       case JS_Differences:
209          termstat = "Diffs";
210          break;
211       case JS_Canceled:
212          termstat = "Cancel";
213          break;
214       case JS_Terminated:
215          termstat = "OK";
216          break;
217       default:
218          termstat = "Other";
219          break;
220       }
221       bstrncpy(JobName, je->Job, sizeof(JobName));
222       /* There are three periods after the Job name */
223       char *p;
224       for (int i=0; i<3; i++) {
225          if ((p=strrchr(JobName, '.')) != NULL) {
226             *p = 0;
227          }
228       }
229       bsnprintf(buf, sizeof(buf), _("%6d  %-6s %8s %14s %-7s  %-8s %s\n"), 
230          je->JobId,
231          level, 
232          edit_uint64_with_commas(je->JobFiles, b1),
233          edit_uint64_with_commas(je->JobBytes, b2), 
234          termstat,
235          dt, JobName);
236       sendit(buf, strlen(buf), arg);
237    }
238    sendit("====\n", 5, arg);
239    unlock_last_jobs_list();
240 }
241
242
243 /*
244  * Send to bsock (Director or Console)
245  */
246 static void bsock_sendit(const char *msg, int len, void *arg)
247 {
248    BSOCK *user = (BSOCK *)arg;
249
250    user->msg = check_pool_memory_size(user->msg, len+1);
251    memcpy(user->msg, msg, len+1);
252    user->msglen = len+1;
253    bnet_send(user);
254 }
255                                    
256 /*
257  * Status command from Director
258  */
259 int status_cmd(JCR *jcr)
260 {
261    BSOCK *user = jcr->dir_bsock;
262
263    bnet_fsend(user, "\n");
264    do_status(bsock_sendit, (void *)user);
265
266    bnet_sig(user, BNET_EOD);
267    return 1;
268 }
269
270
271 /*
272  * Convert Job Level into a string
273  */
274 static const char *level_to_str(int level) 
275 {
276    const char *str;
277
278    switch (level) {
279    case L_BASE:
280       str = _("Base");
281    case L_FULL:
282       str = _("Full");
283       break;
284    case L_INCREMENTAL:
285       str = _("Incremental");
286       break;
287    case L_DIFFERENTIAL:
288       str = _("Differential");
289       break;
290    case L_SINCE:
291       str = _("Since");
292       break;
293    case L_VERIFY_CATALOG:
294       str = _("Verify Catalog");
295       break;
296    case L_VERIFY_INIT:
297       str = _("Init Catalog");
298       break;
299    case L_VERIFY_VOLUME_TO_CATALOG:
300       str = _("Volume to Catalog");
301       break;
302    case L_VERIFY_DISK_TO_CATALOG:
303       str = _("Disk to Catalog");
304       break;
305    case L_VERIFY_DATA:
306       str = _("Data");
307       break;
308    case L_NONE:
309       str = " ";
310       break;
311    default:
312       str = _("Unknown Job Level");
313       break;
314    }
315    return str;
316 }
317
318
319 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
320 #include <windows.h>
321
322 int bacstat = 0;
323
324 struct s_win32_arg {
325    HWND hwnd;
326    int idlist;
327 };
328
329 /*
330  * Put message in Window List Box
331  */
332 static void win32_sendit(const char *msg, int len, void *marg)
333 {
334    struct s_win32_arg *arg = (struct s_win32_arg *)marg;
335
336    if (len > 0 && msg[len-1] == '\n') {
337        // when compiling with visual studio some strings are read-only 
338        // and cause access violations.  So we creat a tmp copy.
339        char *_msg = (char *)alloca(len);
340        bstrncpy(_msg, msg, len);
341        msg = _msg;
342    }
343    SendDlgItemMessage(arg->hwnd, arg->idlist, LB_ADDSTRING, 0, (LONG)msg);
344    
345 }
346
347 void FillStatusBox(HWND hwnd, int idlist)
348 {
349    struct s_win32_arg arg;
350
351    arg.hwnd = hwnd;
352    arg.idlist = idlist;
353
354    /* Empty box */
355    for ( ; SendDlgItemMessage(hwnd, idlist, LB_DELETESTRING, 0, (LONG)0) > 0; )
356       { }
357    do_status(win32_sendit, (void *)&arg);
358 }
359
360 char *bac_status(char *buf, int buf_len)
361 {
362    JCR *njcr;
363    const char *termstat = _("Bacula Idle");
364    struct s_last_job *job;
365    int stat = 0;                      /* Idle */
366
367    if (!last_jobs) {
368       goto done;
369    }
370    Dmsg0(1000, "Begin bac_status jcr loop.\n");
371    lock_jcr_chain();
372    foreach_jcr(njcr) {
373       if (njcr->JobId != 0) {
374          stat = JS_Running;
375          termstat = _("Bacula Running");
376          free_locked_jcr(njcr);
377          break;
378       }
379       free_locked_jcr(njcr);
380    }
381    unlock_jcr_chain();
382    if (stat != 0) {
383       goto done;
384    }
385    if (last_jobs->size() > 0) {
386       job = (struct s_last_job *)last_jobs->last();
387       stat = job->JobStatus;
388       switch (job->JobStatus) {
389       case JS_Canceled:
390          termstat = _("Last Job Canceled");
391          break;
392       case JS_ErrorTerminated:
393       case JS_FatalError:  
394          termstat = _("Last Job Failed");
395          break;
396       default:
397          if (job->Errors) {
398             termstat = _("Last Job had Warnings");
399          }
400          break;
401       }
402    }
403    Dmsg0(1000, "End bac_status jcr loop.\n");
404 done:
405    bacstat = stat;
406    if (buf) {
407       bstrncpy(buf, termstat, buf_len);
408    }
409    return buf;
410 }
411
412 #endif /* HAVE_CYGWIN */