# This is the list of Bacula daemon events that you
 #  can receive.
-class BaculaEvents:
+class BaculaEvents(object):
   def __init__(self):
      # Called here when a new Bacula Events class is
      #  is created. Normally not used 
 """
   There are the Job events that you can receive.
 """
-class JobEvents:
+class JobEvents(object):
   def __init__(self):
      # Called here when you instantiate the Job. Not
      # normally used
 
 
 # This is the list of Bacula daemon events that you
 #  can receive.
-class BaculaEvents:
+class BaculaEvents(object):
   def __init__(self):
      # Called here when a new Bacula Events class is
      #  is created. Normally not used 
 """
   There are the Job events that you can receive.
 """
-class JobEvents:
+class JobEvents(object):
   def __init__(self):
      # Called here when you instantiate the Job. Not
      # normally used
 
 
 # This is the list of Bacula daemon events that you
 #  can receive.
-class BaculaEvents:
+class BaculaEvents(object):
   def __init__(self):
      # Called here when a new Bacula Events class is
      #  is created. Normally not used 
 """
   There are the Job events that you can receive.
 """
-class JobEvents:
+class JobEvents(object):
   def __init__(self):
      # Called here when you instantiate the Job. Not
      # normally used
 
 
 General:
 
+27Feb06
+- Modify the Python class examples to inherit object -- new way
+  of defining classes. Patch from Felix Schwartz.
+- Implement jobuid to replace old usage of job in keywords as
+  suggested by Eric Bollengier.
+- Apply patch for enhancing wait from Eric Bollengier. On can now:
+   wait  (wait for all jobs to stop)
+   wait jobid=nn
+   wait jobuid=unique id
+   wait job=job-name
+- Implement write variables for Python to set Priority (anytime), and
+  Job Level, only during JobInit event.
+
 26Feb06
 - Fix the block listing bug pointed out by Arno.
 - Update the po files at Eric's request.
 
  *    Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
          Mmsg(mdb->cmd, 
             "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
             "FROM Job WHERE JobId=%s", edit_int64(jr->JobId, ed1));
-      } else {                           /* single record */
+      } else {                           /* all records */
          Mmsg(mdb->cmd,
            "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
            "FROM Job ORDER BY StartTime,JobId ASC%s", limit);
 
 #include <Python.h>
 
 extern char *configfile;
+extern struct s_jl joblevels[];
 extern JCR *get_jcr_from_PyObject(PyObject *self);
 extern PyObject *find_method(PyObject *eventsObject, PyObject *method, 
          const char *name);
    { "JobReport",   "s"},
    { "VolumeName",  "s"},
    { "Priority",    "i"},
+   { "JobLevel",    "s"},
 
    { NULL,             NULL}
 };
       break;
    case 2:                            /* Priority */
       Dmsg1(000, "Set priority=%d\n", intval);
-      return 0;
+      if (intval >= 1 && intval <= 100) {
+         jcr->JobPriority = intval;
+      } else {
+         PyErr_SetString(PyExc_ValueError, _("Priority must be 1-100"));
+         return -1;
+      }
+   case 3:                            /* Job Level */
+      if (strcmp("JobInit", jcr->event) != 0) {
+         PyErr_SetString(PyExc_RuntimeError, _("Job Level can be set only during JobInit"));
+         return -1;
+      }
+      for (i=0; joblevels[i].level_name; i++) {
+         if (strcmp(strval, joblevels[i].level_name) == 0) {
+            if (joblevels[i].job_type == jcr->JobType) {
+               jcr->JobLevel = joblevels[i].level;
+               return 0;
+            }
+         }
+      }
+      PyErr_SetString(PyExc_ValueError, _("Bad JobLevel string"));
+      return -1;
    }
 bail_out:
    PyErr_SetString(PyExc_AttributeError, attrname);
 
             bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
          }
          break;
+      } else if (strcasecmp(ua->argk[i], _("jobuid")) == 0) {
+         if (!ua->argv[i]) {
+            break;
+         }
+         if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
+            bsendmsg(ua, _("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
+            jcr = new_jcr(sizeof(JCR), dird_free_jcr);
+            bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
+         }
+         break;
       }
+
    }
    /* If we still do not have a jcr,
     *   throw up a list and ask the user to select one.
             return 1;
          }
       }
-      /* NOTE! This increments the ref_count */
       sscanf(buf, "JobId=%d Job=%127s", &njobs, JobName);
       jcr = get_jcr_by_full_name(JobName);
       if (!jcr) {
 
  *
  *  list jobs           - lists all jobs run
  *  list jobid=nnn      - list job data for jobid
- *  list job=name       - list job data for job
+ *  list jobuid=uname   - list job data for unique jobid
+ *  list job=name       - list all jobs with "name"   
+ *  list jobname=name   - same as above 
  *  list jobmedia jobid=<nn>
  *  list jobmedia job=name
  *  list files jobid=<nn> - list files saved for job nn
          }
 
       /* List JOB=xxx */
-      } else if (strcasecmp(ua->argk[i], N_("job")) == 0 && ua->argv[i]) {
-         bstrncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
+      } else if ((strcasecmp(ua->argk[i], N_("job")) == 0 ||
+                  strcasecmp(ua->argk[i], N_("jobname")) == 0) && ua->argv[i]) {
+         bstrncpy(jr.Name, ua->argv[i], MAX_NAME_LENGTH);
          jr.JobId = 0;
          db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, llist);
 
-      /* List JOBNAME=xxx */
-      } else if (strcasecmp(ua->argk[i], N_("job")) == 0 && ua->argv[i]) {
-         bstrncpy(jr.Name, ua->argv[i], MAX_NAME_LENGTH);
+      /* List JOBUID=xxx */
+      } else if (strcasecmp(ua->argk[i], N_("jobuid")) == 0 && ua->argv[i]) {
+         bstrncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
          jr.JobId = 0;
          db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, llist);
 
-
       /* List FILES */
       } else if (strcasecmp(ua->argk[i], N_("files")) == 0) {
 
          for (j=i+1; j<ua->argc; j++) {
-            if (strcasecmp(ua->argk[j], N_("job")) == 0 && ua->argv[j]) {
+            if (strcasecmp(ua->argk[j], N_("jobuid")) == 0 && ua->argv[j]) {
                bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH);
                jr.JobId = 0;
                db_get_job_record(ua->jcr, ua->db, &jr);
       } else if (strcasecmp(ua->argk[i], N_("jobmedia")) == 0) {
          int done = FALSE;
          for (j=i+1; j<ua->argc; j++) {
-            if (strcasecmp(ua->argk[j], N_("job")) == 0 && ua->argv[j]) {
+            if (strcasecmp(ua->argk[j], N_("jobuid")) == 0 && ua->argv[j]) {
                bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH);
                jr.JobId = 0;
                db_get_job_record(ua->jcr, ua->db, &jr);
                  strcasecmp(ua->argk[i], N_("volumes")) == 0) {
          bool done = false;
          for (j=i+1; j<ua->argc; j++) {
-            if (strcasecmp(ua->argk[j], N_("job")) == 0 && ua->argv[j]) {
+            if (strcasecmp(ua->argk[j], N_("jobuid")) == 0 && ua->argv[j]) {
                bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH);
                jr.JobId = 0;
                db_get_job_record(ua->jcr, ua->db, &jr);
 
    int i;
 
    for (i=1; i<ua->argc; i++) {
-      if (strcasecmp(ua->argk[i], N_("job")) == 0 && ua->argv[i]) {
+      if (strcasecmp(ua->argk[i], N_("jobuid")) == 0 && ua->argv[i]) {
          jr->JobId = 0;
          bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
       } else if (strcasecmp(ua->argk[i], N_("jobid")) == 0 && ua->argv[i]) {
    jr->Job[0] = 0;
 
    for (i=1; i<ua->argc; i++) {
-      if (strcasecmp(ua->argk[i], N_("jobname")) == 0 && ua->argv[i]) {
+      if ((strcasecmp(ua->argk[i], N_("jobname")) == 0 ||
+           strcasecmp(ua->argk[i], N_("job")) == 0) && ua->argv[i]) {
          jr->JobId = 0;
          bstrncpy(jr->Name, ua->argv[i], sizeof(jr->Name));
          break;
             free_jcr(jcr);
             break;
 
-         } else if (strcasecmp(ua->argk[i], N_("job")) == 0) {
+         } else if (strcasecmp(ua->argk[i], N_("job")) == 0 ||
+                    strcasecmp(ua->argk[i], N_("jobname")) == 0) {
             if (!ua->argv[i]) {
                bsendmsg(ua, _("Expecting job=xxx, got: %s.\n"), ua->argk[i]);
                return NULL;
             store = jcr->store;
             free_jcr(jcr);
             break;
+         } else if (strcasecmp(ua->argk[i], N_("jobuid")) == 0) {
+            if (!ua->argv[i]) {
+               bsendmsg(ua, _("Expecting jobuid=xxx, got: %s.\n"), ua->argk[i]);
+               return NULL;
+            }
+            if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
+               bsendmsg(ua, _("Job \"%s\" is not running.\n"), ua->argv[i]);
+               return NULL;
+            }
+            store = jcr->store;
+            free_jcr(jcr);
+            break;
         }
       }
    }
 
 
 #undef  VERSION
 #define VERSION "1.39.6"
-#define BDATE   "26 February 2006"
-#define LSMDATE "26Feb06"
+#define BDATE   "27 February 2006"
+#define LSMDATE "27Feb06"
 
 /* Debug flags */
 #undef  DEBUG