From acd8bd7b234c39f26050918148075423af2e3eb9 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Mon, 30 Dec 2013 18:18:23 -0500 Subject: [PATCH] database: Implement updates to match my current design - Force the primary key to be a string - Throw error codes rather than 0 Signed-off-by: Anna Schumaker --- design.txt | 31 +++++---- design/database.txt | 31 +++++---- include/database.h | 28 ++++----- include/database.hpp | 122 ++++++++++++++++++++---------------- lib/database.cpp | 23 ++++--- tests/database/database.cpp | 33 ++++------ tests/index/index.cpp | 29 +++++---- 7 files changed, 162 insertions(+), 135 deletions(-) diff --git a/design.txt b/design.txt index c26fd6bf..855b7ff3 100644 --- a/design.txt +++ b/design.txt @@ -240,9 +240,10 @@ Database: (lib/database.cpp) - DatabaseEntry: class DatabaseEntry { /* let database modify valid flag */ public: + const std::string primary_key; bool valid; - virtual const std::string &primary_key() = 0; + DatabaseEntry(const std::string &); virtual void write(File &) = 0; virtual void read(File &) = 0; virtual void print() = 0; @@ -253,13 +254,13 @@ Database: (lib/database.cpp) - IndexEntry: class IndexEntry : public DatabaseEntry { public: - string key; set values; - const std::string &primary_key(); void write(File &); void read(File &); void print(); + void insert(unsigned int); + void remove(unsigned int); }; File << key << endl; @@ -283,7 +284,7 @@ Database: (lib/database.cpp) void print_keys(); unsigned int insert(T); - void delete(unsigned int); + void remove(unsigned int); unsigned int size(); unsigned int num_rows(); @@ -332,7 +333,7 @@ Database: (lib/database.cpp) mapping is also created into the keys map to map the primary key back to the id of the newly added item. - void Database :: delete(unsigned int index); + void Database :: remove(unsigned int index); Mark db[index] as invalid (quick deletion). unsigned int Database :: size(); @@ -342,14 +343,16 @@ Database: (lib/database.cpp) Return db.size(). unsigned int Database :: first(); - Return the id to the first valid row. + Return the id to the first valid row. Return db.size() if + there are no valid rows. unsigned int Database :: last(); - Return the id of the last valid row. + Return the id of the last valid row. Return db.size() if + there are no valid rows. unsigned int Database :: next(unsigned int &id); - Return the id of the next valid row or throw -EINVAL if there - are no remaining valid rows. + Return the id of the next valid row or return db.size() if + there are no valid rows. bool Database :: has_key(const std::string &key); Return true if an item with primary key "key" exists in the @@ -363,13 +366,15 @@ Database: (lib/database.cpp) template T &Database :: find(const std::string &key); Search for primary key "key" in the database. The reverse - mapping should be used to make this operation faster. Throw - -EEXIST if the key is not found in the mapping. + mapping should be used to make this operation faster. + Throw -EEXIST if the key is not found in the mapping. + Throw -EINVAL if the key points to an invalid entry. template T &Database :: operator[](unsigned int index); - Return a reference to db[index]. Throw -EEXIST if index is out - of range. + Return a reference to db[index]. + Throw -EEXIST if index is out of range. + Throw -EINVAL if index is invalid. diff --git a/design/database.txt b/design/database.txt index 6101f9e0..f336f420 100644 --- a/design/database.txt +++ b/design/database.txt @@ -32,9 +32,10 @@ Database: (lib/database.cpp) - DatabaseEntry: class DatabaseEntry { /* let database modify valid flag */ public: + const std::string primary_key; bool valid; - virtual const std::string &primary_key() = 0; + DatabaseEntry(const std::string &); virtual void write(File &) = 0; virtual void read(File &) = 0; virtual void print() = 0; @@ -45,13 +46,13 @@ Database: (lib/database.cpp) - IndexEntry: class IndexEntry : public DatabaseEntry { public: - string key; set values; - const std::string &primary_key(); void write(File &); void read(File &); void print(); + void insert(unsigned int); + void remove(unsigned int); }; File << key << endl; @@ -75,7 +76,7 @@ Database: (lib/database.cpp) void print_keys(); unsigned int insert(T); - void delete(unsigned int); + void remove(unsigned int); unsigned int size(); unsigned int num_rows(); @@ -124,7 +125,7 @@ Database: (lib/database.cpp) mapping is also created into the keys map to map the primary key back to the id of the newly added item. - void Database :: delete(unsigned int index); + void Database :: remove(unsigned int index); Mark db[index] as invalid (quick deletion). unsigned int Database :: size(); @@ -134,14 +135,16 @@ Database: (lib/database.cpp) Return db.size(). unsigned int Database :: first(); - Return the id to the first valid row. + Return the id to the first valid row. Return db.size() if + there are no valid rows. unsigned int Database :: last(); - Return the id of the last valid row. + Return the id of the last valid row. Return db.size() if + there are no valid rows. unsigned int Database :: next(unsigned int &id); - Return the id of the next valid row or throw -EINVAL if there - are no remaining valid rows. + Return the id of the next valid row or return db.size() if + there are no valid rows. bool Database :: has_key(const std::string &key); Return true if an item with primary key "key" exists in the @@ -155,10 +158,12 @@ Database: (lib/database.cpp) template T &Database :: find(const std::string &key); Search for primary key "key" in the database. The reverse - mapping should be used to make this operation faster. Throw - -EEXIST if the key is not found in the mapping. + mapping should be used to make this operation faster. + Throw -EEXIST if the key is not found in the mapping. + Throw -EINVAL if the key points to an invalid entry. template T &Database :: operator[](unsigned int index); - Return a reference to db[index]. Throw -EEXIST if index is out - of range. + Return a reference to db[index]. + Throw -EEXIST if index is out of range. + Throw -EINVAL if index is invalid. diff --git a/include/database.h b/include/database.h index 785bca6a..3c4cd6b1 100644 --- a/include/database.h +++ b/include/database.h @@ -12,43 +12,42 @@ #include -template class DatabaseEntry { public: + std::string primary_key; bool valid; DatabaseEntry(); - virtual T &primary_key() = 0; virtual void write(File &) = 0; virtual void read(File &) = 0; -#ifdef CONFIG_DEBUG +#ifdef CONFIG_TEST virtual void print() = 0; -#endif /* CONFIG_DEBUG */ +#endif /* CONFIG_TEST */ }; -class IndexEntry : public DatabaseEntry { +class IndexEntry : public DatabaseEntry { public: - std::string key; std::set values; IndexEntry(); IndexEntry(const std::string &, unsigned int); ~IndexEntry(); - const std::string &primary_key(); void write(File &); void read(File &); +#ifdef CONFIG_TEST void print(); +#endif /* CONFIG_TEST */ void insert(unsigned int); void remove(unsigned int); }; -template +template class Database { private: std::vector db; - std::map keys; + std::map keys; unsigned int _size; File file; @@ -57,11 +56,11 @@ public: ~Database(); void save(); void load(); -#ifdef CONFIG_DEBUG +#ifdef CONFIG_TEST void clear(); void print(); void print_keys(); -#endif /* CONFIG_DEBUG */ +#endif /* CONFIG_TEST */ unsigned int insert(T); void remove(unsigned int); @@ -71,13 +70,13 @@ public: unsigned int first(); unsigned int last(); unsigned int next(unsigned int); + bool has_key(const std::string &); unsigned int find_index(const std::string &); T &find(const std::string &); T &operator[](unsigned int); }; -template -static inline void index_insert(Database &db, +static inline void index_insert(Database &db, const std::string &key, unsigned int val) { @@ -88,8 +87,7 @@ static inline void index_insert(Database &db, } } -template -static inline void index_remove(Database &db, +static inline void index_remove(Database &db, const std::string &key, unsigned int val) { diff --git a/include/database.hpp b/include/database.hpp index 20d00075..7f9f8a08 100644 --- a/include/database.hpp +++ b/include/database.hpp @@ -7,30 +7,27 @@ #ifndef OCARINA_DATABASE_HPP #define OCARINA_DATABASE_HPP +#include + template -DatabaseEntry :: DatabaseEntry() - : valid(false) -{ -} - - - -template -Database :: Database(std::string filepath) +Database :: Database(std::string filepath) : _size(0), file(filepath, FILE_TYPE_DATA) { } -template -Database :: ~Database() +template +Database :: ~Database() { } -template -void Database :: save() +template +void Database :: save() { - if (file.open(OPEN_WRITE) == false) + try { + file.open(OPEN_WRITE); + } catch (int error) { return; + } file << db.size() << std::endl; for (unsigned int i = 0; i < db.size(); i++) { @@ -43,12 +40,16 @@ void Database :: save() file.close(); } -template -void Database :: load() +template +void Database :: load() { unsigned int db_size; - if (file.open(OPEN_READ) == false) + + try { + file.open(OPEN_READ); + } catch (int error) { return; + } file >> db_size; db.resize(db_size); @@ -56,7 +57,7 @@ void Database :: load() file >> db[i].valid; if (db[i].valid == true) { db[i].read(file); - keys.insert(std::pair(db[i].primary_key(), i)); + keys.insert(std::pair(db[i].primary_key, i)); _size++; } } @@ -64,17 +65,17 @@ void Database :: load() file.close(); } -#ifdef CONFIG_DEBUG -template -void Database :: clear() +#ifdef CONFIG_TEST +template +void Database :: clear() { db.clear(); keys.clear(); _size = 0; } -template -void Database :: print() +template +void Database :: print() { :: print("Allocated rows: %u\n", db.size()); :: print("Valid rows: %u\n", _size); @@ -87,8 +88,8 @@ void Database :: print() } } -template -void Database :: print_keys() +template +void Database :: print_keys() { std::map::iterator it; :: print("Found keys:"); @@ -96,15 +97,15 @@ void Database :: print_keys() :: print(" %s", it->first.c_str()); :: print("\n"); } -#endif /* CONFIG_DEBUG */ +#endif /* CONFIG_TEST */ -template -unsigned int Database :: insert(T val) +template +unsigned int Database :: insert(T val) { unsigned int id; - typename std::map::iterator it; + typename std::map::iterator it; - it = keys.find(val.primary_key()); + it = keys.find(val.primary_key); if (it != keys.end()) return it->second; @@ -113,34 +114,34 @@ unsigned int Database :: insert(T val) */ id = db.size(); db.push_back(val); - keys.insert(std::pair(val.primary_key(), id)); + keys.insert(std::pair(val.primary_key, id)); db[id].valid = true; _size++; return id; } -template -void Database :: remove(unsigned int id) +template +void Database :: remove(unsigned int id) { - keys.erase(db[id].primary_key()); + keys.erase(db[id].primary_key); db[id].valid = false; _size--; } -template -unsigned int Database :: size() +template +unsigned int Database :: size() { return _size; } -template -unsigned int Database :: num_rows() +template +unsigned int Database :: num_rows() { return db.size(); } -template -unsigned int Database :: first() +template +unsigned int Database :: first() { for (unsigned int i = 0; i < db.size(); i++) { if (db[i].valid == true) @@ -150,8 +151,8 @@ unsigned int Database :: first() return db.size(); } -template -unsigned int Database :: last() +template +unsigned int Database :: last() { if (_size == 0) return db.size(); @@ -164,8 +165,8 @@ unsigned int Database :: last() return db.size(); } -template -unsigned int Database :: next(unsigned int id) +template +unsigned int Database :: next(unsigned int id) { for (unsigned int i = id + 1; i < db.size(); i++) { if (db[i].valid == true) @@ -175,25 +176,40 @@ unsigned int Database :: next(unsigned int id) return db.size(); } -template -unsigned int Database :: find_index(const std::string &key) +template +bool Database :: has_key(const std::string &key) { - typename std::map::iterator it; + std::map::iterator it; + it = keys.find(key); + return it != keys.end(); +} + +template +unsigned int Database :: find_index(const std::string &key) +{ + std::map::iterator it; it = keys.find(key); if (it == keys.end()) - throw 0; + throw -EEXIST; return it->second; } -template -T &Database :: find(const std::string &key) +template +T &Database :: find(const std::string &key) { - return db[find_index(key)]; + unsigned int index = find_index(key); + if (db[index].valid == false) + throw -EINVAL; + return db[index]; } -template -T &Database :: operator[](unsigned int id) +template +T &Database :: operator[](unsigned int id) { + if (id >= db.size()) + throw -EEXIST; + else if (db[id].valid == false) + throw -EINVAL; return db[id]; } diff --git a/lib/database.cpp b/lib/database.cpp index 37be35ee..20459068 100644 --- a/lib/database.cpp +++ b/lib/database.cpp @@ -3,13 +3,21 @@ */ #include + +DatabaseEntry :: DatabaseEntry() + : primary_key(""), valid(false) +{ +} + + + IndexEntry :: IndexEntry() { } -IndexEntry :: IndexEntry(const std::string &k, unsigned int v) - : key(k) +IndexEntry :: IndexEntry(const std::string &key, unsigned int v) { + primary_key = key; insert(v); } @@ -17,15 +25,10 @@ IndexEntry :: ~IndexEntry() { } -const std::string &IndexEntry :: primary_key() -{ - return key; -} - void IndexEntry :: write(File &f) { std::set::iterator it; - f << key << std::endl << values.size() << " "; + f << primary_key << std::endl << values.size() << " "; for (it = values.begin(); it != values.end(); it++) f << *it << " "; } @@ -34,13 +37,14 @@ void IndexEntry :: read(File &f) { unsigned int num, val; - f >> key >> num; + f >> primary_key >> num; for (unsigned int i = 0; i < num; i++) { f >> val; values.insert(val); } } +#ifdef CONFIG_TEST void IndexEntry :: print() { std::set::iterator it; @@ -52,6 +56,7 @@ void IndexEntry :: print() } :: print("}"); } +#endif /* CONFIG_TEST */ void IndexEntry :: insert(unsigned int val) { diff --git a/tests/database/database.cpp b/tests/database/database.cpp index 3883843b..20ffe3fd 100644 --- a/tests/database/database.cpp +++ b/tests/database/database.cpp @@ -6,14 +6,12 @@ #include -class DBTest : public DatabaseEntry { +class DBTest : public DatabaseEntry { public: unsigned int value; - std::string key; DBTest(); DBTest(unsigned int); - const std::string &primary_key(); void write(File &); void read(File &); void print(); @@ -29,7 +27,7 @@ DBTest :: DBTest(unsigned int val) value = val; ss << value; - key = ss.str(); + primary_key = ss.str(); } void DBTest :: write(File &file) @@ -47,14 +45,9 @@ void DBTest :: print() :: print("%u", value); } -const std::string &DBTest :: primary_key() -{ - return key; -} - -void print_db(Database &db) +void print_db(Database &db) { print("Database size: %u\n", db.size()); print("Num rows: %u\n", db.num_rows()); @@ -65,14 +58,14 @@ void print_db(Database &db) print("db[%u] = %u\n", i, db[i].value); } -void test_insertion(Database &db) +void test_insertion(Database &db) { for (unsigned int i = 1; i <= 100000; i++) db.insert(DBTest(i)); print_db(db); } -void test_deletion(Database &db) +void test_deletion(Database &db) { for (unsigned int i = db.first(); i < db.num_rows(); i = db.next(i)) { db.remove(i); @@ -87,7 +80,7 @@ void test_deletion(Database &db) void test_0() { print("Test 0\n"); - Database db("test.db"); + Database db("test.db"); test_insertion(db); test_deletion(db); @@ -102,7 +95,7 @@ void test_0() void test_1() { print("\nTest 1\n"); - Database db("test.db"); + Database db("test.db"); db.load(); print_db(db); } @@ -113,7 +106,7 @@ void test_1() void test_2() { print("\nTest 2\n"); - Database db(""); + Database db(""); test_insertion(db); db.save(); @@ -125,7 +118,7 @@ void test_2() void test_3() { print("\nTest 3\n"); - Database db(""); + Database db(""); db.load(); } @@ -135,7 +128,7 @@ void test_3() void test_4() { print("\nTest 4\n"); - Database db(""); + Database db(""); for (unsigned int i = 0; i < 100; i++) db.insert(DBTest(i % 5)); @@ -149,7 +142,7 @@ void test_4() void test_5() { print("\nTest 5\n"); - Database db(""); + Database db(""); for (unsigned int i = 0; i < 10; i++) db.insert(DBTest(i)); db.print(); @@ -161,7 +154,7 @@ void test_5() void test_6() { print("\nTest 6\n"); - Database db(""); + Database db(""); for (unsigned int i = 0; i < 10; i++) db.insert(DBTest(i)); print_db(db); @@ -175,7 +168,7 @@ void test_6() void test_7() { print("\nTest 7\n"); - Database db(""); + Database db(""); print_db(db); for (unsigned int i = 0; i < 10; i++) diff --git a/tests/index/index.cpp b/tests/index/index.cpp index 4b8e9e79..eaa8a70f 100644 --- a/tests/index/index.cpp +++ b/tests/index/index.cpp @@ -4,7 +4,7 @@ #include #include -void print_index(Database &index) +void print_index(Database &index) { std::set::iterator s_it; std::set::iterator u_it; @@ -13,7 +13,7 @@ void print_index(Database &index) index.print_keys(); for (unsigned int i = index.first(); i != index.num_rows(); i = index.next(i)) { - print("index[%s] = ", index[i].key.c_str()); + print("index[%s] = ", index[i].primary_key.c_str()); index[i].print(); print("\n"); } @@ -21,7 +21,7 @@ void print_index(Database &index) print("\n"); } -void populate_index(Database &index) +void populate_index(Database &index) { std::string key_str; @@ -32,17 +32,19 @@ void populate_index(Database &index) } } -void remove_keys(Database &index) +void remove_keys(Database &index) { std::string key_str; for (char key = 'a'; key <= 'z'; key+=2) { key_str = key; index.remove(index.find_index(key_str)); + if (index.has_key(key_str)) + print("Failed to remove key!\n"); } } -void remove_values(Database &index) +void remove_values(Database &index) { std::string key_str; unsigned int limit = 0; @@ -52,8 +54,11 @@ void remove_values(Database &index) for (unsigned int i = 0; i < limit; i++) index_remove(index, key_str, i); limit++; - if (limit == 11) + if (limit == 11) { limit = 0; + if (index.has_key(key_str)) + print("Failed to remove key!\n"); + } } } @@ -63,7 +68,7 @@ void remove_values(Database &index) void test_0() { print("Test 0\n"); - Database index(""); + Database index(""); populate_index(index); print_index(index); @@ -75,7 +80,7 @@ void test_0() void test_1() { print("Test 1\n"); - Database index(""); + Database index(""); populate_index(index); remove_keys(index); @@ -88,7 +93,7 @@ void test_1() void test_2() { print("Test 2\n"); - Database index(""); + Database index(""); populate_index(index); remove_values(index); @@ -101,7 +106,7 @@ void test_2() void test_3() { print("Test 3\n"); - Database index("test.idx"); + Database index("test.idx"); populate_index(index); remove_values(index); @@ -114,7 +119,7 @@ void test_3() void test_4() { print("Test 4\n"); - Database index("test.idx"); + Database index("test.idx"); index.load(); print_index(index); @@ -126,7 +131,7 @@ void test_4() void test_5() { print("Test 5\n"); - Database index(""); + Database index(""); print("index[nokey].size() = "); try { print("%u\n", index.find("nokey").values.size());