]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/status.c
misc minor updates
[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 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];
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
84    list_terminated_jobs(sendit, arg);
85
86    /*
87     * List running jobs  
88     */
89    Dmsg0(1000, "Begin status jcr loop.\n");
90    lock_jcr_chain();
91    foreach_jcr(njcr) {
92       bstrftime_nc(dt, sizeof(dt), njcr->start_time);
93       if (njcr->JobId == 0) {
94          len = Mmsg(&msg, _("Director connected at: %s\n"), dt);
95       } else {
96          len = Mmsg(&msg, _("JobId %d Job %s is running.\n"), 
97                     njcr->JobId, njcr->Job);
98          sendit(msg, len, arg);
99          len = Mmsg(&msg, _("    %s Job started: %s\n"), 
100                     job_type_to_str(njcr->JobType), dt);
101       }
102       sendit(msg, len, arg);
103       if (njcr->JobId == 0) {
104          free_locked_jcr(njcr);
105          continue;
106       }
107       sec = time(NULL) - njcr->start_time;
108       if (sec <= 0) {
109          sec = 1;
110       }
111       bps = (int)(njcr->JobBytes / sec);
112       len = Mmsg(&msg,  _("    Files=%s Bytes=%s Bytes/sec=%s\n"), 
113            edit_uint64_with_commas(njcr->JobFiles, b1),
114            edit_uint64_with_commas(njcr->JobBytes, b2),
115            edit_uint64_with_commas(bps, b3));
116       sendit(msg, len, arg);
117       len = Mmsg(&msg, _("    Files Examined=%s\n"), 
118            edit_uint64_with_commas(njcr->num_files_examined, b1));
119       sendit(msg, len, arg);
120       if (njcr->JobFiles > 0) {
121          P(njcr->mutex);
122          len = Mmsg(&msg, _("    Processing file: %s\n"), njcr->last_fname);
123          V(njcr->mutex);
124          sendit(msg, len, arg);
125       }
126
127       found = 1;
128       if (njcr->store_bsock) {
129          len = Mmsg(&msg, "    SDReadSeqNo=%" lld " fd=%d\n",
130              njcr->store_bsock->read_seqno, njcr->store_bsock->fd);
131          sendit(msg, len, arg);
132       } else {
133          len = Mmsg(&msg, _("    SDSocket closed.\n"));
134          sendit(msg, len, arg);
135       }
136       free_locked_jcr(njcr);
137    }
138    unlock_jcr_chain();
139    Dmsg0(1000, "Begin status jcr loop.\n");
140    if (!found) {
141       len = Mmsg(&msg, _("No jobs running.\n"));
142       sendit(msg, len, arg);
143    }
144    free_pool_memory(msg);
145 }
146
147 static void  list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg) 
148 {
149    char dt[MAX_TIME_LENGTH], b1[30], b2[30];
150    char level[10];
151    struct s_last_job *je;
152    const char *msg;
153
154    if (last_jobs->size() == 0) {
155       msg = _("No Terminated Jobs.\n"); 
156       sendit(msg, strlen(msg), arg);
157       return;
158    }
159    lock_last_jobs_list();
160    sendit("\n", 1, arg);               /* send separately */
161    msg =  _("Terminated Jobs:\n"); 
162    sendit(msg, strlen(msg), arg);
163    msg =  _(" JobId  Level   Files          Bytes Status   Finished        Name \n");
164    sendit(msg, strlen(msg), arg);
165    msg = _("======================================================================\n"); 
166    sendit(msg, strlen(msg), arg);
167    foreach_dlist(je, last_jobs) {
168       char JobName[MAX_NAME_LENGTH];
169       char *termstat;
170       char buf[1000];
171
172       bstrftime_nc(dt, sizeof(dt), je->end_time);
173       switch (je->JobType) {
174       case JT_ADMIN:
175       case JT_RESTORE:
176          bstrncpy(level, "    ", sizeof(level));
177          break;
178       default:
179          bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
180          level[4] = 0;
181          break;
182       }
183       switch (je->JobStatus) {
184       case JS_Created:
185          termstat = "Created";
186          break;
187       case JS_FatalError:
188       case JS_ErrorTerminated:
189          termstat = "Error";
190          break;
191       case JS_Differences:
192          termstat = "Diffs";
193          break;
194       case JS_Canceled:
195          termstat = "Cancel";
196          break;
197       case JS_Terminated:
198          termstat = "OK";
199          break;
200       default:
201          termstat = "Other";
202          break;
203       }
204       bstrncpy(JobName, je->Job, sizeof(JobName));
205       /* There are three periods after the Job name */
206       char *p;
207       for (int i=0; i<3; i++) {
208          if ((p=strrchr(JobName, '.')) != NULL) {
209             *p = 0;
210          }
211       }
212       bsnprintf(buf, sizeof(buf), _("%6d  %-6s %8s %14s %-7s  %-8s %s\n"), 
213          je->JobId,
214          level, 
215          edit_uint64_with_commas(je->JobFiles, b1),
216          edit_uint64_with_commas(je->JobBytes, b2), 
217          termstat,
218          dt, JobName);
219       sendit(buf, strlen(buf), arg);
220    }
221    sendit("\n", 1, arg);
222    unlock_last_jobs_list();
223 }
224
225
226 /*
227  * Send to bsock (Director or Console)
228  */
229 static void bsock_sendit(const char *msg, int len, void *arg)
230 {
231    BSOCK *user = (BSOCK *)arg;
232
233    user->msg = check_pool_memory_size(user->msg, len+1);
234    memcpy(user->msg, msg, len+1);
235    user->msglen = len+1;
236    bnet_send(user);
237 }
238                                    
239 /*
240  * Status command from Director
241  */
242 int status_cmd(JCR *jcr)
243 {
244    BSOCK *user = jcr->dir_bsock;
245
246    bnet_fsend(user, "\n");
247    do_status(bsock_sendit, (void *)user);
248    bnet_fsend(user, "====\n");
249
250    bnet_sig(user, BNET_EOD);
251    return 1;
252 }
253
254
255 /*
256  * Convert Job Level into a string
257  */
258 static char *level_to_str(int level) 
259 {
260    char *str;
261
262    switch (level) {
263    case L_BASE:
264       str = _("Base");
265    case L_FULL:
266       str = _("Full");
267       break;
268    case L_INCREMENTAL:
269       str = _("Incremental");
270       break;
271    case L_DIFFERENTIAL:
272       str = _("Differential");
273       break;
274    case L_SINCE:
275       str = _("Since");
276       break;
277    case L_VERIFY_CATALOG:
278       str = _("Verify Catalog");
279       break;
280    case L_VERIFY_INIT:
281       str = _("Init Catalog");
282       break;
283    case L_VERIFY_VOLUME_TO_CATALOG:
284       str = _("Volume to Catalog");
285       break;
286    case L_VERIFY_DISK_TO_CATALOG:
287       str = _("Disk to Catalog");
288       break;
289    case L_VERIFY_DATA:
290       str = _("Data");
291       break;
292    case L_NONE:
293       str = " ";
294       break;
295    default:
296       str = _("Unknown Job Level");
297       break;
298    }
299    return str;
300 }
301
302
303 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
304 #include <windows.h>
305
306 static char buf[100];
307 int bacstat = 0;
308
309 struct s_win32_arg {
310    HWND hwnd;
311    int idlist;
312 };
313
314 /*
315  * Put message in Window List Box
316  */
317 static void win32_sendit(const char *msg, int len, void *marg)
318 {
319    struct s_win32_arg *arg = (struct s_win32_arg *)marg;
320
321    if (len > 0 && msg[len-1] == '\n') {
322        // when compiling with visual studio some strings are read-only 
323        // and cause access violations.  So we creat a tmp copy.
324        char *_msg = (char *)alloca(len);
325        strncpy(_msg, msg, len-1);
326        _msg[len-1] = 0;
327        msg = _msg;
328    }
329    SendDlgItemMessage(arg->hwnd, arg->idlist, LB_ADDSTRING, 0, (LONG)msg);
330    
331 }
332
333 void FillStatusBox(HWND hwnd, int idlist)
334 {
335    struct s_win32_arg arg;
336
337    arg.hwnd = hwnd;
338    arg.idlist = idlist;
339
340    /* Empty box */
341    for ( ; SendDlgItemMessage(hwnd, idlist, LB_DELETESTRING, 0, (LONG)0) > 0; )
342       { }
343    do_status(win32_sendit, (void *)&arg);
344 }
345
346 char *bac_status(int stat)
347 {
348    JCR *njcr;
349    char *termstat = _("Bacula Idle");
350    struct s_last_job *job;
351
352    bacstat = 0;
353    if (last_jobs->size() > 0) {
354       job = (struct s_last_job *)last_jobs->first();
355       switch (job->JobStatus) {
356       case JS_Canceled:
357          bacstat = -1;
358          termstat = _("Last Job Canceled");
359          break;
360       case JS_ErrorTerminated:
361          bacstat = -1;
362          termstat = _("Last Job Failed");
363          break;
364       default:
365          break;
366       }
367    }
368    Dmsg0(1000, "Begin bac_status jcr loop.\n");
369    lock_jcr_chain();
370    foreach_jcr(njcr) {
371       if (njcr->JobId != 0) {
372          bacstat = 1;
373          termstat = _("Bacula Running");
374          free_locked_jcr(njcr);
375          break;
376       }
377       free_locked_jcr(njcr);
378    }
379    unlock_jcr_chain();
380    Dmsg0(1000, "End bac_status jcr loop.\n");
381    bstrncpy(buf, termstat, sizeof(buf));
382    return buf;
383 }
384
385 #endif /* HAVE_CYGWIN */