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