void test_iter_modify_entry(void **state) { /* Test that deleting entry under cursor does not interrupt iteration */ CF_DB *db; assert_int_equal(OpenDB(&db, dbid_classes), true); assert_int_equal(WriteDB(db, "foobar", "abc", 3), true); assert_int_equal(WriteDB(db, "bazbaz", "def", 3), true); assert_int_equal(WriteDB(db, "booo", "ghi", 3), true); CF_DBC *cursor; assert_int_equal(NewDBCursor(db, &cursor), true); char *key; int ksize; void *value; int vsize; assert_int_equal(NextDB(db, cursor, &key, &ksize, &value, &vsize), true); assert_int_equal(DBCursorWriteEntry(cursor, "eee", 3), true); assert_int_equal(NextDB(db, cursor, &key, &ksize, &value, &vsize), true); assert_int_equal(NextDB(db, cursor, &key, &ksize, &value, &vsize), true); assert_int_equal(DeleteDBCursor(db, cursor), true); CloseDB(db); }
void NoteClassUsage(AlphaList baselist, int purge) { CF_DB *dbp; CF_DBC *dbcp; void *stored; char *key; int ksize, vsize; Event e, entry, newe; double lsea = SECONDS_PER_WEEK * 52; /* expire after (about) a year */ time_t now = time(NULL); Item *list = NULL; const Item *ip; double lastseen; double vtrue = 1.0; /* end with a rough probability */ /* Only do this for the default policy, too much "downgrading" otherwise */ if (MINUSF) { return; } AlphaListIterator it = AlphaListIteratorInit(&baselist); for (ip = AlphaListIteratorNext(&it); ip != NULL; ip = AlphaListIteratorNext(&it)) { if ((IGNORECLASS(ip->name))) { CfDebug("Ignoring class %s (not packing)", ip->name); continue; } IdempPrependItem(&list, ip->name, NULL); } if (!OpenDB(&dbp, dbid_classes)) { return; } /* First record the classes that are in use */ for (ip = list; ip != NULL; ip = ip->next) { if (ReadDB(dbp, ip->name, &e, sizeof(e))) { CfDebug("FOUND %s with %lf\n", ip->name, e.Q.expect); lastseen = now - e.t; newe.t = now; newe.Q = QAverage(e.Q, vtrue, 0.7); } else { lastseen = 0.0; newe.t = now; /* With no data it's 50/50 what we can say */ newe.Q = QDefinite(0.5 * vtrue); } if (lastseen > lsea) { CfDebug("Class usage record %s expired\n", ip->name); DeleteDB(dbp, ip->name); } else { WriteDB(dbp, ip->name, &newe, sizeof(newe)); } } /* Then update with zero the ones we know about that are not active */ if (purge) { /* Acquire a cursor for the database and downgrade classes that did not get defined this time*/ if (!NewDBCursor(dbp, &dbcp)) { CfOut(cf_inform, "", " !! Unable to scan class db"); CloseDB(dbp); DeleteItemList(list); return; } memset(&entry, 0, sizeof(entry)); while (NextDB(dbp, dbcp, &key, &ksize, &stored, &vsize)) { time_t then; char eventname[CF_BUFSIZE]; memset(eventname, 0, CF_BUFSIZE); strncpy(eventname, (char *) key, ksize); if (stored != NULL) { memcpy(&entry, stored, sizeof(entry)); then = entry.t; lastseen = now - then; if (lastseen > lsea) { CfDebug("Class usage record %s expired\n", eventname); DBCursorDeleteEntry(dbcp); } else if (!IsItemIn(list, eventname)) { newe.t = then; newe.Q = QAverage(entry.Q, 0, 0.5); if (newe.Q.expect <= 0.0001) { CfDebug("Deleting class %s as %lf is zero\n", eventname, newe.Q.expect); DBCursorDeleteEntry(dbcp); } else { CfDebug("Downgrading class %s from %lf to %lf\n", eventname, entry.Q.expect, newe.Q.expect); DBCursorWriteEntry(dbcp, &newe, sizeof(newe)); } } } } DeleteDBCursor(dbp, dbcp); } CloseDB(dbp); DeleteItemList(list); }
static void PurgeMultipleIPReferences(CF_DB *dbp, char *rkey, char *ipaddress) { CF_DBC *dbcp; KeyHostSeen q; double lastseen, lsea = LASTSEENEXPIREAFTER; void *stored; char *key; time_t now = time(NULL); int qsize, ksize, update_address, keys_match; // This is an expensive call, but it is the price we pay for consistency // Make sure we only call it if we have to if (!NewDBCursor(dbp, &dbcp)) { CfOut(cf_inform, "", " !! Unable to scan the last seen db"); return; } while (NextDB(dbp, dbcp, &key, &ksize, &stored, &qsize)) { keys_match = false; if (strcmp(key + 1, rkey + 1) == 0) { keys_match = true; } memcpy(&q, stored, sizeof(q)); lastseen = (double) now - q.Q.q; if (lastseen > lsea) { CfOut(cf_verbose, "", " -> Last-seen record for %s expired after %.1lf > %.1lf hours\n", key, lastseen / 3600, lsea / 3600); DBCursorDeleteEntry(dbcp); continue; } // Avoid duplicate address/key pairs if (keys_match && strcmp(q.address, ipaddress) != 0) { CfOut(cf_verbose, "", " ! Synchronizing %s's address as this host %s seems to have moved from location %s to %s", key, rkey, q.address, ipaddress); strcpy(q.address, ipaddress); update_address = true; } else if (!keys_match && strcmp(q.address, ipaddress) == 0) { CfOut(cf_verbose, "", " ! Updating %s's address (%s) as this host %s seems to have gone off line", key, ipaddress, rkey); strcpy(q.address, CF_UNKNOWN_IP); update_address = true; } else { update_address = false; } if (update_address) { DBCursorWriteEntry(dbcp, &q, sizeof(q)); } } DeleteDBCursor(dbp, dbcp); }