Changes to 1.37.20:
26May05
+- Use light weight non-recursive locking on jcr chain.
- 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.
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.
+ 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.
*/
init_job_server(director->MaxConcurrentJobs);
-// init_device_resources();
-
Dmsg0(200, "wait for next job\n");
/* Main loop -- call scheduler to get next job to run */
while ((jcr = wait_for_next_job(runjob))) {
int reload_id = (int)((long int)ctx);
Dmsg3(100, "reload job_end JobId=%d table=%d cnt=%d\n", jcr->JobId,
reload_id, reload_table[reload_id].job_count);
- lock_jcr_chain();
+ lock_jobs();
LockRes();
if (--reload_table[reload_id].job_count <= 0) {
free_saved_resources(reload_id);
}
UnlockRes();
- unlock_jcr_chain();
+ unlock_jobs();
}
static int find_free_reload_table_entry()
sigaddset(&set, SIGHUP);
sigprocmask(SIG_BLOCK, &set, NULL);
- lock_jcr_chain();
+ lock_jobs();
LockRes();
table = find_free_reload_table_entry();
bail_out:
UnlockRes();
- unlock_jcr_chain();
+ unlock_jobs();
sigprocmask(SIG_UNBLOCK, &set, NULL);
signal(SIGHUP, reload_config);
already_here = false;
extern JCR *get_next_jcr(JCR *jcr);
extern void set_jcr_job_status(JCR *jcr, int JobStatus);
-#ifdef TRACE_JCR_CHAIN
-extern void b_lock_jcr_chain(const char *filen, int line);
-extern void b_unlock_jcr_chain(const char *filen, int line);
-#define lock_jcr_chain() b_lock_jcr_chain(__FILE__, __LINE__);
-#define unlock_jcr_chain() b_unlock_jcr_chain(__FILE__, __LINE__);
-#else
-extern void lock_jcr_chain();
-extern void unlock_jcr_chain();
-#endif
-
#ifdef DEBUG
extern void b_free_jcr(const char *file, int line, JCR *jcr);
#define free_jcr(jcr) b_free_jcr(__FILE__, __LINE__, (jcr))
/* Forward referenced functions */
extern "C" void timeout_handler(int sig);
-
static void jcr_timeout_check(watchdog_t *self);
+#ifdef TRACE_JCR_CHAIN
+static void b_lock_jcr_chain(const char *filen, int line);
+static void b_unlock_jcr_chain(const char *filen, int line);
+#define lock_jcr_chain() b_lock_jcr_chain(__FILE__, __LINE__);
+#define unlock_jcr_chain() b_unlock_jcr_chain(__FILE__, __LINE__);
+#else
+static void lock_jcr_chain();
+static void unlock_jcr_chain();
+#endif
+
int num_jobs_run;
dlist *last_jobs = NULL;
const int max_last_jobs = 10;
static dlist *jcrs = NULL; /* JCR chain */
-static brwlock_t lock; /* lock for last jobs and JCR chain */
+//static brwlock_t lock; /* lock for last jobs and JCR chain */
+static pthread_mutex_t jcr_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_mutex_t job_start_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void lock_jobs()
+{
+ P(job_start_mutex);
+}
+
+void unlock_jobs()
+{
+ V(job_start_mutex);
+}
void init_last_jobs_list()
{
- int errstat;
+// int errstat;
JCR *jcr;
struct s_last_job *job_entry = NULL;
if (!last_jobs) {
last_jobs = New(dlist(job_entry, &job_entry->link));
- if ((errstat=rwl_init(&lock)) != 0) {
- Emsg1(M_ABORT, 0, _("Unable to initialize jcr_chain lock. ERR=%s\n"),
- strerror(errstat));
- }
+// if ((errstat=rwl_init(&lock)) != 0) {
+// Emsg1(M_ABORT, 0, _("Unable to initialize jcr_chain lock. ERR=%s\n"),
+// strerror(errstat));
+// }
}
if (!jcrs) {
jcrs = New(dlist(jcr, &jcr->link));
}
delete last_jobs;
last_jobs = NULL;
- rwl_destroy(&lock);
+// rwl_destroy(&lock);
delete jcrs;
}
}
sigfillset(&sigtimer.sa_mask);
sigaction(TIMEOUT_SIGNAL, &sigtimer, NULL);
+ /*
+ * Locking jobs is a global lock that is needed
+ * so that the Director can stop new jobs from being
+ * added to the jcr chain while it processes a new
+ * conf file and does the job_end_push().
+ */
+ lock_jobs();
lock_jcr_chain();
if (!jcrs) {
jcrs = New(dlist(jcr, &jcr->link));
}
jcrs->append(jcr);
unlock_jcr_chain();
+ unlock_jobs();
return jcr;
}
* Lock the chain
*/
#ifdef TRACE_JCR_CHAIN
-void b_lock_jcr_chain(const char *fname, int line)
+static void b_lock_jcr_chain(const char *fname, int line)
#else
-void lock_jcr_chain()
+static void lock_jcr_chain()
#endif
{
- int errstat;
+// int errstat;
#ifdef TRACE_JCR_CHAIN
Dmsg3(3400, "Lock jcr chain %d from %s:%d\n", ++lock_count,
fname, line);
#endif
- if ((errstat=rwl_writelock(&lock)) != 0) {
- Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
- strerror(errstat));
- }
+// if ((errstat=rwl_writelock(&lock)) != 0) {
+// Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
+// strerror(errstat));
+// }
+ P(jcr_lock);
}
/*
* Unlock the chain
*/
#ifdef TRACE_JCR_CHAIN
-void b_unlock_jcr_chain(const char *fname, int line)
+static void b_unlock_jcr_chain(const char *fname, int line)
#else
-void unlock_jcr_chain()
+static void unlock_jcr_chain()
#endif
{
- int errstat;
+// int errstat;
#ifdef TRACE_JCR_CHAIN
Dmsg3(3400, "Unlock jcr chain %d from %s:%d\n", lock_count--,
fname, line);
#endif
- if ((errstat=rwl_writeunlock(&lock)) != 0) {
- Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
- strerror(errstat));
- }
+// if ((errstat=rwl_writeunlock(&lock)) != 0) {
+// Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
+// strerror(errstat));
+// }
+ V(jcr_lock);
}
uint64_t write_last_jobs_list(int fd, uint64_t addr);
void write_state_file(char *dir, const char *progname, int port);
void job_end_push(JCR *jcr, void job_end_cb(JCR *jcr,void *), void *ctx);
+void lock_jobs();
+void unlock_jobs();
/* lex.c */
* This file handles locking and seaching resources
*
* Kern Sibbald, January MM
- * Split from parse_conf.c April MMV
+ * Split from parse_conf.c April MMV
*
* 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.
*/
-
#include "bacula.h"
extern int debug_level;
extern "C" CURES res_all;
extern "C" int res_all_size;
#else
-extern CURES res_all;
+extern CURES res_all;
extern int res_all_size;
#endif
-brwlock_t res_lock; /* resource lock */
-static int res_locked = 0; /* set when resource chains locked -- for debug */
-
+brwlock_t res_lock; /* resource lock */
+static int res_locked = 0; /* set when resource chains locked -- for debug */
/* #define TRACE_RES */
int errstat;
#ifdef TRACE_RES
Pmsg4(000, "LockRes locked=%d w_active=%d at %s:%d\n",
- res_locked, res_lock.w_active, file, line);
+ res_locked, res_lock.w_active, file, line);
if (res_locked) {
Pmsg2(000, "LockRes writerid=%d myid=%d\n", res_lock.writer_id,
- pthread_self());
+ pthread_self());
}
#endif
if ((errstat=rwl_writelock(&res_lock)) != 0) {
Emsg3(M_ABORT, 0, "rwl_writelock failure at %s:%d: ERR=%s\n",
- file, line, strerror(errstat));
+ file, line, strerror(errstat));
}
res_locked++;
}
int errstat;
if ((errstat=rwl_writeunlock(&res_lock)) != 0) {
Emsg3(M_ABORT, 0, "rwl_writeunlock failure at %s:%d:. ERR=%s\n",
- file, line, strerror(errstat));
+ file, line, strerror(errstat));
}
res_locked--;
#ifdef TRACE_RES
Pmsg4(000, "UnLockRes locked=%d wactive=%d at %s:%d\n",
- res_locked, res_lock.w_active, file, line);
+ res_locked, res_lock.w_active, file, line);
#endif
}
res = res_head[rindex];
while (res) {
if (strcmp(res->name, name) == 0) {
- break;
+ break;
}
res = res->next;
}
RES *nres;
int rindex = rcode - r_first;
-
-// if (!res_locked) {
-// Emsg0(M_ABORT, 0, "Resource chain not locked.\n");
-// }
if (res == NULL) {
nres = res_head[rindex];
} else {