core/database: Replace database constructor and destructor
Use db_init() and db_deinit() instead. Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
parent
3ff992cf52
commit
2c5b14c7f3
|
@ -70,8 +70,9 @@ void IndexEntry :: read(file &file)
|
|||
|
||||
|
||||
Index :: Index(const std::string &filepath, bool autosave)
|
||||
: database(filepath, autosave)
|
||||
{}
|
||||
{
|
||||
db_init(this, filepath.c_str(), autosave);
|
||||
}
|
||||
|
||||
void Index :: insert(const std::string &key, unsigned int value)
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@ extern "C" {
|
|||
#include <glib.h>
|
||||
|
||||
|
||||
static database<Album> album_db("album.db", true);
|
||||
static database<Album> album_db;
|
||||
|
||||
static const std::string make_key(const std::string &name, unsigned int year)
|
||||
{
|
||||
|
@ -65,6 +65,7 @@ unsigned int Album :: year()
|
|||
|
||||
void tags :: init_album_db()
|
||||
{
|
||||
db_init(&album_db, "album.db", true);
|
||||
db_load(&album_db);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <core/tags/artist.h>
|
||||
|
||||
|
||||
static database<Artist> artist_db("artist.db", true);
|
||||
static database<Artist> artist_db;
|
||||
|
||||
|
||||
Artist :: Artist() : GenericTag() {}
|
||||
|
@ -17,6 +17,7 @@ Artist :: Artist(const std::string &name)
|
|||
|
||||
void tags :: init_artist_db()
|
||||
{
|
||||
db_init(&artist_db, "artist.db", true);
|
||||
db_load(&artist_db);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <core/tags/genre.h>
|
||||
|
||||
|
||||
static database<Genre> genre_db("genre.db", true);
|
||||
static database<Genre> genre_db;
|
||||
|
||||
|
||||
Genre :: Genre() : GenericTag() {}
|
||||
|
@ -17,6 +17,7 @@ Genre :: Genre(const std::string &name)
|
|||
|
||||
void tags :: init_genre_db()
|
||||
{
|
||||
db_init(&genre_db, "genre.db", true);
|
||||
db_load(&genre_db);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <core/tags/library.h>
|
||||
|
||||
|
||||
static database<Library> library_db("library.db", true);
|
||||
static database<Library> library_db;
|
||||
|
||||
|
||||
Library :: Library()
|
||||
|
@ -69,6 +69,7 @@ void Library :: dec_size()
|
|||
|
||||
void tags :: init_library_db()
|
||||
{
|
||||
db_init(&library_db, "library.db", true);
|
||||
db_load(&library_db);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <glib.h>
|
||||
|
||||
|
||||
static database<Track> track_db("track.db", false);
|
||||
static database<Track> track_db;
|
||||
|
||||
static const std::string make_key(Library *library, const std::string &path)
|
||||
{
|
||||
|
@ -144,6 +144,7 @@ void Track :: write(file &file)
|
|||
|
||||
void tags :: init_track_db()
|
||||
{
|
||||
db_init(&track_db, "track.db", false);
|
||||
db_load(&track_db);
|
||||
}
|
||||
|
||||
|
|
|
@ -85,27 +85,21 @@ struct database {
|
|||
|
||||
std::vector<T *> db_entries;
|
||||
std::map<const std::string, unsigned int> db_keys;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a Database using filepath as a location to store data
|
||||
* on disk.
|
||||
*
|
||||
* @param filepath File on disk that will be written to.
|
||||
* @param autosave Set to True if the Database should be saved upon
|
||||
* every insertion and deletion. If this is set
|
||||
* to False then the Database will have to be saved
|
||||
* manually.
|
||||
*/
|
||||
database(std::string, bool);
|
||||
|
||||
/**
|
||||
* Deletes all remaining entries in a Database to prevent memory leaks.
|
||||
*/
|
||||
~database();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Initialize a database using filepath as a location on disk to store data
|
||||
* and autosave as a hint for if this database should be automatically saved.
|
||||
*/
|
||||
template <class T>
|
||||
void db_init(struct database<T> *, const char *, bool);
|
||||
|
||||
/* Called to prevent memory leaks by freeing all remaining database entries. */
|
||||
template <class T>
|
||||
void db_deinit(struct database<T> *);
|
||||
|
||||
|
||||
/* Called to write the database to disk. */
|
||||
template <class T>
|
||||
void db_save(struct database<T> *);
|
||||
|
|
|
@ -8,18 +8,22 @@
|
|||
#define OCARINA_DATABASE_HPP
|
||||
|
||||
template <class T>
|
||||
database<T> :: database(std::string filepath, bool autosave)
|
||||
: db_size(0), db_autosave(autosave)
|
||||
void db_init(struct database<T> *db, const char *filepath, bool autosave)
|
||||
{
|
||||
file_init(&db_file, filepath.c_str(), 0);
|
||||
db->db_size = 0;
|
||||
db->db_autosave = autosave;
|
||||
file_init(&db->db_file, filepath, 0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
database<T> :: ~database()
|
||||
void db_deinit(struct database<T> *db)
|
||||
{
|
||||
T *t, *u;
|
||||
db_for_each(t, u, this)
|
||||
db_for_each(t, u, db) {
|
||||
db->db_entries[t->index()] = NULL;
|
||||
delete t;
|
||||
db->db_size--;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
|
|
@ -62,21 +62,31 @@ static void test_db_entry()
|
|||
|
||||
static void test_init()
|
||||
{
|
||||
database<struct int_entry> db("database.db", false);
|
||||
database<struct int_entry> db;
|
||||
|
||||
db_init(&db, "init.db", false);
|
||||
|
||||
/* Check initial sizes. */
|
||||
test_equal(db_actual_size(&db), 0);
|
||||
test_equal(db.db_entries.size(), 0);
|
||||
test_equal(db.db_keys.size(), 0);
|
||||
test_equal(db.db_size, 0);
|
||||
test_equal(db.db_autosave, false);
|
||||
test_equal(db.db_file.f_version, 0);
|
||||
test_equal(db.db_file.f_name, "init.db");
|
||||
|
||||
db_deinit(&db);
|
||||
}
|
||||
|
||||
static void test_stress(unsigned int N)
|
||||
{
|
||||
database<struct int_entry> db("stress.db", false);
|
||||
database<struct int_entry> db;
|
||||
std::vector<struct int_entry *> ptrs;
|
||||
struct int_entry *dbe, *next, rmv(42);
|
||||
unsigned int i;
|
||||
gchar *key;
|
||||
|
||||
db_init(&db, "stress.db", false);
|
||||
|
||||
/* db_insert() */
|
||||
for (i = 0; i < N; i++) {
|
||||
dbe = db_insert(&db, new int_entry(i));
|
||||
|
@ -157,6 +167,11 @@ static void test_stress(unsigned int N)
|
|||
i += 2;
|
||||
} test_loop_passed();
|
||||
test_equal(i, N + 1);
|
||||
|
||||
db_deinit(&db);
|
||||
test_equal(db.db_size, 0);
|
||||
test_equal(db_actual_size(&db), N + 1);
|
||||
test_equal(db_first(&db), NULL);
|
||||
}
|
||||
|
||||
static void test_basics() { test_stress(10); }
|
||||
|
@ -165,67 +180,65 @@ static void test_stress_100K() { test_stress(100000); }
|
|||
|
||||
static void test_save_load()
|
||||
{
|
||||
database<struct int_entry> db1("save_load.db", true);
|
||||
database<struct int_entry> db2("save_load.db", false);
|
||||
struct int_entry *dbe;
|
||||
database<struct int_entry> db1, db2;
|
||||
struct int_entry *dbe, *next;
|
||||
const unsigned int N = 10;
|
||||
unsigned int i;
|
||||
|
||||
db_init(&db1, "save_load.db", true);
|
||||
db_init(&db2, "save_load.db", false);
|
||||
|
||||
/* 10 items should "autosave" when inserted */
|
||||
for (i = 0; i < N; i++)
|
||||
db_insert(&db1, new int_entry(i));
|
||||
|
||||
i = 0;
|
||||
db_load(&db2);
|
||||
test_equal(db2.db_size, N);
|
||||
test_equal(db_actual_size(&db2), N);
|
||||
for (i = 0; i < N; i++) {
|
||||
dbe = db_at(&db2, i);
|
||||
test_loop_not_equal(dbe, NULL, i);
|
||||
db_for_each(dbe, next, &db2) {
|
||||
test_loop_equal(dbe->ie_val, i, i);
|
||||
i++;
|
||||
} test_loop_passed();
|
||||
|
||||
/* Removing 5 items, should also trigger autosaving. */
|
||||
for (i = 0; i < N; i += 2)
|
||||
db_remove(&db1, db_at(&db1, i));
|
||||
|
||||
db2 = database<struct int_entry>("save_load.db", false);
|
||||
i = 1;
|
||||
db_deinit(&db2);
|
||||
db_load(&db2);
|
||||
test_equal(db2.db_size, N / 2);
|
||||
for (i = 1; i < N; i++) {
|
||||
dbe = db_at(&db2, i);
|
||||
if ((i % 2) == 0) {
|
||||
test_loop_equal(dbe, NULL, i);
|
||||
} else {
|
||||
test_loop_not_equal(dbe, NULL, i);
|
||||
test_loop_equal(dbe->ie_val, i, i);
|
||||
}
|
||||
db_for_each(dbe, next, &db2) {
|
||||
test_loop_equal(dbe->ie_val, i, i);
|
||||
i += 2;
|
||||
} test_loop_passed();
|
||||
|
||||
/* Test with autosave turned off. */
|
||||
/* Manually turn autosave off. */
|
||||
db1.db_autosave = false;
|
||||
for (i = N; i < (2 * N); i++)
|
||||
db_insert(&db2, new int_entry(i));
|
||||
db_insert(&db1, new int_entry(i));
|
||||
for (i = N; i < (2 * N); i += 2)
|
||||
db_remove(&db2, db_at(&db2, i));
|
||||
db_remove(&db1, db_at(&db1, i));
|
||||
|
||||
db1 = database<struct int_entry>("save_load.db", false);
|
||||
db_load(&db1);
|
||||
test_equal(db1.db_size, N / 2);
|
||||
db_deinit(&db2);
|
||||
db_load(&db2);
|
||||
test_equal(db2.db_size, N / 2);
|
||||
|
||||
db_save(&db2);
|
||||
db1 = database<struct int_entry>("save_load.db", false);
|
||||
db_load(&db1);
|
||||
db_save(&db1);
|
||||
db_deinit(&db2);
|
||||
db_load(&db2);
|
||||
|
||||
test_equal(db1.db_size, N);
|
||||
test_equal(db_actual_size(&db1), 2 * N);
|
||||
for (i = 1; i < (2 * N); i++) {
|
||||
dbe = db_at(&db1, i);
|
||||
if ((i % 2) == 0) {
|
||||
test_loop_equal(dbe, NULL, i);
|
||||
} else {
|
||||
test_loop_not_equal(dbe, NULL, i);
|
||||
test_loop_equal(dbe->ie_val, i, i);
|
||||
}
|
||||
i = 1;
|
||||
test_equal(db2.db_size, N);
|
||||
test_equal(db_actual_size(&db2), 2 * N);
|
||||
db_for_each(dbe, next, &db2) {
|
||||
test_loop_equal(dbe->ie_val, i, i);
|
||||
i += 2;
|
||||
} test_loop_passed();
|
||||
|
||||
db_deinit(&db1);
|
||||
db_deinit(&db2);
|
||||
}
|
||||
|
||||
DECLARE_UNIT_TESTS(
|
||||
|
|
|
@ -16,7 +16,8 @@ res += [ TagTest("artist", "artist.cpp") ]
|
|||
res += [ TagTest("album", "album.cpp") ]
|
||||
res += [ TagTest("genre", "genre.cpp") ]
|
||||
res += [ TagTest("library", "library.cpp") ]
|
||||
res += [ TagTest("track", "track.cpp") ]
|
||||
|
||||
core_objs += [ env.Object("../../../core/tags/tags.cpp") ]
|
||||
res += [ TagTest("track", "track.cpp") ]
|
||||
|
||||
Return("res")
|
||||
|
|
|
@ -37,8 +37,11 @@ static void test_album_tag()
|
|||
|
||||
static void test_album_tag_lookup()
|
||||
{
|
||||
database<Album> album_db("album.db", false);
|
||||
Album *album = tags :: get_album("Hyrule Symphony", 1998);
|
||||
database<Album> album_db;
|
||||
Album *album;
|
||||
|
||||
tags :: init_album_db();
|
||||
album = tags :: get_album("Hyrule Symphony", 1998);
|
||||
|
||||
test_equal(album->name(), (std::string)"Hyrule Symphony");
|
||||
test_equal(album->lowercase(), (std::string)"hyrule symphony");
|
||||
|
@ -49,6 +52,7 @@ static void test_album_tag_lookup()
|
|||
test_equal(tags :: get_album(0), album);
|
||||
test_equal(tags :: get_album(1), (Album *)NULL);
|
||||
|
||||
db_init(&album_db, "album.db", false);
|
||||
db_load(&album_db);
|
||||
test_equal(album_db.db_size, (unsigned)1);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,11 @@ static void test_artist_tag()
|
|||
|
||||
static void test_artist_tag_lookup()
|
||||
{
|
||||
database<Artist> artist_db("artist.db", false);
|
||||
Artist *artist = tags :: get_artist("Koji Kondo");
|
||||
database<Artist> artist_db;
|
||||
Artist *artist;
|
||||
|
||||
tags :: init_artist_db();
|
||||
artist = tags :: get_artist("Koji Kondo");
|
||||
|
||||
test_equal(artist->name(), (std::string)"Koji Kondo");
|
||||
test_equal(artist->lowercase(), (std::string)"koji kondo");
|
||||
|
@ -30,6 +33,7 @@ static void test_artist_tag_lookup()
|
|||
test_equal(tags :: get_artist(0), artist);
|
||||
test_equal(tags :: get_artist(1), (Artist *)NULL);
|
||||
|
||||
db_init(&artist_db, "artist.db", false);
|
||||
db_load(&artist_db);
|
||||
test_equal(artist_db.db_size, (unsigned)1);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,11 @@ static void test_artist_tag()
|
|||
|
||||
static void test_genere_tag_lookup()
|
||||
{
|
||||
database<Genre> genre_db("genre.db", false);
|
||||
Genre *genre = tags :: get_genre("Video Game Music");
|
||||
database<Genre> genre_db;
|
||||
Genre *genre;
|
||||
|
||||
tags :: init_genre_db();
|
||||
genre = tags :: get_genre("Video Game Music");
|
||||
|
||||
test_equal(genre->name(), (std::string)"Video Game Music");
|
||||
test_equal(genre->lowercase(), (std::string)"video game music");
|
||||
|
@ -30,6 +33,7 @@ static void test_genere_tag_lookup()
|
|||
test_equal(tags :: get_genre(0), genre);
|
||||
test_equal(tags :: get_genre(1), (Genre *)NULL);
|
||||
|
||||
db_init(&genre_db, "genre.db", false);
|
||||
db_load(&genre_db);
|
||||
test_equal(genre_db.db_size, (unsigned)1);
|
||||
}
|
||||
|
|
|
@ -44,11 +44,12 @@ static void test_library_tag()
|
|||
|
||||
static void test_library_tag_lookup()
|
||||
{
|
||||
database<Library> library_db("library.db", false);
|
||||
database<Library> library_db;
|
||||
Library *library;
|
||||
|
||||
test_equal(tags :: library_size(), (unsigned)0);
|
||||
|
||||
tags :: init_library_db();
|
||||
library = tags :: get_library("/home/Zelda/Music");
|
||||
test_equal(library->primary_key(), (std::string)"/home/Zelda/Music");
|
||||
test_equal(library->size(), (unsigned)0);
|
||||
|
@ -58,6 +59,7 @@ static void test_library_tag_lookup()
|
|||
test_equal(tags :: get_library(0), library);
|
||||
test_equal(tags :: get_library(1), (Library *)NULL);
|
||||
|
||||
db_init(&library_db, "library.db", false);
|
||||
db_load(&library_db);
|
||||
test_equal(db_actual_size(&library_db), (unsigned)tags :: library_size());
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ extern "C" {
|
|||
#include <core/string.h>
|
||||
}
|
||||
#include <core/filter.h>
|
||||
#include <core/tags/tags.h>
|
||||
#include <core/tags/track.h>
|
||||
#include "../test.h"
|
||||
|
||||
|
@ -62,6 +63,7 @@ static void test_track_tag_constructor()
|
|||
{
|
||||
file f;
|
||||
|
||||
tags :: init();
|
||||
album = tags :: get_album("Hyrule Symphony", 1998);
|
||||
artist = tags :: get_artist("Koji Kondo");
|
||||
genre = tags :: get_genre("Video Game Music");
|
||||
|
@ -107,9 +109,11 @@ static void test_track_tag_destructor()
|
|||
|
||||
static void test_track_tag_load_db(unsigned int size)
|
||||
{
|
||||
database<Track> track_db("track.db", false);
|
||||
database<Track> track_db;
|
||||
db_init(&track_db, "track.db", false);
|
||||
db_load(&track_db);
|
||||
test_equal(track_db.db_size, size);
|
||||
db_deinit(&track_db);
|
||||
}
|
||||
|
||||
static void test_track_tag_lookup()
|
||||
|
|
Loading…
Reference in New Issue