]> git.sur5r.net Git - bacula/bacula/commitdiff
- Make JCR a class and implement inc_use_count() and
authorKern Sibbald <kern@sibbald.com>
Thu, 26 May 2005 18:58:17 +0000 (18:58 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 26 May 2005 18:58:17 +0000 (18:58 +0000)
  dec_use_count() methods that ensure that the jcr is
  locked when inc/dec the use count.
- Remove the global jcr lock when traversing the jcr
  chain.
- Use dlist to implement the jcr chain rather than hand
  crafted next and prev links.
- Lock the jcr chain inside each function that modifies
  the chain.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2089 91ce42f0-d328-0410-95d8-f526ca767f89

17 files changed:
bacula/kernstodo
bacula/kes-1.37
bacula/src/dird/dird.c
bacula/src/dird/job.c
bacula/src/dird/jobq.c
bacula/src/dird/pythondir.c
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_status.c
bacula/src/filed/status.c
bacula/src/jcr.h
bacula/src/lib/dlist.h
bacula/src/lib/jcr.c
bacula/src/lib/watchdog.c
bacula/src/stored/askdir.c
bacula/src/stored/status.c
bacula/src/stored/stored.c
bacula/src/version.h

index f64d347891b01283b6195ce1e095a31a62061b4a..c3d0325758d264c3f9ce7b8072b5f3e187397c31 100644 (file)
@@ -1,5 +1,5 @@
                     Kern's ToDo List
-                     20 May 2005
+                     26 May 2005
 
 Major development:      
 Project                     Developer
@@ -52,13 +52,9 @@ Document:
 - Document testing
 - Document that ChangerDevice is used for Alert command.
 - Document new CDROM directory.
+- Document Heartbeat Interval in the dealing with firewalls section.
 
 For 1.37:
-- From Chris Hull:
-   it seems to be complaining about 12:00pm which should be a valid 12
-   hour time.  I changed the time to 11:59am and everything works fine.
-   Also 12:00am works fine.  0:00pm also works (which I don't think
-   should).  None of the values 12:00pm - 12:59pm work for that matter.
 === rate design
   jcr->last_rate
   jcr->last_runtime
@@ -1284,3 +1280,9 @@ Block Position: 0
 - Add "limit=n" for "list jobs"
 - Make bootstrap filename unique.
 - Make Dmsg look at global before calling subroutine.
+- From Chris Hull:
+   it seems to be complaining about 12:00pm which should be a valid 12
+   hour time.  I changed the time to 11:59am and everything works fine.
+   Also 12:00am works fine.  0:00pm also works (which I don't think
+   should).  None of the values 12:00pm - 12:59pm work for that matter.
+
index edd1500e03957fa74696e9e560dbf429d7c56b9b..b5a483f514ca07bd76be53b3bfa978514a4b8c0d 100644 (file)
@@ -3,6 +3,18 @@
 
 General:
 
+Changes to 1.37.20:
+26May05
+- Make JCR a class and implement inc_use_count() and
+  dec_use_count() methods that ensure that the jcr is
+  locked when inc/dec the use count.
+- Remove the global jcr lock when traversing the jcr
+  chain.   
+- Use dlist to implement the jcr chain rather than hand
+  crafted next and prev links.
+- Lock the jcr chain inside each function that modifies
+  the chain.
+
 Changes to 1.37.19:
 26May05
 - Fix compile problem of ua_restore.c on broken compilers.
index e28738c4e8bf07e6d63728ad6e30ab80291d7692..b8ee906569dfc0824dc49858e97823c4657aac04 100644 (file)
@@ -392,8 +392,6 @@ void reload_config(int sig)
    sigaddset(&set, SIGHUP);
    sigprocmask(SIG_BLOCK, &set, NULL);
 
-// Jmsg(NULL, M_INFO, 0, "Entering experimental reload config code. Bug reports will not be accepted.\n");
-
    lock_jcr_chain();
    LockRes();
 
@@ -437,7 +435,7 @@ void reload_config(int sig)
             job_end_push(jcr, reload_job_end_cb, (void *)((long int)table));
             njobs++;
          }
-         free_locked_jcr(jcr);
+         free_jcr(jcr);
       }
    }
 
@@ -447,8 +445,6 @@ void reload_config(int sig)
    SDConnectTimeout = director->SDConnectTimeout;
    Dmsg0(0, "Director's configuration file reread.\n");
 
-// init_device_resources();           /* Update Device resources */
-
    /* Now release saved resources, if no jobs using the resources */
    if (njobs == 0) {
       free_saved_resources(table);
index 5f5de77d8d039d09a4243da6b93fe35f8dd36673..9c6ba26e342557a8211fa1f7a688deef922c68e1 100644 (file)
    Copyright (C) 2000-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+   modify it under the terms of the GNU General Public License
+   version 2 as ammended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
@@ -445,8 +440,6 @@ static void job_monitor_watchdog(watchdog_t *self)
 
    Dmsg1(800, "job_monitor_watchdog %p called\n", self);
 
-   lock_jcr_chain();
-
    foreach_jcr(jcr) {
       bool cancel;
 
@@ -454,7 +447,7 @@ static void job_monitor_watchdog(watchdog_t *self)
          Dmsg2(800, "Skipping JCR %p (%s) with JobId 0\n",
                jcr, jcr->Job);
          /* Keep reference counts correct */
-         free_locked_jcr(jcr);
+         free_jcr(jcr);
          continue;
       }
 
@@ -477,9 +470,8 @@ static void job_monitor_watchdog(watchdog_t *self)
       }
 
       /* Keep reference counts correct */
-      free_locked_jcr(jcr);
+      free_jcr(jcr);
    }
-   unlock_jcr_chain();
 }
 
 /*
index ccc794e92923b6862609f678f84a2ae9b37bba3e..acbdba743f8c1baf61faac29c5e167b180ee6179 100755 (executable)
@@ -229,7 +229,6 @@ int jobq_add(jobq_t *jq, JCR *jcr)
       sched_pkt = (wait_pkt *)malloc(sizeof(wait_pkt));
       sched_pkt->jcr = jcr;
       sched_pkt->jq = jq;
-//    jcr->use_count--;            /* release our use of jcr */
       stat = pthread_create(&id, &jq->attr, sched_wait, (void *)sched_pkt);        
       if (stat != 0) {                /* thread not created */
          berrno be;
index 77245b07dbb31f8279d8fe7459848f08b81b7b94..d7dbe335c8cfe63ca08416137efb5a90e6cfbc3d 100644 (file)
@@ -7,24 +7,18 @@
  *   Version $Id$
  *
  */
-
 /*
    Copyright (C) 2004-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+   modify it under the terms of the GNU General Public License
+   version 2 as ammended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
@@ -296,23 +290,20 @@ static PyObject *job_cancel(PyObject *self, PyObject *args)
       Dmsg0(000, "Parse tuple error in job_write\n");
       return NULL;
    }
-   lock_jcr_chain();
    foreach_jcr(jcr) {
       if (jcr->JobId == 0) {
-        free_locked_jcr(jcr);           /* OK to free now cuz chain is locked */
+         free_jcr(jcr);
          continue;
       }
       if (jcr->JobId == JobId) {
          found = true;
-        break;
+         break;
       }
    }
    if (!found) {
-      unlock_jcr_chain();
       /* ***FIXME*** raise exception */
       return NULL;
    }
-   unlock_jcr_chain();
    PyEval_ReleaseLock();
    UAContext *ua = new_ua_context(jcr);
    ua->batch = true;
@@ -321,7 +312,7 @@ static PyObject *job_cancel(PyObject *self, PyObject *args)
       return NULL;
    }
    free_ua_context(ua);
-   free_locked_jcr(jcr);
+   free_jcr(jcr);
    PyEval_AcquireLock();   
    Py_INCREF(Py_None);
    return Py_None;
index 77aedf191e52bb695ac934abd40d0620f93e6667..471315ed06c6fb41854704a90a9af1b052ebdb20 100644 (file)
@@ -6,24 +6,18 @@
  *
  *   Version $Id$
  */
-
 /*
    Copyright (C) 2000-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+   modify it under the terms of the GNU General Public License
+   version 2 as ammended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
@@ -399,33 +393,29 @@ static int cancel_cmd(UAContext *ua, const char *cmd)
    if (!jcr) {
       char buf[1000];
       /* Count Jobs running */
-      lock_jcr_chain();
       foreach_jcr(jcr) {
          if (jcr->JobId == 0) {      /* this is us */
-            free_locked_jcr(jcr);
+            free_jcr(jcr);
             continue;
          }
-         free_locked_jcr(jcr);
+         free_jcr(jcr);
          njobs++;
       }
-      unlock_jcr_chain();
 
       if (njobs == 0) {
          bsendmsg(ua, _("No Jobs running.\n"));
          return 1;
       }
       start_prompt(ua, _("Select Job:\n"));
-      lock_jcr_chain();
       foreach_jcr(jcr) {
          if (jcr->JobId == 0) {      /* this is us */
-            free_locked_jcr(jcr);
+            free_jcr(jcr);
             continue;
          }
          bsnprintf(buf, sizeof(buf), "JobId=%d Job=%s", jcr->JobId, jcr->Job);
          add_prompt(ua, buf);
-         free_locked_jcr(jcr);
+         free_jcr(jcr);
       }
-      unlock_jcr_chain();
 
       if (do_prompt(ua, _("Job"),  _("Choose Job to cancel"), buf, sizeof(buf)) < 0) {
          return 1;
@@ -1355,16 +1345,14 @@ int wait_cmd(UAContext *ua, const char *cmd)
    bmicrosleep(0, 200000);            /* let job actually start */
    for (bool running=true; running; ) {
       running = false;
-      lock_jcr_chain();
       foreach_jcr(jcr) {
          if (jcr->JobId != 0) {
             running = true;
-            free_locked_jcr(jcr);
+            free_jcr(jcr);
             break;
          }
-         free_locked_jcr(jcr);
+         free_jcr(jcr);
       }
-      unlock_jcr_chain();
       if (running) {
          bmicrosleep(1, 0);
       }
index 9e97944a2cf61c5a095d9f5a9c4b042db700b576..499d0c8c732fcef03946ed0b958312b605deb193 100644 (file)
@@ -6,27 +6,22 @@
  *
  *   Version $Id$
  */
-
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2001-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+   modify it under the terms of the GNU General Public License
+   version 2 as ammended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
+
 #include "bacula.h"
 #include "dird.h"
 
@@ -65,20 +60,18 @@ int qstatus_cmd(UAContext *ua, const char *cmd)
 
    if (strcasecmp(ua->argk[2], "current") == 0) {
       bsendmsg(ua, OKqstatus, ua->argk[2]);
-      lock_jcr_chain();
       foreach_jcr(njcr) {
-        if (njcr->JobId != 0) {
-           bsendmsg(ua, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
-        }
-        free_locked_jcr(njcr);
+         if (njcr->JobId != 0) {
+            bsendmsg(ua, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
+         }
+         free_jcr(njcr);
       }
-      unlock_jcr_chain();
    }
    else if (strcasecmp(ua->argk[2], "last") == 0) {
       bsendmsg(ua, OKqstatus, ua->argk[2]);
       if ((last_jobs) && (last_jobs->size() > 0)) {
-        job = (s_last_job*)last_jobs->last();
-        bsendmsg(ua, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
+         job = (s_last_job*)last_jobs->last();
+         bsendmsg(ua, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
       }
    }
    else {
@@ -105,24 +98,24 @@ int status_cmd(UAContext *ua, const char *cmd)
 
    for (i=1; i<ua->argc; i++) {
       if (strcasecmp(ua->argk[i], _("all")) == 0) {
-        do_all_status(ua);
-        return 1;
+         do_all_status(ua);
+         return 1;
       } else if (strcasecmp(ua->argk[i], _("dir")) == 0 ||
                  strcasecmp(ua->argk[i], _("director")) == 0) {
-        do_director_status(ua);
-        return 1;
+         do_director_status(ua);
+         return 1;
       } else if (strcasecmp(ua->argk[i], _("client")) == 0) {
-        client = get_client_resource(ua);
-        if (client) {
-           do_client_status(ua, client);
-        }
-        return 1;
+         client = get_client_resource(ua);
+         if (client) {
+            do_client_status(ua, client);
+         }
+         return 1;
       } else {
-        store = get_storage_resource(ua, 0);
-        if (store) {
-           do_storage_status(ua, store);
-        }
-        return 1;
+         store = get_storage_resource(ua, 0);
+         if (store) {
+            do_storage_status(ua, store);
+         }
+         return 1;
       }
    }
    /* If no args, ask for status type */
@@ -136,30 +129,30 @@ int status_cmd(UAContext *ua, const char *cmd)
       add_prompt(ua, _("All"));
       Dmsg0(20, "do_prompt: select daemon\n");
       if ((item=do_prompt(ua, "",  _("Select daemon type for status"), prmt, sizeof(prmt))) < 0) {
-        return 1;
+         return 1;
       }
       Dmsg1(20, "item=%d\n", item);
       switch (item) {
-      case 0:                        /* Director */
-        do_director_status(ua);
-        break;
+      case 0:                         /* Director */
+         do_director_status(ua);
+         break;
       case 1:
-        store = select_storage_resource(ua);
-        if (store) {
-           do_storage_status(ua, store);
-        }
-        break;
+         store = select_storage_resource(ua);
+         if (store) {
+            do_storage_status(ua, store);
+         }
+         break;
       case 2:
-        client = select_client_resource(ua);
-        if (client) {
-           do_client_status(ua, client);
-        }
-        break;
+         client = select_client_resource(ua);
+         if (client) {
+            do_client_status(ua, client);
+         }
+         break;
       case 3:
-        do_all_status(ua);
-        break;
+         do_all_status(ua);
+         break;
       default:
-        break;
+         break;
       }
    }
    return 1;
@@ -186,17 +179,17 @@ static void do_all_status(UAContext *ua)
    foreach_res(store, R_STORAGE) {
       found = false;
       if (!acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
-        continue;
+         continue;
       }
       for (j=0; j<i; j++) {
-        if (strcmp(unique_store[j]->address, store->address) == 0 &&
-            unique_store[j]->SDport == store->SDport) {
-           found = true;
-           break;
-        }
+         if (strcmp(unique_store[j]->address, store->address) == 0 &&
+             unique_store[j]->SDport == store->SDport) {
+            found = true;
+            break;
+         }
       }
       if (!found) {
-        unique_store[i++] = store;
+         unique_store[i++] = store;
          Dmsg2(40, "Stuffing: %s:%d\n", store->address, store->SDport);
       }
    }
@@ -220,17 +213,17 @@ static void do_all_status(UAContext *ua)
    foreach_res(client, R_CLIENT) {
       found = false;
       if (!acl_access_ok(ua, Client_ACL, client->hdr.name)) {
-        continue;
+         continue;
       }
       for (j=0; j<i; j++) {
-        if (strcmp(unique_client[j]->address, client->address) == 0 &&
-            unique_client[j]->FDport == client->FDport) {
-           found = true;
-           break;
-        }
+         if (strcmp(unique_client[j]->address, client->address) == 0 &&
+             unique_client[j]->FDport == client->FDport) {
+            found = true;
+            break;
+         }
       }
       if (!found) {
-        unique_client[i++] = client;
+         unique_client[i++] = client;
          Dmsg2(40, "Stuffing: %s:%d\n", client->address, client->FDport);
       }
    }
@@ -249,17 +242,17 @@ static void do_director_status(UAContext *ua)
    char dt[MAX_TIME_LENGTH];
 
    bsendmsg(ua, "%s Version: " VERSION " (" BDATE ") %s %s %s\n", my_name,
-           HOST_OS, DISTNAME, DISTVER);
+            HOST_OS, DISTNAME, DISTVER);
    bstrftime_nc(dt, sizeof(dt), daemon_start_time);
    bsendmsg(ua, _("Daemon started %s, %d Job%s run since started.\n"),
         dt, num_jobs_run, num_jobs_run == 1 ? "" : "s");
    if (debug_level > 0) {
       char b1[35], b2[35], b3[35], b4[35];
       bsendmsg(ua, _(" Heap: bytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
-           edit_uint64_with_commas(sm_bytes, b1),
-           edit_uint64_with_commas(sm_max_bytes, b2),
-           edit_uint64_with_commas(sm_buffers, b3),
-           edit_uint64_with_commas(sm_max_buffers, b4));
+            edit_uint64_with_commas(sm_bytes, b1),
+            edit_uint64_with_commas(sm_max_bytes, b2),
+            edit_uint64_with_commas(sm_buffers, b3),
+            edit_uint64_with_commas(sm_max_buffers, b4));
    }
    /*
     * List scheduled Jobs
@@ -288,10 +281,10 @@ static void do_storage_status(UAContext *ua, STORE *store)
       store->hdr.name, store->address, store->SDport);
    if (!connect_to_storage_daemon(ua->jcr, 1, 15, 0)) {
       bsendmsg(ua, _("\nFailed to connect to Storage daemon %s.\n====\n"),
-        store->hdr.name);
+         store->hdr.name);
       if (ua->jcr->store_bsock) {
-        bnet_close(ua->jcr->store_bsock);
-        ua->jcr->store_bsock = NULL;
+         bnet_close(ua->jcr->store_bsock);
+         ua->jcr->store_bsock = NULL;
       }
       return;
    }
@@ -326,10 +319,10 @@ static void do_client_status(UAContext *ua, CLIENT *client)
       client->hdr.name, client->address, client->FDport);
    if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
       bsendmsg(ua, _("Failed to connect to Client %s.\n====\n"),
-        client->hdr.name);
+         client->hdr.name);
       if (ua->jcr->file_bsock) {
-        bnet_close(ua->jcr->file_bsock);
-        ua->jcr->file_bsock = NULL;
+         bnet_close(ua->jcr->file_bsock);
+         ua->jcr->file_bsock = NULL;
       }
       return;
    }
@@ -355,7 +348,7 @@ static void prt_runhdr(UAContext *ua)
 
 /* Scheduling packet */
 struct sched_pkt {
-   dlink link;                       /* keep this as first item!!! */
+   dlink link;                        /* keep this as first item!!! */
    JOB *job;
    int level;
    int priority;
@@ -377,11 +370,11 @@ static void prt_runtime(UAContext *ua, sched_pkt *sp)
       jcr->db = NULL;
       ok = complete_jcr_for_job(jcr, sp->job, sp->pool);
       if (jcr->db) {
-        close_db = true;             /* new db opened, remember to close it */
+         close_db = true;             /* new db opened, remember to close it */
       }
       if (ok) {
          mr.PoolId = jcr->PoolId;
-        ok = find_next_volume_for_append(jcr, &mr, 0);
+         ok = find_next_volume_for_append(jcr, &mr, 0);
       }
       if (!ok) {
          bstrncpy(mr.VolumeName, "*unknown*", sizeof(mr.VolumeName));
@@ -403,7 +396,7 @@ static void prt_runtime(UAContext *ua, sched_pkt *sp)
    if (close_db) {
       db_close_database(jcr, jcr->db);
    }
-   jcr->db = ua->db;                 /* restore ua db to jcr */
+   jcr->db = ua->db;                  /* restore ua db to jcr */
 
 }
 
@@ -448,29 +441,29 @@ static void list_scheduled_jobs(UAContext *ua)
    LockRes();
    foreach_res(job, R_JOB) {
       if (!acl_access_ok(ua, Job_ACL, job->hdr.name)) {
-        continue;
+         continue;
       }
       for (run=NULL; (run = find_next_run(run, job, runtime)); ) {
-        level = job->JobLevel;
-        if (run->level) {
-           level = run->level;
-        }
-        priority = job->Priority;
-        if (run->Priority) {
-           priority = run->Priority;
-        }
-        if (!hdr_printed) {
-           prt_runhdr(ua);
-           hdr_printed = true;
-        }
-        sp = (sched_pkt *)malloc(sizeof(sched_pkt));
-        sp->job = job;
-        sp->level = level;
-        sp->priority = priority;
-        sp->runtime = runtime;
-        sp->pool = run->pool;
-        sched.binary_insert(sp, my_compare);
-        num_jobs++;
+         level = job->JobLevel;
+         if (run->level) {
+            level = run->level;
+         }
+         priority = job->Priority;
+         if (run->Priority) {
+            priority = run->Priority;
+         }
+         if (!hdr_printed) {
+            prt_runhdr(ua);
+            hdr_printed = true;
+         }
+         sp = (sched_pkt *)malloc(sizeof(sched_pkt));
+         sp->job = job;
+         sp->level = level;
+         sp->priority = priority;
+         sp->runtime = runtime;
+         sp->pool = run->pool;
+         sched.binary_insert(sp, my_compare);
+         num_jobs++;
       }
    } /* end for loop over resources */
    UnlockRes();
@@ -489,30 +482,28 @@ static void list_running_jobs(UAContext *ua)
    JCR *jcr;
    int njobs = 0;
    const char *msg;
-   char *emsg;                       /* edited message */
+   char *emsg;                        /* edited message */
    char dt[MAX_TIME_LENGTH];
    char level[10];
    bool pool_mem = false;
 
    Dmsg0(200, "enter list_run_jobs()\n");
    bsendmsg(ua, _("\nRunning Jobs:\n"));
-   lock_jcr_chain();
    foreach_jcr(jcr) {
       njobs++;
-      if (jcr->JobId == 0) {     /* this is us */
-        /* this is a console or other control job. We only show console
-         * jobs in the status output.
-         */
-        if (jcr->JobType == JT_CONSOLE) {
-           bstrftime_nc(dt, sizeof(dt), jcr->start_time);
+      if (jcr->JobId == 0) {      /* this is us */
+         /* this is a console or other control job. We only show console
+          * jobs in the status output.
+          */
+         if (jcr->JobType == JT_CONSOLE) {
+            bstrftime_nc(dt, sizeof(dt), jcr->start_time);
             bsendmsg(ua, _("Console connected at %s\n"), dt);
-        }
-        njobs--;
+         }
+         njobs--;
       }
-      free_locked_jcr(jcr);
+      free_jcr(jcr);
    }
    if (njobs == 0) {
-      unlock_jcr_chain();
       /* Note the following message is used in regress -- don't change */
       bsendmsg(ua, _("No Jobs running.\n====\n"));
       Dmsg0(200, "leave list_run_jobs()\n");
@@ -523,128 +514,127 @@ static void list_running_jobs(UAContext *ua)
    bsendmsg(ua, _("======================================================================\n"));
    foreach_jcr(jcr) {
       if (jcr->JobId == 0 || !acl_access_ok(ua, Job_ACL, jcr->job->hdr.name)) {
-        free_locked_jcr(jcr);
-        continue;
+         free_jcr(jcr);
+         continue;
       }
       njobs++;
       switch (jcr->JobStatus) {
       case JS_Created:
          msg = _("is waiting execution");
-        break;
+         break;
       case JS_Running:
          msg = _("is running");
-        break;
+         break;
       case JS_Blocked:
          msg = _("is blocked");
-        break;
+         break;
       case JS_Terminated:
          msg = _("has terminated");
-        break;
+         break;
       case JS_ErrorTerminated:
          msg = _("has erred");
-        break;
+         break;
       case JS_Error:
          msg = _("has errors");
-        break;
+         break;
       case JS_FatalError:
          msg = _("has a fatal error");
-        break;
+         break;
       case JS_Differences:
          msg = _("has verify differences");
-        break;
+         break;
       case JS_Canceled:
          msg = _("has been canceled");
-        break;
+         break;
       case JS_WaitFD:
-        emsg = (char *) get_pool_memory(PM_FNAME);
+         emsg = (char *) get_pool_memory(PM_FNAME);
          Mmsg(emsg, _("is waiting on Client %s"), jcr->client->hdr.name);
-        pool_mem = true;
-        msg = emsg;
-        break;
+         pool_mem = true;
+         msg = emsg;
+         break;
       case JS_WaitSD:
-        emsg = (char *) get_pool_memory(PM_FNAME);
+         emsg = (char *) get_pool_memory(PM_FNAME);
          Mmsg(emsg, _("is waiting on Storage %s"), jcr->store->hdr.name);
-        pool_mem = true;
-        msg = emsg;
-        break;
+         pool_mem = true;
+         msg = emsg;
+         break;
       case JS_WaitStoreRes:
          msg = _("is waiting on max Storage jobs");
-        break;
+         break;
       case JS_WaitClientRes:
          msg = _("is waiting on max Client jobs");
-        break;
+         break;
       case JS_WaitJobRes:
          msg = _("is waiting on max Job jobs");
-        break;
+         break;
       case JS_WaitMaxJobs:
          msg = _("is waiting on max total jobs");
-        break;
+         break;
       case JS_WaitStartTime:
          msg = _("is waiting for its start time");
-        break;
+         break;
       case JS_WaitPriority:
          msg = _("is waiting for higher priority jobs to finish");
-        break;
+         break;
 
       default:
-        emsg = (char *) get_pool_memory(PM_FNAME);
+         emsg = (char *) get_pool_memory(PM_FNAME);
          Mmsg(emsg, _("is in unknown state %c"), jcr->JobStatus);
-        pool_mem = true;
-        msg = emsg;
-        break;
+         pool_mem = true;
+         msg = emsg;
+         break;
       }
       /*
        * Now report Storage daemon status code
        */
       switch (jcr->SDJobStatus) {
       case JS_WaitMount:
-        if (pool_mem) {
-           free_pool_memory(emsg);
-           pool_mem = false;
-        }
+         if (pool_mem) {
+            free_pool_memory(emsg);
+            pool_mem = false;
+         }
          msg = _("is waiting for a mount request");
-        break;
+         break;
       case JS_WaitMedia:
-        if (pool_mem) {
-           free_pool_memory(emsg);
-           pool_mem = false;
-        }
+         if (pool_mem) {
+            free_pool_memory(emsg);
+            pool_mem = false;
+         }
          msg = _("is waiting for an appendable Volume");
-        break;
+         break;
       case JS_WaitFD:
-        if (!pool_mem) {
-           emsg = (char *) get_pool_memory(PM_FNAME);
-           pool_mem = true;
-        }
+         if (!pool_mem) {
+            emsg = (char *) get_pool_memory(PM_FNAME);
+            pool_mem = true;
+         }
          Mmsg(emsg, _("is waiting for Client %s to connect to Storage %s"),
-             jcr->client->hdr.name, jcr->store->hdr.name);
-        msg = emsg;
-        break;
+              jcr->client->hdr.name, jcr->store->hdr.name);
+         msg = emsg;
+         break;
       }
       switch (jcr->JobType) {
       case JT_ADMIN:
       case JT_RESTORE:
          bstrncpy(level, "      ", sizeof(level));
-        break;
+         break;
       default:
-        bstrncpy(level, level_to_str(jcr->JobLevel), sizeof(level));
-        level[7] = 0;
-        break;
+         bstrncpy(level, level_to_str(jcr->JobLevel), sizeof(level));
+         level[7] = 0;
+         break;
       }
 
       bsendmsg(ua, _("%6d %-6s  %-20s %s\n"),
-        jcr->JobId,
-        level,
-        jcr->Job,
-        msg);
+         jcr->JobId,
+         level,
+         jcr->Job,
+         msg);
 
       if (pool_mem) {
-        free_pool_memory(emsg);
-        pool_mem = false;
+         free_pool_memory(emsg);
+         pool_mem = false;
       }
-      free_locked_jcr(jcr);
+      free_jcr(jcr);
    }
-   unlock_jcr_chain();
    bsendmsg(ua, "====\n");
    Dmsg0(200, "leave list_run_jobs()\n");
 }
@@ -672,12 +662,12 @@ static void list_terminated_jobs(UAContext *ua)
       char *p;
       for (int i=0; i<3; i++) {
          if ((p=strrchr(JobName, '.')) != NULL) {
-           *p = 0;
-        }
+            *p = 0;
+         }
       }
 
       if (!acl_access_ok(ua, Job_ACL, JobName)) {
-        continue;
+         continue;
       }
 
       bstrftime_nc(dt, sizeof(dt), je->end_time);
@@ -685,40 +675,40 @@ static void list_terminated_jobs(UAContext *ua)
       case JT_ADMIN:
       case JT_RESTORE:
          bstrncpy(level, "    ", sizeof(level));
-        break;
+         break;
       default:
-        bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
-        level[4] = 0;
-        break;
+         bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
+         level[4] = 0;
+         break;
       }
       switch (je->JobStatus) {
       case JS_Created:
          termstat = "Created";
-        break;
+         break;
       case JS_FatalError:
       case JS_ErrorTerminated:
          termstat = "Error";
-        break;
+         break;
       case JS_Differences:
          termstat = "Diffs";
-        break;
+         break;
       case JS_Canceled:
          termstat = "Cancel";
-        break;
+         break;
       case JS_Terminated:
          termstat = "OK";
-        break;
+         break;
       default:
          termstat = "Other";
-        break;
+         break;
       }
       bsendmsg(ua, _("%6d  %-6s %8s %14s %-7s  %-8s %s\n"),
-        je->JobId,
-        level,
-        edit_uint64_with_commas(je->JobFiles, b1),
-        edit_uint64_with_commas(je->JobBytes, b2),
-        termstat,
-        dt, JobName);
+         je->JobId,
+         level,
+         edit_uint64_with_commas(je->JobFiles, b1),
+         edit_uint64_with_commas(je->JobBytes, b2),
+         termstat,
+         dt, JobName);
    }
    bsendmsg(ua, "\n");
    unlock_last_jobs_list();
index 7fa0829aa0f71fc83d6b5ed8c4e5ce38f265df16..398ad673198cbd08f9f2da01a1036780b7f0700a 100755 (executable)
@@ -63,16 +63,16 @@ static void do_status(void sendit(const char *msg, int len, void *sarg), void *a
    msg = (char *)get_pool_memory(PM_MESSAGE);
    found = 0;
    len = Mmsg(msg, "%s Version: " VERSION " (" BDATE ") %s %s %s\n", my_name,
-             HOST_OS, DISTNAME, DISTVER);
+              HOST_OS, DISTNAME, DISTVER);
    sendit(msg, len, arg);
    bstrftime_nc(dt, sizeof(dt), daemon_start_time);
    len = Mmsg(msg, _("Daemon started %s, %d Job%s run since started.\n"),
-       dt, num_jobs_run, num_jobs_run == 1 ? "" : "s");
+        dt, num_jobs_run, num_jobs_run == 1 ? "" : "s");
    sendit(msg, len, arg);
 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
    if (/*debug_level > 0*/ true) {
       if (!privs) {
-        privs = enable_backup_privileges(NULL, 1);
+         privs = enable_backup_privileges(NULL, 1);
       }
       len = Mmsg(msg,
      _(" Priv 0x%x\n APIs=%sOPT,%sATP,%sLPV,%sCFA,%sCFW,\n"
@@ -80,12 +80,12 @@ static void do_status(void sendit(const char *msg, int len, void *sarg), void *a
      " %sWC2MB,%sMB2WC,%sFFFA,%sFFFW,%sFNFA,%sFNFW,%sSCDA,%sSCDW,\n"
      " %sGCDA,%sGCDW\n"), 
      privs,
-        p_OpenProcessToken?"":"!",
-        p_AdjustTokenPrivileges?"":"!",
-        p_LookupPrivilegeValue?"":"!",
+         p_OpenProcessToken?"":"!",
+         p_AdjustTokenPrivileges?"":"!",
+         p_LookupPrivilegeValue?"":"!",
 
     p_CreateFileA?"":"!",
-        p_CreateFileW?"":"!",
+         p_CreateFileW?"":"!",
 
     p_wunlink?"":"!",
     p_wmkdir?"":"!",
@@ -95,13 +95,13 @@ static void do_status(void sendit(const char *msg, int len, void *sarg), void *a
     p_GetFileAttributesW?"":"!",
 
     p_GetFileAttributesExA?"":"!",
-        p_GetFileAttributesExW?"":"!",
+         p_GetFileAttributesExW?"":"!",
 
     p_SetFileAttributesA?"":"!",
-        p_SetFileAttributesW?"":"!",
-        p_BackupRead?"":"!",
-        p_BackupWrite?"":"!",
-        p_SetProcessShutdownParameters?"":"!",
+         p_SetFileAttributesW?"":"!",
+         p_BackupRead?"":"!",
+         p_BackupWrite?"":"!",
+         p_SetProcessShutdownParameters?"":"!",
 
     p_WideCharToMultiByte?"":"!",
     p_MultiByteToWideChar?"":"!",
@@ -122,13 +122,13 @@ static void do_status(void sendit(const char *msg, int len, void *sarg), void *a
 #endif
    if (debug_level > 0) {
       len = Mmsg(msg, _(" Heap: bytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
-           edit_uint64_with_commas(sm_bytes, b1),
-           edit_uint64_with_commas(sm_max_bytes, b2),
-           edit_uint64_with_commas(sm_buffers, b3),
-           edit_uint64_with_commas(sm_max_buffers, b4));
+            edit_uint64_with_commas(sm_bytes, b1),
+            edit_uint64_with_commas(sm_max_bytes, b2),
+            edit_uint64_with_commas(sm_buffers, b3),
+            edit_uint64_with_commas(sm_max_buffers, b4));
       sendit(msg, len, arg);
       len = Mmsg(msg, _(" Sizeof: off_t=%d size_t=%d debug=%d trace=%d\n"),
-           sizeof(off_t), sizeof(size_t), debug_level, get_trace());
+            sizeof(off_t), sizeof(size_t), debug_level, get_trace());
       sendit(msg, len, arg);
    }
 
@@ -140,55 +140,53 @@ static void do_status(void sendit(const char *msg, int len, void *sarg), void *a
    Dmsg0(1000, "Begin status jcr loop.\n");
    len = Mmsg(msg, _("Running Jobs:\n"));
    sendit(msg, len, arg);
-   lock_jcr_chain();
    foreach_jcr(njcr) {
       bstrftime_nc(dt, sizeof(dt), njcr->start_time);
       if (njcr->JobId == 0) {
-        len = Mmsg(msg, _("Director connected at: %s\n"), dt);
+         len = Mmsg(msg, _("Director connected at: %s\n"), dt);
       } else {
-        len = Mmsg(msg, _("JobId %d Job %s is running.\n"),
-                   njcr->JobId, njcr->Job);
-        sendit(msg, len, arg);
-        len = Mmsg(msg, _("    %s Job started: %s\n"),
-                   job_type_to_str(njcr->JobType), dt);
+         len = Mmsg(msg, _("JobId %d Job %s is running.\n"),
+                    njcr->JobId, njcr->Job);
+         sendit(msg, len, arg);
+         len = Mmsg(msg, _("    %s Job started: %s\n"),
+                    job_type_to_str(njcr->JobType), dt);
       }
       sendit(msg, len, arg);
       if (njcr->JobId == 0) {
-        free_locked_jcr(njcr);
-        continue;
+         free_jcr(njcr);
+         continue;
       }
       sec = time(NULL) - njcr->start_time;
       if (sec <= 0) {
-        sec = 1;
+         sec = 1;
       }
       bps = (int)(njcr->JobBytes / sec);
       len = Mmsg(msg,  _("    Files=%s Bytes=%s Bytes/sec=%s\n"),
-          edit_uint64_with_commas(njcr->JobFiles, b1),
-          edit_uint64_with_commas(njcr->JobBytes, b2),
-          edit_uint64_with_commas(bps, b3));
+           edit_uint64_with_commas(njcr->JobFiles, b1),
+           edit_uint64_with_commas(njcr->JobBytes, b2),
+           edit_uint64_with_commas(bps, b3));
       sendit(msg, len, arg);
       len = Mmsg(msg, _("    Files Examined=%s\n"),
-          edit_uint64_with_commas(njcr->num_files_examined, b1));
+           edit_uint64_with_commas(njcr->num_files_examined, b1));
       sendit(msg, len, arg);
       if (njcr->JobFiles > 0) {
-        P(njcr->mutex);
-        len = Mmsg(msg, _("    Processing file: %s\n"), njcr->last_fname);
-        V(njcr->mutex);
-        sendit(msg, len, arg);
+         P(njcr->mutex);
+         len = Mmsg(msg, _("    Processing file: %s\n"), njcr->last_fname);
+         V(njcr->mutex);
+         sendit(msg, len, arg);
       }
 
       found = 1;
       if (njcr->store_bsock) {
-        len = Mmsg(msg, "    SDReadSeqNo=%" lld " fd=%d\n",
-            njcr->store_bsock->read_seqno, njcr->store_bsock->fd);
-        sendit(msg, len, arg);
+         len = Mmsg(msg, "    SDReadSeqNo=%" lld " fd=%d\n",
+             njcr->store_bsock->read_seqno, njcr->store_bsock->fd);
+         sendit(msg, len, arg);
       } else {
-        len = Mmsg(msg, _("    SDSocket closed.\n"));
-        sendit(msg, len, arg);
+         len = Mmsg(msg, _("    SDSocket closed.\n"));
+         sendit(msg, len, arg);
       }
-      free_locked_jcr(njcr);
+      free_jcr(njcr);
    }
-   unlock_jcr_chain();
    Dmsg0(1000, "Begin status jcr loop.\n");
    if (!found) {
       len = Mmsg(msg, _("No Jobs running.\n"));
@@ -228,49 +226,49 @@ static void  list_terminated_jobs(void sendit(const char *msg, int len, void *sa
       switch (je->JobType) {
       case JT_ADMIN:
       case JT_RESTORE:
-        bstrncpy(level, "    ", sizeof(level));
-        break;
+         bstrncpy(level, "    ", sizeof(level));
+         break;
       default:
-        bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
-        level[4] = 0;
-        break;
+         bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
+         level[4] = 0;
+         break;
       }
       switch (je->JobStatus) {
       case JS_Created:
-        termstat = "Created";
-        break;
+         termstat = "Created";
+         break;
       case JS_FatalError:
       case JS_ErrorTerminated:
-        termstat = "Error";
-        break;
+         termstat = "Error";
+         break;
       case JS_Differences:
-        termstat = "Diffs";
-        break;
+         termstat = "Diffs";
+         break;
       case JS_Canceled:
-        termstat = "Cancel";
-        break;
+         termstat = "Cancel";
+         break;
       case JS_Terminated:
-        termstat = "OK";
-        break;
+         termstat = "OK";
+         break;
       default:
-        termstat = "Other";
-        break;
+         termstat = "Other";
+         break;
       }
       bstrncpy(JobName, je->Job, sizeof(JobName));
       /* There are three periods after the Job name */
       char *p;
       for (int i=0; i<3; i++) {
-        if ((p=strrchr(JobName, '.')) != NULL) {
-           *p = 0;
-        }
+         if ((p=strrchr(JobName, '.')) != NULL) {
+            *p = 0;
+         }
       }
       bsnprintf(buf, sizeof(buf), _("%6d  %-6s %8s %14s %-7s  %-8s %s\n"),
-        je->JobId,
-        level,
-        edit_uint64_with_commas(je->JobFiles, b1),
-        edit_uint64_with_commas(je->JobBytes, b2),
-        termstat,
-        dt, JobName);
+         je->JobId,
+         level,
+         edit_uint64_with_commas(je->JobFiles, b1),
+         edit_uint64_with_commas(je->JobBytes, b2),
+         termstat,
+         dt, JobName);
       sendit(buf, strlen(buf), arg);
    }
    sendit("====\n", 5, arg);
@@ -329,20 +327,18 @@ int qstatus_cmd(JCR *jcr)
 
    if (strcmp(time, "current") == 0) {
       bnet_fsend(dir, OKqstatus, time);
-      lock_jcr_chain();
       foreach_jcr(njcr) {
-        if (njcr->JobId != 0) {
-           bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
-        }
-        free_locked_jcr(njcr);
+         if (njcr->JobId != 0) {
+            bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
+         }
+         free_jcr(njcr);
       }
-      unlock_jcr_chain();
    }
    else if (strcmp(time, "last") == 0) {
       bnet_fsend(dir, OKqstatus, time);
       if ((last_jobs) && (last_jobs->size() > 0)) {
-        job = (s_last_job*)last_jobs->last();
-        bnet_fsend(dir, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
+         job = (s_last_job*)last_jobs->last();
+         bnet_fsend(dir, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
       }
    }
    else {
@@ -426,7 +422,7 @@ static void win32_sendit(const char *msg, int len, void *marg)
 
    if (len > 0 && msg[len-1] == '\n') {
        // when compiling with visual studio some strings are read-only
-       // and cause access violations. So we creat a tmp copy.
+       // and cause access violations.  So we creat a tmp copy.
        char *_msg = (char *)alloca(len);
        bstrncpy(_msg, msg, len);
        msg = _msg;
@@ -453,23 +449,21 @@ char *bac_status(char *buf, int buf_len)
    JCR *njcr;
    const char *termstat = _("Bacula Idle");
    struct s_last_job *job;
-   int stat = 0;                     /* Idle */
+   int stat = 0;                      /* Idle */
 
    if (!last_jobs) {
       goto done;
    }
    Dmsg0(1000, "Begin bac_status jcr loop.\n");
-   lock_jcr_chain();
    foreach_jcr(njcr) {
       if (njcr->JobId != 0) {
-        stat = JS_Running;
-        termstat = _("Bacula Running");
-        free_locked_jcr(njcr);
-        break;
+         stat = JS_Running;
+         termstat = _("Bacula Running");
+         free_jcr(njcr);
+         break;
       }
-      free_locked_jcr(njcr);
+      free_jcr(njcr);
    }
-   unlock_jcr_chain();
    if (stat != 0) {
       goto done;
    }
@@ -478,17 +472,17 @@ char *bac_status(char *buf, int buf_len)
       stat = job->JobStatus;
       switch (job->JobStatus) {
       case JS_Canceled:
-        termstat = _("Last Job Canceled");
-        break;
+         termstat = _("Last Job Canceled");
+         break;
       case JS_ErrorTerminated:
       case JS_FatalError:
-        termstat = _("Last Job Failed");
-        break;
+         termstat = _("Last Job Failed");
+         break;
       default:
-        if (job->Errors) {
-           termstat = _("Last Job had Warnings");
-        }
-        break;
+         if (job->Errors) {
+            termstat = _("Last Job had Warnings");
+         }
+         break;
       }
    }
    Dmsg0(1000, "End bac_status jcr loop.\n");
index 9fc06e81d56d0175ecd6932b28f0d9733d170019..ba7fd9cea4f20b033c082e25c2aba747c4666f4d 100644 (file)
 #define SD_READ   0
 
 /* Forward referenced structures */
-struct JCR;
+class JCR;
 struct FF_PKT;
 
 typedef void (JCR_free_HANDLER)(JCR *jcr);
 
 /* Job Control Record (JCR) */
-struct JCR {
+class JCR {
+public:
+   void inc_use_count(void) {P(mutex); use_count++; V(mutex); };
+   void dec_use_count(void) {P(mutex); use_count--; V(mutex); };
+
    /* Global part of JCR common to all daemons */
-   JCR *next;
-   JCR *prev;
+   dlink link;                        /* JCR chain link */
    volatile int use_count;            /* use count */
    pthread_t my_thread_id;            /* id of thread controlling jcr */
    pthread_mutex_t mutex;             /* jcr mutex */
@@ -306,7 +309,6 @@ extern dlist *last_jobs;
 /* The following routines are found in lib/jcr.c */
 extern bool init_jcr_subsystem(void);
 extern JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr);
-extern void free_locked_jcr(JCR *jcr);
 extern JCR *get_jcr_by_id(uint32_t JobId);
 extern JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime);
 extern JCR *get_jcr_by_partial_name(char *Job);
index 09eccfbb68b0d683e696f32f45bede899c563d0b..7dd1b175620cea54ad79d99b472f04c3c5afbd50 100644 (file)
@@ -2,7 +2,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2003-2005 Kern Sibbald
+   Copyright (C) 2004-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -41,7 +41,7 @@
 
 #ifdef the_old_way
 #define foreach_dlist(var, list) \
-       for((var)=NULL; (((void *)(var))=(list)->next(var)); )
+        for((var)=NULL; (((void *)(var))=(list)->next(var)); )
 #endif
 
 
@@ -68,7 +68,7 @@ public:
    void binary_insert(void *item, int compare(void *item1, void *item2));
    void remove(void *item);
    bool empty() const;
-   int size() const;
+   int  size() const;
    void *next(const void *item) const;
    void *prev(const void *item) const;
    void destroy();
index 91ad72db915775a19b413ca158ec189ea8ded0aa..964d5c3e2759c04060882b8e7b201568a7168d2f 100755 (executable)
@@ -1,5 +1,6 @@
 /*
- * Manipulation routines for Job Control Records
+ * Manipulation routines for Job Control Records and
+ *  handling of last_jobs_list.
  *
  *  Kern E. Sibbald, December 2000
  *
@@ -7,24 +8,32 @@
  *
  *  These routines are thread safe.
  *
+ *  The job list routines were re-written in May 2005 to
+ *  eliminate the global lock while traversing the list, and
+ *  to use the dlist subroutines.  The locking is now done
+ *  on the list each time the list is modified or traversed.
+ *  That is it is "micro-locked" rather than globally locked.
+ *  The result is that there is one lock/unlock for each entry
+ *  in the list while traversing it rather than a single lock
+ *  at the beginning of a traversal and one at the end.  This
+ *  incurs slightly more overhead, but effectively eliminates 
+ *  the possibilty of race conditions.  In addition, with the
+ *  exception of the global locking of the list during the
+ *  re-reading of the config file, no recursion is needed.
+ *
  */
 /*
    Copyright (C) 2000-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+   modify it under the terms of the GNU General Public License
+   version 2 as ammended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
@@ -42,13 +51,14 @@ static void jcr_timeout_check(watchdog_t *self);
 int num_jobs_run;
 dlist *last_jobs = NULL;
 const int max_last_jobs = 10;
-
-JCR *jobs = NULL;                     /* pointer to JCR chain */
+static dlist *jcrs = NULL;            /* JCR chain */
 static brwlock_t lock;                /* lock for last jobs and JCR chain */
 
 void init_last_jobs_list()
 {
    int errstat;
+   JCR *jcr;
    struct s_last_job *job_entry = NULL;
    if (!last_jobs) {
       last_jobs = New(dlist(job_entry, &job_entry->link));
@@ -57,7 +67,9 @@ void init_last_jobs_list()
                strerror(errstat));
       }
    }
-
+   if (!jcrs) {
+      jcrs = New(dlist(jcr, &jcr->link));
+   }
 }
 
 void term_last_jobs_list()
@@ -71,6 +83,7 @@ void term_last_jobs_list()
       delete last_jobs;
       last_jobs = NULL;
       rwl_destroy(&lock);
+      delete jcrs;
    }
 }
 
@@ -216,13 +229,12 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
    sigaction(TIMEOUT_SIGNAL, &sigtimer, NULL);
 
    lock_jcr_chain();
-   jcr->prev = NULL;
-   jcr->next = jobs;
-   if (jobs) {
-      jobs->prev = jcr;
+   if (!jcrs) {
+      jcrs = New(dlist(jcr, &jcr->link));
    }
-   jobs = jcr;
+   jcrs->append(jcr);
    unlock_jcr_chain();
+
    return jcr;
 }
 
@@ -238,14 +250,7 @@ static void remove_jcr(JCR *jcr)
    if (!jcr) {
       Emsg0(M_ABORT, 0, "NULL jcr.\n");
    }
-   if (!jcr->prev) {                  /* if no prev */
-      jobs = jcr->next;               /* set new head */
-   } else {
-      jcr->prev->next = jcr->next;    /* update prev */
-   }
-   if (jcr->next) {
-      jcr->next->prev = jcr->prev;
-   }
+   jcrs->remove(jcr);
    Dmsg0(3400, "Leave remove_jcr\n");
 }
 
@@ -360,7 +365,7 @@ void free_jcr(JCR *jcr)
 
    dequeue_messages(jcr);
    lock_jcr_chain();
-   jcr->use_count--;                  /* decrement use count */
+   jcr->dec_use_count();              /* decrement use count */
    if (jcr->use_count < 0) {
       Emsg2(M_ERROR, 0, _("JCR use_count=%d JobId=%d\n"),
          jcr->use_count, jcr->JobId);
@@ -387,24 +392,6 @@ void free_jcr(JCR *jcr)
 }
 
 
-/*
- * Global routine to free a jcr
- *  JCR chain is already locked
- */
-void free_locked_jcr(JCR *jcr)
-{
-   jcr->use_count--;                  /* decrement use count */
-   Dmsg2(3400, "Dec free_locked_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
-   if (jcr->use_count > 0) {          /* if in use */
-      return;
-   }
-   remove_jcr(jcr);
-   jcr->daemon_free_jcr(jcr);         /* call daemon free routine */
-   free_common_jcr(jcr);
-}
-
-
-
 /*
  * Given a JobId, find the JCR
  *   Returns: jcr on success
@@ -415,11 +402,9 @@ JCR *get_jcr_by_id(uint32_t JobId)
    JCR *jcr;
 
    lock_jcr_chain();                    /* lock chain */
-   for (jcr = jobs; jcr; jcr=jcr->next) {
+   foreach_dlist(jcr, jcrs) {
       if (jcr->JobId == JobId) {
-         P(jcr->mutex);
-         jcr->use_count++;
-         V(jcr->mutex);
+         jcr->inc_use_count();
          Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
          break;
       }
@@ -438,12 +423,10 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
    JCR *jcr;
 
    lock_jcr_chain();
-   for (jcr = jobs; jcr; jcr=jcr->next) {
+   foreach_dlist(jcr, jcrs) {
       if (jcr->VolSessionId == SessionId &&
           jcr->VolSessionTime == SessionTime) {
-         P(jcr->mutex);
-         jcr->use_count++;
-         V(jcr->mutex);
+         jcr->inc_use_count();
          Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
          break;
       }
@@ -470,11 +453,9 @@ JCR *get_jcr_by_partial_name(char *Job)
    }
    lock_jcr_chain();
    len = strlen(Job);
-   for (jcr = jobs; jcr; jcr=jcr->next) {
+   foreach_dlist(jcr, jcrs) {
       if (strncmp(Job, jcr->Job, len) == 0) {
-         P(jcr->mutex);
-         jcr->use_count++;
-         V(jcr->mutex);
+         jcr->inc_use_count();
          Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
          break;
       }
@@ -498,11 +479,9 @@ JCR *get_jcr_by_full_name(char *Job)
       return NULL;
    }
    lock_jcr_chain();
-   for (jcr = jobs; jcr; jcr=jcr->next) {
+   foreach_dlist(jcr, jcrs) {
       if (strcmp(jcr->Job, Job) == 0) {
-         P(jcr->mutex);
-         jcr->use_count++;
-         V(jcr->mutex);
+         jcr->inc_use_count();
          Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
          break;
       }
@@ -578,17 +557,13 @@ JCR *get_next_jcr(JCR *prev_jcr)
 {
    JCR *jcr;
 
-   if (prev_jcr == NULL) {
-      jcr = jobs;
-   } else {
-      jcr = prev_jcr->next;
-   }
+   lock_jcr_chain();
+   jcr = (JCR *)jcrs->next(prev_jcr);
    if (jcr) {
-      P(jcr->mutex);
-      jcr->use_count++;
-      V(jcr->mutex);
+      jcr->inc_use_count();
       Dmsg2(3400, "Inc get_next_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
    }
+   unlock_jcr_chain();
    return jcr;
 }
 
@@ -617,10 +592,9 @@ static void jcr_timeout_check(watchdog_t *self)
    /* Walk through all JCRs checking if any one is
     * blocked for more than specified max time.
     */
-   lock_jcr_chain();
    foreach_jcr(jcr) {
-      free_locked_jcr(jcr);           /* OK to free now cuz chain is locked */
       if (jcr->JobId == 0) {
+         free_jcr(jcr);
          continue;
       }
       fd = jcr->store_bsock;
@@ -659,9 +633,8 @@ static void jcr_timeout_check(watchdog_t *self)
             pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
          }
       }
-
+      free_jcr(jcr);
    }
-   unlock_jcr_chain();
 
    Dmsg0(3400, "Finished JCR timeout checks\n");
 }
index d6c65dd6d70200fbffcc7df6e2605993904190c6..985856dc3953e20fd5518989e01777c928ea856d 100755 (executable)
@@ -30,7 +30,7 @@
 #include "jcr.h"
 
 /* Exported globals */
-time_t watchdog_time = 0;            /* this has granularity of SLEEP_TIME */
+time_t watchdog_time = 0;             /* this has granularity of SLEEP_TIME */
 time_t watchdog_sleep_time = 60;      /* examine things every 60 seconds */
 
 /* Locals */
@@ -46,7 +46,7 @@ static void wd_unlock();
 /* Static globals */
 static bool quit = false;;
 static bool wd_is_init = false;
-static brwlock_t lock;               /* watchdog lock */
+static brwlock_t lock;                /* watchdog lock */
 
 static pthread_t wd_tid;
 static dlist *wd_queue;
@@ -56,7 +56,7 @@ static dlist *wd_inactive;
  * Start watchdog thread
  *
  *  Returns: 0 on success
- *          errno on failure
+ *           errno on failure
  */
 int start_watchdog(void)
 {
@@ -72,7 +72,7 @@ int start_watchdog(void)
 
    if ((errstat=rwl_init(&lock)) != 0) {
       Emsg1(M_ABORT, 0, _("Unable to initialize watchdog lock. ERR=%s\n"),
-           strerror(errstat));
+            strerror(errstat));
    }
    wd_queue = New(dlist(dummy, &dummy->link));
    wd_inactive = New(dlist(dummy, &dummy->link));
@@ -99,7 +99,7 @@ static void ping_watchdog()
  * Terminate the watchdog thread
  *
  * Returns: 0 on success
- *         errno on failure
+ *          errno on failure
  */
 int stop_watchdog(void)
 {
@@ -110,7 +110,7 @@ int stop_watchdog(void)
       return 0;
    }
 
-   quit = true;                      /* notify watchdog thread to stop */
+   quit = true;                       /* notify watchdog thread to stop */
    wd_is_init = false;
 
    ping_watchdog();
@@ -121,7 +121,7 @@ int stop_watchdog(void)
       wd_queue->remove(item);
       p = (watchdog_t *)item;
       if (p->destructor != NULL) {
-        p->destructor(p);
+         p->destructor(p);
       }
       free(p);
    }
@@ -133,7 +133,7 @@ int stop_watchdog(void)
       wd_inactive->remove(item);
       p = (watchdog_t *)item;
       if (p->destructor != NULL) {
-        p->destructor(p);
+         p->destructor(p);
       }
       free(p);
    }
@@ -199,19 +199,19 @@ bool unregister_watchdog(watchdog_t *wd)
    wd_lock();
    foreach_dlist(p, wd_queue) {
       if (wd == p) {
-        wd_queue->remove(wd);
+         wd_queue->remove(wd);
          Dmsg1(800, "Unregistered watchdog %p\n", wd);
-        ok = true;
-        goto get_out;
+         ok = true;
+         goto get_out;
       }
    }
 
    foreach_dlist(p, wd_inactive) {
       if (wd == p) {
-        wd_inactive->remove(wd);
+         wd_inactive->remove(wd);
          Dmsg1(800, "Unregistered inactive watchdog %p\n", wd);
-        ok = true;
-        goto get_out;
+         ok = true;
+         goto get_out;
       }
    }
 
@@ -242,6 +242,10 @@ extern "C" void *watchdog_thread(void *arg)
       watchdog_t *p;
 
       /*
+       *
+       *  NOTE. lock_jcr_chain removed, but the message below
+       *   was left until we are sure there are no deadlocks.
+       *  
        * We lock the jcr chain here because a good number of the
        *   callback routines lock the jcr chain. We need to lock
        *   it here *before* the watchdog lock because the SD message
@@ -250,32 +254,30 @@ extern "C" void *watchdog_thread(void *arg)
        *   lock in the same order, we get a deadlock -- each holds
        *   the other's needed lock.
        */
-      lock_jcr_chain();
       wd_lock();
 
 walk_list:
       watchdog_time = time(NULL);
       next_time = watchdog_time + watchdog_sleep_time;
       foreach_dlist(p, wd_queue) {
-        if (p->next_fire <= watchdog_time) {
-           /* Run the callback */
-           p->callback(p);
+         if (p->next_fire <= watchdog_time) {
+            /* Run the callback */
+            p->callback(p);
 
             /* Reschedule (or move to inactive list if it's a one-shot timer) */
-           if (p->one_shot) {
-              wd_queue->remove(p);
-              wd_inactive->append(p);
-              goto walk_list;
-           } else {
-              p->next_fire = watchdog_time + p->interval;
-           }
-        }
-        if (p->next_fire < next_time) {
-           next_time = p->next_fire;
-        }
+            if (p->one_shot) {
+               wd_queue->remove(p);
+               wd_inactive->append(p);
+               goto walk_list;
+            } else {
+               p->next_fire = watchdog_time + p->interval;
+            }
+         }
+         if (p->next_fire < next_time) {
+            next_time = p->next_fire;
+         }
       }
       wd_unlock();
-      unlock_jcr_chain();
 
       /*
        * Wait sleep time or until someone wakes us
@@ -284,8 +286,8 @@ walk_list:
       timeout.tv_nsec = tv.tv_usec * 1000;
       timeout.tv_sec = tv.tv_sec + next_time - time(NULL);
       while (timeout.tv_nsec >= 1000000000) {
-        timeout.tv_nsec -= 1000000000;
-        timeout.tv_sec++;
+         timeout.tv_nsec -= 1000000000;
+         timeout.tv_sec++;
       }
 
       Dmsg1(1900, "pthread_cond_timedwait %d\n", timeout.tv_sec - tv.tv_sec);
@@ -309,7 +311,7 @@ static void wd_lock()
    int errstat;
    if ((errstat=rwl_writelock(&lock)) != 0) {
       Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
-          strerror(errstat));
+           strerror(errstat));
    }
 }
 
@@ -323,6 +325,6 @@ static void wd_unlock()
    int errstat;
    if ((errstat=rwl_writeunlock(&lock)) != 0) {
       Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
-          strerror(errstat));
+           strerror(errstat));
    }
 }
index 0fb5fcfa16b684b3e42282e1dd66942ba4157c07..d449634709a204d3fd09181954d48f882b282061 100644 (file)
@@ -255,22 +255,20 @@ bool dir_find_next_appendable_volume(DCR *dcr)
            * This would be better done by walking through
            *  all the devices.
            */
-          lock_jcr_chain();
           foreach_jcr(njcr) {
              if (jcr == njcr) {
-                free_locked_jcr(njcr);
+                free_jcr(njcr);
                 continue;             /* us */
              }
              Dmsg2(300, "Compare to JobId=%d using Vol=%s\n", njcr->JobId, njcr->dcr->VolumeName);
              if (njcr->dcr && strcmp(dcr->VolumeName, njcr->dcr->VolumeName) == 0) {
                 found = true;
                 Dmsg1(400, "Vol in use by JobId=%u\n", njcr->JobId);
-                free_locked_jcr(njcr);
+                free_jcr(njcr);
                 break;
              }
-             free_locked_jcr(njcr);
+             free_jcr(njcr);
           }
-          unlock_jcr_chain();
           if (!found) {
              Dmsg0(400, "dir_find_next_appendable_volume return true\n");
              return true;             /* Got good Volume */
index dc18ca4290d300f9f8be97aae093cee472dd026f..0e281357ac400191ff361b25e4e36137362a857e 100644 (file)
@@ -252,7 +252,6 @@ static void list_running_jobs(BSOCK *user)
    char b1[30], b2[30], b3[30];
 
    bnet_fsend(user, _("\nRunning Jobs:\n"));
-   lock_jcr_chain();
    foreach_jcr(jcr) {
       if (jcr->JobStatus == JS_WaitFD) {
          bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"),
@@ -295,9 +294,8 @@ static void list_running_jobs(BSOCK *user)
          }
 #endif
       }
-      free_locked_jcr(jcr);
+      free_jcr(jcr);
    }
-   unlock_jcr_chain();
    if (!found) {
       bnet_fsend(user, _("No Jobs running.\n"));
    }
@@ -461,14 +459,12 @@ bool qstatus_cmd(JCR *jcr)
 
    if (strcmp(time.c_str(), "current") == 0) {
       bnet_fsend(dir, OKqstatus, time.c_str());
-      lock_jcr_chain();
       foreach_jcr(njcr) {
          if (njcr->JobId != 0) {
             bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
          }
-         free_locked_jcr(njcr);
+         free_jcr(njcr);
       }
-      unlock_jcr_chain();
    }
    else if (strcmp(time.c_str(), "last") == 0) {
       bnet_fsend(dir, OKqstatus, time.c_str());
index 50bb025aa1f762de3616665f57474e49c43870e3..8b8a76f7ccee850cb5bd5e3a303f379e870a0ca1 100644 (file)
@@ -515,11 +515,10 @@ void terminate_stored(int sig)
        *   them up so that they will report back the correct
        *   volume status.
        */
-      lock_jcr_chain();
       foreach_jcr(jcr) {
          BSOCK *fd;
-         free_locked_jcr(jcr);
          if (jcr->JobId == 0) {
+            free_jcr(jcr);
             continue;                 /* ignore console */
          }
          set_jcr_job_status(jcr, JS_Canceled);
@@ -534,9 +533,9 @@ void terminate_stored(int sig)
                pthread_cond_broadcast(&wait_device_release);
             }
             bmicrosleep(0, 50000);
-          }
+         }
+         free_jcr(jcr);
       }
-      unlock_jcr_chain();
       bmicrosleep(0, 500000);         /* give them 1/2 sec to clean up */
    }
 
@@ -545,13 +544,11 @@ void terminate_stored(int sig)
 
    Dmsg1(200, "In terminate_stored() sig=%d\n", sig);
 
-// LockRes();
    foreach_res(device, R_DEVICE) {
       if (device->dev) {
          term_dev(device->dev);
       }
    }
-// UnlockRes();
 
    if (configfile)
    free(configfile);
index 5621dae6b1f334bb143f46f366c7a4ffe3178e18..53a34e9cf117242b8457956ce3ee353812e96a3c 100644 (file)
@@ -1,6 +1,6 @@
 /* */
 #undef  VERSION
-#define VERSION "1.37.19"
+#define VERSION "1.37.20"
 #define BDATE   "26 May 2005"
 #define LSMDATE "26May05"