Example #1
0
static void
run_expiry()
{
    DBC *dbcp;
    int rc;
    time_t now;
    unsigned int count = 0;
    /* Cursor operations can hold several locks and therefore deadlock
       so don't run expiry if deadlock detection does not work
       http://www.oracle.com/technology/documentation/berkeley-db/db/ref/lock/notxn.html */
    if (db == 0 || deadlock_detect == 0)
        return;
    if (time(&now) == (time_t)-1) {
        syslog(LOG_ERR, "time failed during run_expiry");
        return;
    }
    muffle_error++;
    if (rc = db->cursor(db, 0, &dbcp, 0))
        log_db_error("db->cursor failed during expiry run", rc);
    else {
        DBT key = { 0 };
        while ((rc = dbcp->c_get(dbcp, &key, &dbdata, DB_NEXT | DB_RMW)) == 0) {
            time_t ref_time;
            double age_max, age;
            if (triplet_data.pass_count) {
                ref_time = triplet_data.access_time;
                age_max = pass_max_idle;
            }
            else {
                ref_time = triplet_data.create_time;
                age_max = bloc_max_idle;
            }
            age = difftime(now, ref_time);
            if (age > age_max) {
                if (opt_verbose)
                    syslog(LOG_INFO, "Expiring %s %s after %.0f seconds idle",
                           key.data,
                           triplet_data.pass_count ? "pass" : "block", age);
                if (rc = dbcp->c_del(dbcp, 0))
                    log_db_error("dbcp->c_del failed", rc);
                else
                    count++;
            }
        }
        if (rc == DB_LOCK_DEADLOCK)
            syslog(LOG_DEBUG, "skipping concurrent expiry avoids "
                   "deadlocks and unnecessary work");
        else if (rc != DB_NOTFOUND)
            log_db_error("dbcp->c_get failed", rc);
        if (rc = dbcp->c_close(dbcp))
            log_db_error("dbcp->c_close failed", rc);
    }
    muffle_error--;
    if (count)
        syslog(LOG_NOTICE, "Expired %u triplets", count);
}
Example #2
0
static void
get_grey_data(DB *db, DB_TXN *txn)
{
    int rc;
    rc = db->get(db, txn, &dbkey, &dbdata, 0);
    if (rc == DB_NOTFOUND) {
	touch_data();
	build_data();
    }
    else if (rc) {
	log_db_error("get failed", rc);
	jmperr("get failed");
    }
    else {
	time_t ref_time;
	double age_max;
	if (triplet_data.pass_count) {
	    ref_time = triplet_data.access_time;
	    age_max = pass_max_idle;
	}
	else {
	    ref_time = triplet_data.create_time;
	    age_max = bloc_max_idle;
	}
	touch_data();
	/* Expire IDLE records */
	if (difftime(triplet_data.access_time, ref_time) > age_max)
	    build_data();
    }
}
Example #3
0
static int
call_db(int err, const char *msg)
{
    if (err)
	log_db_error(msg, err);
    return err;
}
Example #4
0
static int
prepare_db()
{
    int rc;
    rc = db_create(&db, dbenv, 0);
    if (rc)
        log_db_error("db_create", rc);
    else {
        rc = db_open(db, DB_FILE_NAME, NULL, DB_BTREE, DB_CREATE, 0644);
        if (rc) {
            log_db_error("db->open", rc);
            db->close(db, 0);
            db = 0;
        }
    }
    return rc;
}
Example #5
0
static int
put_grey_data()
{
    int rc;
    rc = db->put(db, NULL, &dbkey, &dbdata, 0);
    if (rc)
        log_db_error("put", rc);
    return rc;
}
Example #6
0
static void
cleanup()
{
    int rc;
    if (dbkey.data)
        free(dbkey.data);
    if (db) {
        rc = db->close(db, 0);
        if (rc)
            log_db_error("DB close", rc);
    }
    rc = db_create(&db, dbenv, 0);
    if (!rc)
        if (! db->remove(db, "tls_stats.db", 0, 0))
            syslog(LOG_NOTICE, "Unused database tls_stats.db removed");
    db = 0;
    if (dbenv) {
        rc = dbenv->close(dbenv, 0);
        dbenv = 0;
        if (rc)
            log_db_error("DB_ENV close", rc);
    }
    policy_cleanup();
}
Example #7
0
static int
prepare_env()
{
    int rc;
    rc = db_env_create(&dbenv, 0);
    if (rc)
        log_db_error("db_env_create", rc);
    else {
        dbenv->set_errcall(dbenv, db_errcall_fcn);
        rc = dbenv->set_lk_detect(dbenv, DB_LOCK_YOUNGEST);
        if (rc)
            log_db_error("dbenv->set_lk_detect DB_LOCK_YOUNGEST, expired triplets will not be deleted", rc);
        else
            deadlock_detect = 1;
        rc = dbenv->open(dbenv, db_home,
                         DB_INIT_LOCK | DB_INIT_MPOOL | DB_CREATE, 0);
        if (rc) {
            log_db_error("dbenv->open", rc);
            dbenv->close(dbenv, 0);
            dbenv = 0;
        }
    }
    return rc;
}
Example #8
0
static void
run_expiry()
{
    DB_ENV *dbenv;
    DB *db;
    DB_TXN *txn;
    DBC *dbcp;
    int rc;
    time_t now;
    DBT key = { 0 };
    unsigned int count = 0;
    if (exit_requested)
	return;
    /* Cursor operations can hold several locks and therefore deadlock
       so don't run expiry if deadlock detection does not work
       http://docs.oracle.com/cd/E17076_02/html/programmer_reference/lock_notxn.html */
    rc = get_db(&db, 0);
    assert(! rc);
    if (db == 0 || deadlock_detect == 0)
	return;
    rc = get_dbenv(&dbenv, 0);
    assert(! rc && dbenv);
    if (time(&now) == (time_t)-1) {
	syslog(LOG_ERR, "time failed during run_expiry");
	return;
    }
    muffle_error++;
    rc = dbenv->txn_begin(dbenv, NULL, &txn, DB_TXN_NOWAIT);
    if (rc) {
	if (rc == DB_LOCK_DEADLOCK)
	    syslog(LOG_DEBUG, "skipping concurrent expiry avoids "
		   "deadlocks and unnecessary work");
	else
	    log_db_error("txn_begin failed during run_expiry", rc);
	goto out;
    }
#if DB_VERSION_MAJOR >= 5
    call_db(txn->set_priority(txn, 50), "TXN->set_priority");
#endif
    rc = call_db(db->cursor(db, txn, &dbcp, 0),
		 "db->cursor failed during expiry run");
    if (rc)
	goto txn_fail;
    while ((rc = dbcp->c_get(dbcp, &key, &dbdata, DB_NEXT | DB_RMW)) == 0) {
	time_t ref_time;
	double age_max, age;
	if (triplet_data.pass_count) {
	    ref_time = triplet_data.access_time;
	    age_max = pass_max_idle;
	}
	else {
	    ref_time = triplet_data.create_time;
	    age_max = bloc_max_idle;
	}
	age = difftime(now, ref_time);
	if (age > age_max) {
	    if (opt_verbose) {
		syslog(LOG_INFO, "Expiring %s %s after %.0f seconds idle",
		       db_key_ntop(key.data),
		       triplet_data.pass_count ? "pass" : "block", age);
	    }
	    rc = call_db(dbcp->c_del(dbcp, 0), "dbcp->c_del failed");
	    if (rc)
		goto cursor_fail;
	    count++;
	}
	if (exit_requested)
	    break;
    }
    if (rc && rc != DB_NOTFOUND) {
	if (rc == DB_LOCK_DEADLOCK)
	    syslog(LOG_NOTICE, "Aborting concurrent expiry due to deadlock");
	else
	    log_db_error("dbcp->c_get failed", rc);
	goto cursor_fail;
    }
    if (call_db(dbcp->c_close(dbcp), "dbcp->c_close failed"))
	goto txn_fail;
    call_db(txn->commit(txn, 0), "commit failed in run_expiry");
    if (count)
	syslog(LOG_NOTICE, "Expired %u triplets", count);
    goto out;

  cursor_fail:
    call_db(dbcp->c_close(dbcp), "dbcp->c_close failed");
  txn_fail:
    call_db(txn->abort(txn), "failed to abort");
  out:
    muffle_error--;
    return;
}