//-< TSTBTREE.CXX >--------------------------------------------------*--------* // GOODS Version 1.0 (c) 1997 GARRET * ? * // (Generic Object Oriented Database System) * /\| * // * / \ * // Created: 7-Jun-97 K.A. Knizhnik * / [] \ * // Last update: 17-Oct-97 K.A. Knizhnik * GARRET * //-------------------------------------------------------------------*--------* // Test program for measuring GOODS performance //-------------------------------------------------------------------*--------* #include "goods.h" #include "dbscls.h" USE_GOODS_NAMESPACE #define N_RECORDS 100 #define N_READS 10 #define MAX_KEY_LEN 28 #define MAX_DATA 1024 #define N_TREES 4 #define SCATTER_OBJECTS 1 class record : public object { public: ref key; char data[1]; static ref create(const char* key_str, const char* data_str) { size_t len = strlen(data_str) + 1; return new (self_class, len) record(key_str, data_str, len); } boolean check(char* expected_key, int expected_data_len) const { int i; if (key->compare(expected_key) != 0) { return False; } for (i = 0; i < expected_data_len; i++) { if (data[i] != ' ') return False; } return data[i] == '\0'; } METACLASS_DECLARATIONS(record, object); protected: record(const char* key_str, const char* data_str, size_t data_len) : object(self_class, data_len) { key = set_member::create(this, key_str); strcpy(data, data_str); } }; class container : public B_tree { public: void insert(const char* key_str, const char* data_str) { ref rec = record::create(key_str, data_str); B_tree::insert(rec->key); #ifdef SCATTER_OBJECTS database const* db = get_database(); rec->attach_to_storage(db, rand() % db->get_number_of_storages()); #endif } METACLASS_DECLARATIONS(container, B_tree); container() : B_tree(self_class) {} }; class wood : public object { public: ref tree[N_TREES]; void initialize() const { if (is_abstract_root()) { ref root = this; modify(root)->become(NEW wood(get_database())); } } METACLASS_DECLARATIONS(wood, object); protected: wood(database const* db) : object(self_class) { for (int i = 0; i < N_TREES; i++) { tree[i] = NEW container; tree[i]->attach_to_storage(db, i % db->get_number_of_storages()); } } }; field_descriptor& record::describe_components() { return FIELD(key), VARYING(data); } field_descriptor& container::describe_components() { return NO_FIELDS; } field_descriptor& wood::describe_components() { return ARRAY(tree); } REGISTER(wood, object, pessimistic_repeatable_read_scheme); REGISTER(container, B_tree, pessimistic_repeatable_read_scheme); REGISTER(record, object, pessimistic_repeatable_read_scheme); struct record_ref { char key[MAX_KEY_LEN]; int data_len; }; int main(int argc, char* argv[]) { char record_data[MAX_DATA]; record_ref* table = NEW record_ref[N_RECORDS]; database db; int i, j, id; task::initialize(task::normal_stack); if (argc < 2) { fputs("Usage: tstbtree \n", stderr); delete[] table; return 1; } id = atoi(argv[1]); srand(id+1997); memset(record_data, ' ', sizeof record_data); if (db.open("btree.cfg")) { ref root; db.get_root(root); root->initialize(); ref tree = root->tree[id % N_TREES]; for (i = 0; i < N_RECORDS; i++) { sprintf(table[i].key, "%x%x.%x", rand(), rand(), id); int record_len = rand() % (sizeof(record_data)-1); record_data[record_len] = '\0'; modify(tree)->insert(table[i].key, record_data); table[i].data_len = record_len; record_data[record_len] = ' '; } for (i = 1; i < N_READS; i++) { for (j = 0; j < N_RECORDS; j++) { ref mbr = tree->find(table[j].key); if (mbr == NULL) { console::error("Pass %d, %d: key %s not found\n", i, j, table[j].key); tree->ok(); } } } for (i = 0; i < N_RECORDS; i++) { ref mbr = tree->find(table[i].key); if (mbr == NULL) { console::error("Remove: key %s not found\n", table[i].key); } ref rec = mbr->obj; if (!rec->check(table[i].key, table[i].data_len)) { console::error("Record corrupted\n"); } modify(tree)->remove(mbr); } tree->ok(); db.close(); console::output("Process %d terminated\n", id); delete[] table; return EXIT_SUCCESS; } else { console::output("Failed to open database\n"); delete[] table; return EXIT_FAILURE; } }