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