core/database: Introduce the dbe_free() database operation

The Track tag needs to do some cleanup when removed from a database, so
we need to use this op when removing items.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2015-09-30 09:15:15 -04:00
parent 049156a523
commit c8021639ba
17 changed files with 102 additions and 46 deletions

View File

@ -9,11 +9,6 @@ index_entry :: index_entry()
ie_set = SET_INIT();
}
index_entry :: ~index_entry()
{
set_deinit(&ie_set);
}
static struct db_entry *index_alloc(const gchar *key)
{
struct index_entry *ent = new struct index_entry;
@ -21,6 +16,13 @@ static struct db_entry *index_alloc(const gchar *key)
return ent;
}
static void index_free(struct db_entry *dbe)
{
struct index_entry *ent = (struct index_entry *)dbe;
set_deinit(&ent->ie_set);
delete (struct index_entry *)dbe;
}
const std::string index_entry :: primary_key() const
{
return ie_key;
@ -45,6 +47,7 @@ void index_entry :: read(file &file)
static const struct db_ops index_ops = {
index_alloc,
index_free,
};

View File

@ -43,6 +43,11 @@ static struct db_entry *album_alloc(const gchar *key)
return album;
}
static void album_free(struct db_entry *dbe)
{
delete (struct album *)dbe;
}
const std::string album :: primary_key() const
{
return __album_key(al_name, al_year);
@ -63,6 +68,7 @@ void album :: write(file &file)
static const struct db_ops album_ops = {
album_alloc,
album_free,
};

View File

@ -24,6 +24,11 @@ static db_entry *artist_alloc(const gchar *name)
return artist;
}
static void artist_free(struct db_entry *dbe)
{
delete (struct artist *)dbe;
}
const std::string artist :: primary_key() const
{
return ar_name;
@ -49,6 +54,7 @@ void artist :: write(file &file)
static const struct db_ops artist_ops = {
artist_alloc,
artist_free,
};

View File

@ -23,6 +23,11 @@ static struct db_entry *genre_alloc(const gchar *name)
return genre;
}
static void genre_free(struct db_entry *dbe)
{
delete (struct genre *)dbe;
}
const std::string genre :: primary_key() const
{
return ge_name;
@ -48,6 +53,7 @@ void genre :: write(file &file)
static const struct db_ops genre_ops = {
genre_alloc,
genre_free,
};

View File

@ -21,6 +21,11 @@ static struct db_entry *library_alloc(const gchar *path)
return library;
}
static void library_free(struct db_entry *dbe)
{
delete (struct library *)dbe;
}
const std::string library :: primary_key() const
{
return li_path;
@ -47,6 +52,7 @@ void library :: write(file &file)
static const struct db_ops library_ops = {
library_alloc,
library_free,
};

View File

@ -82,10 +82,13 @@ out:
g_free(path);
}
track :: ~track()
static void track_free(struct db_entry *dbe)
{
if (tr_library)
tr_library->li_size--;
struct track *track = (struct track *)dbe;
if (track->tr_library)
track->tr_library->li_size--;
delete track;
}
const std::string track :: primary_key() const
@ -136,6 +139,8 @@ void track :: write(file &file)
static const struct db_ops track_ops = {
NULL,
track_free,
};

View File

@ -53,6 +53,9 @@ struct db_entry {
struct db_ops {
/* Allocate a new struct db_entry from a given key. */
struct db_entry *(*dbe_alloc)(const gchar *);
/* Free a struct db_entry. */
void (*dbe_free)(struct db_entry *);
};

View File

@ -7,6 +7,18 @@
#ifndef OCARINA_DATABASE_HPP
#define OCARINA_DATABASE_HPP
template <class T>
static inline void __dbe_free(struct database<T> *db, struct db_entry *dbe)
{
if (dbe) {
db->db_keys.erase(dbe->primary_key());
db->db_entries[dbe->dbe_index] = NULL;
db->db_size--;
db->db_ops->dbe_free(dbe);
}
}
template <class T>
void db_init(struct database<T> *db, const char *filepath, bool autosave,
const struct db_ops *ops)
@ -20,12 +32,9 @@ void db_init(struct database<T> *db, const char *filepath, bool autosave,
template <class T>
void db_deinit(struct database<T> *db)
{
T *t, *u;
db_for_each(t, u, db) {
db->db_entries[t->dbe_index] = NULL;
delete t;
db->db_size--;
}
T *dbe, *next;
db_for_each(dbe, next, db)
__dbe_free(db, dbe);
}
template <class T>
@ -106,10 +115,7 @@ void db_remove(struct database<T> *db, T *item)
return;
if (db_at(db, item->dbe_index) != item)
return;
db->db_entries[item->dbe_index] = NULL;
db->db_keys.erase(item->primary_key());
delete item;
db->db_size--;
__dbe_free(db, item);
db_autosave(db);
}

View File

@ -21,7 +21,6 @@ struct index_entry : public db_entry {
struct set ie_set;
index_entry(); /**< Create an empty IndexEntry. */
~index_entry();
/**
* Access the key stored by this IndexEntry.

View File

@ -35,7 +35,6 @@ struct track : public db_entry {
track(const std::string &);
track(); /**< Track constructor. */
~track(); /**< Track destructor. */
/**

View File

@ -30,6 +30,8 @@ struct int_entry : public db_entry {
void read(file &f) { file_readf(&f, "%u", &ie_val); }
};
unsigned int test_free_count = 0;
static struct db_entry *int_alloc(const gchar *key)
{
struct int_entry *ent = new int_entry;
@ -37,9 +39,15 @@ static struct db_entry *int_alloc(const gchar *key)
return ent;
}
static void int_free(struct db_entry *dbe)
{
test_free_count++;
delete (struct int_entry *)dbe;
}
static const struct db_ops int_ops = {
int_alloc,
int_free,
};
@ -57,7 +65,9 @@ static void test_db_entry()
file_open(&f, OPEN_WRITE);
ent->write(f);
file_close(&f);
delete ent;
int_ops.dbe_free(ent);
test_equal(test_free_count, 1);
ent = new int_entry();
test_equal(ent->ie_val, 0);
@ -69,7 +79,8 @@ static void test_db_entry()
test_equal(ent->ie_val, 1);
test_equal(ent->primary_key(), "1");
delete ent;
int_ops.dbe_free(ent);
test_equal(test_free_count, 2);
}
static void test_init()
@ -97,6 +108,7 @@ static void test_stress(unsigned int N)
unsigned int i;
gchar *key;
test_free_count = 0;
db_init(&db, "stress.db", false, &int_ops);
/* db_insert() */
@ -162,6 +174,7 @@ static void test_stress(unsigned int N)
db_remove(&db, &rmv);
test_equal(db.db_size, N / 2);
test_equal(db_actual_size(&db), N + 1);
test_equal(test_free_count, (N / 2) + 1);
/* db_for_each() (db_first() / db_next()) */
i = 1;
@ -184,6 +197,7 @@ static void test_stress(unsigned int N)
test_equal(db.db_size, 0);
test_equal(db_actual_size(&db), N + 1);
test_equal(db_first(&db), NULL);
test_equal(test_free_count, N + 1);
}
static void test_basics() { test_stress(10); }

View File

@ -8,12 +8,13 @@
static void test_entry()
{
const struct db_ops *index_ops = test_index_ops();
struct set_iter it;
index_entry *ie;
unsigned int i;
struct file f;
ie = (index_entry *)test_index_ops()->dbe_alloc("Link");
ie = (index_entry *)index_ops->dbe_alloc("Link");
test_equal(ie->primary_key(), "Link");
set_insert(&ie->ie_set, 0);
set_insert(&ie->ie_set, 1);
@ -30,7 +31,7 @@ static void test_entry()
file_writef(&f, "Zelda\n0 \n");
ie->write(f);
file_close(&f);
delete ie;
index_ops->dbe_free(ie);
ie = new index_entry();
test_equal(ie->primary_key(), "");
@ -52,7 +53,7 @@ static void test_entry()
i++;
} test_loop_passed();
delete ie;
index_ops->dbe_free(ie);
}
static void test_stress(unsigned int N)

View File

@ -34,7 +34,7 @@ static void test_album()
file_writef(&f, "0 \n");
album->write(f);
file_close(&f);
delete album;
album_ops->dbe_free(album);
album = new struct album();
test_verify_empty(album);
@ -46,7 +46,7 @@ static void test_album()
album->read(f);
file_close(&f);
test_verify_hyrule(album);
delete album;
album_ops->dbe_free(album);
}
static void test_album_compare()
@ -61,8 +61,8 @@ static void test_album_compare()
test_equal(album_compare(twilight, skyward), 1);
test_equal(album_compare(skyward, twilight), -1);
delete skyward;
delete twilight;
album_ops->dbe_free(twilight);
album_ops->dbe_free(skyward);
}
static void test_album_db()

View File

@ -33,7 +33,7 @@ static void test_artist()
file_writef(&f, "1 \n1 ");
artist->write(f);
file_close(&f);
delete artist;
artist_ops->dbe_free(artist);
artist = new struct artist();
test_verify_empty(artist);
@ -47,7 +47,7 @@ static void test_artist()
artist->read(f);
file_close(&f);
test_verify_koji(artist);
delete artist;
artist_ops->dbe_free(artist);
}
static void test_artist_compare()
@ -62,8 +62,8 @@ static void test_artist_compare()
test_equal(artist_compare(koji, hajime), 1);
test_equal(artist_compare(hajime, koji), -1);
delete hajime;
delete koji;
artist_ops->dbe_free(koji);
artist_ops->dbe_free(hajime);
}
static void test_artist_db()

View File

@ -33,7 +33,7 @@ static void test_genre()
file_writef(&f, "1 \n1 ");
genre->write(f);
file_close(&f);
delete genre;
genre_ops->dbe_free(genre);
genre = new struct genre();
test_verify_empty(genre);
@ -47,7 +47,7 @@ static void test_genre()
genre->read(f);
file_close(&f);
test_verify_vg(genre);
delete genre;
genre_ops->dbe_free(genre);
}
static void test_genre_compare()
@ -62,8 +62,8 @@ static void test_genre_compare()
test_equal(genre_compare(video, game), 1);
test_equal(genre_compare(game, video), -1);
delete game;
delete video;
genre_ops->dbe_free(video);
genre_ops->dbe_free(game);
}
static void test_genere_db()

View File

@ -59,9 +59,9 @@ static void test_library()
test_verify_zelda(library);
test_equal(library_file(library, "impa.ogg"), "/home/Zelda/Music/impa.ogg");
delete library;
delete zelda;
delete link;
library_ops->dbe_free(link);
library_ops->dbe_free(zelda);
library_ops->dbe_free(library);
}
static void test_library_db()

View File

@ -75,6 +75,7 @@ static void test_verify_notrack(struct track *track)
static void test_track()
{
const struct db_ops *track_ops = test_track_ops();
time_t rawtime = time(NULL);
struct tm *now = localtime(&rawtime);
struct track *track = new struct track;;
@ -83,7 +84,7 @@ static void test_track()
file f;
test_verify_empty(track);
delete track;
track_ops->dbe_free(track);
std::setlocale(LC_TIME, "C");
filter_init();
@ -102,7 +103,7 @@ static void test_track()
track->write(f);
file_close(&f);
delete track;
track_ops->dbe_free(track);
test_equal(library->li_size, 0);
track = new struct track;
@ -110,7 +111,7 @@ static void test_track()
track->read(f);
test_verify_notrack(track);
test_equal(library->li_size, 1);
delete track;
track_ops->dbe_free(track);
track = new struct track;
track->read(f);
@ -122,7 +123,7 @@ static void test_track()
test_equal(track->tr_count, 1);
test_equal(track_last_play(track), date);
delete track;
track_ops->dbe_free(track);
g_free(date);
}
@ -148,6 +149,7 @@ static void test_track_filter()
static void test_track_compare()
{
const struct db_ops *track_ops = test_track_ops();
struct track *title = new struct track("0/Hyrule Symphony/01 - Title Theme.ogg");
struct track *kokiri = new struct track("0/Hyrule Symphony/02 - Kokiri Forest.ogg");
@ -155,8 +157,8 @@ static void test_track_compare()
test_equal(track_compare(kokiri, title), -1);
test_equal(track_compare(title, kokiri), 1);
delete title;
delete kokiri;
track_ops->dbe_free(title);
track_ops->dbe_free(kokiri);
}
static void test_track_db()