//-< UNIDB.CXX >-----------------------------------------------------*--------* // GOODS Version 1.0 (c) 1997 GARRET * ? * // (Generic Object Oriented Database System) * /\| * // * / \ * // Created: 28-Oct-97 K.A. Knizhnik * / [] \ * // Last update: 28-Oct-97 K.A. Knizhnik * GARRET * //-------------------------------------------------------------------*--------* // Example of GOODS application: "university database" //-------------------------------------------------------------------*--------* #include "goods.h" #include "dbscls.h" USE_GOODS_NAMESPACE class professor : public set_owner { friend class university; protected: ref professors; ref department; char name[1]; professor(const char* name, const char* department); public: void print() const; void print_brief() const; void print_students() const; void add_student(ref s) { put_last(s); } void rem_student(ref s) { remove(s); } static ref create(const char* name, const char* department); METACLASS_DECLARATIONS(professor, set_owner); }; class student : public object { friend class university; protected: ref advisor; ref students; ref group; ref diplom; char name[1]; student(const char* name, const char* diplom, ref advisor); public: void print() const; void print_advisor() const; static ref create(const char* name, const char* diplom, ref advisor); METACLASS_DECLARATIONS(student, object); }; class university : public object { protected: enum { students_storage_id, professors_storage_id }; ref students; ref professors; ref find_professor(const char* name) const; ref find_student(const char* name) const; public: int get_number_of_students() const { return students->n_members; } int get_number_of_professors() const { return professors->n_members; } void print_student(const char* name) const; void print_students() const; void print_professor(const char* name) const; void print_professors() const; void print_group(const char* prof_name) const; void print_advisor(const char* stud_name) const; void add_student(const char* name, const char* advisor, const char* diplom) const; void rem_student(const char* name) const; void transfer_student(const char* name, char* new_advisor) const; void add_professor(const char* name, const char* department) const; void rem_professor(const char* name) const; void initialize() const; university(database const* db); void notify(event& e) const; METACLASS_DECLARATIONS(university, object); }; class application { protected: mutex cs; database db; ref uni; boolean session_opened; event term_event; event modification_event; static void task_proc start_update_process(void* arg); void print_menu(); void dialogue(); void update(); public: int main(); }; //--- End of declaration part --------------------------------------------- static void output_student(ref mbr, void const*) { ref s = mbr->obj; s->print(); } static void output_professor(ref mbr, void const*) { ref p = mbr->obj; p->print_brief(); } // // Implementation of "professor" methods // professor::professor(const char* name, const char* department) : set_owner(self_class, this, strlen(name)+1) { professors = set_member::create(this, name); this->department = String::create(department); strcpy(this->name, name); } void professor::print() const { console::output("Pr. %s\n", name); console::output("Department: "); department->print(); console::output("\nNumber of students: %d\n", n_members); } void professor::print_brief() const { console::output("Pr. %s, number of students %d\n", name, n_members); } void professor::print_students() const { iterate(output_student); } ref professor::create(const char* name, const char* department) { return new (self_class, strlen(name)+1) professor(name, department); } field_descriptor& professor::describe_components() { return FIELD(professors), FIELD(department), VARYING(name); } REGISTER(professor, set_owner, pessimistic_repeatable_read_scheme); // // Implementation of "student" methods // student::student(const char* name, const char* diplom, ref advisor) : object(self_class, strlen(name)+1) { strcpy(this->name, name); students = set_member::create(this, name); group = set_member::create(this, name); this->diplom = String::create(diplom); this->advisor = advisor; modify(advisor)->add_student(group); } void student::print() const { console::output("%s: ", name); diplom->print(); console::output("\n"); } void student::print_advisor() const { advisor->print(); } ref student::create(const char* name, const char* diplom, ref advisor) { return new (self_class, strlen(name)+1) student(name, diplom, advisor); } field_descriptor& student::describe_components() { return FIELD(advisor), FIELD(students), FIELD(group), FIELD(diplom), VARYING(name); } REGISTER(student, object, pessimistic_repeatable_read_scheme); // // Implementation of "university" methods // ref university::find_professor(const char* name) const { ref mbr = professors->find(name); if (!mbr.is_nil()) { return mbr->obj; } else { return NULL; } } ref university::find_student(const char* name) const { ref mbr = students->find(name); if (!mbr.is_nil()) { return mbr->obj; } else { return NULL; } } void university::print_student(const char* name) const { ref s = find_student(name); if (s == NULL) { console::output("No such student: %s\n", name); } else { s->print(); } } void university::print_students() const { students->iterate(output_student); } void university::print_professor(const char* name) const { ref p = find_professor(name); if (p == NULL) { console::output("No such professor: %s\n", name); } else { p->print(); } } void university::print_professors() const { professors->iterate(output_professor); } void university::add_student(const char* name, const char* advisor, const char* diplom) const { if (!find_student(name).is_nil()) { console::output("Student with such name already exists\n"); } else { ref p = find_professor(advisor); if (p == NULL) { console::output("No such professor: %s\n", advisor); } else { ref s = student::create(name, diplom, p); modify(students)->insert(s->students); s->cluster_with(students); } } } void university::rem_student(const char* name) const { ref s = find_student(name); if (s == NULL) { console::output("No such student: %s\n", name); } else { modify(s->advisor)->rem_student(s->group); modify(students)->remove(s->students); } } void university::transfer_student(const char* name, char* new_advisor) const { ref s = find_student(name); if (s == NULL) { console::output("No such student: %s\n", name); } else { ref p = find_professor(new_advisor); if (p == NULL) { console::output("No such professor: %s\n", new_advisor); } else { modify(s->advisor)->rem_student(s->group); modify(p)->add_student(s->group); modify(s)->advisor = p; } } } void university::add_professor(const char* name, const char* department) const { if (!find_professor(name).is_nil()) { console::output("Professor with such name already exists\n"); } else { ref p = professor::create(name, department); modify(professors)->insert(p->professors); p->cluster_with(professors); } } void university::rem_professor(const char* name) const { ref p = find_professor(name); if (p == NULL) { console::output("No such professor: %s\n", name); } else { if (p->n_members > 0) { console::output("Pr. %s cann't be deleted as he is advisor" " for %d student(s)\n", name, p->n_members); } else { modify(professors)->remove(p->professors); } } } void university::print_group(const char* prof_name) const { ref p = find_professor(prof_name); if (p == NULL) { console::output("No such professor: %s\n", prof_name); } else { p->iterate(output_student); } } void university::print_advisor(const char* stud_name) const { ref s = find_student(stud_name); if (s == NULL) { console::output("No such student: %s\n", stud_name); } else { s->advisor->print(); } } void university::initialize() const { if (is_abstract_root()) { ref root = this; modify(root)->become(NEW university(get_database())); } // Only "university" root object need to be exclusivly locked object::default_mop = &optimistic_scheme; } university::university(database const* db) : object(self_class) { students = B_tree::create(NULL); students->attach_to_storage(db, students_storage_id); professors = B_tree::create(NULL); professors->attach_to_storage(db, professors_storage_id); } void university::notify(event& e) const { students->signal_on_modification(e); professors->signal_on_modification(e); } field_descriptor& university::describe_components() { return FIELD(students), FIELD(professors); } REGISTER(university, object, pessimistic_exclusive_scheme); // // Implementation of "application" class // static void input(char* prompt, char* buf, size_t buf_size) { char* p; do { console::output(prompt); *buf = '\0'; console::input(buf, buf_size); p = buf + strlen(buf); } while (p <= buf+1); if (*(p-1) == '\n') { *--p = '\0'; } } void task_proc application::start_update_process(void* arg) { ((application*)arg)->update(); } void application::print_menu() { console::output("\n\n\n\n\n\n\n\n\n\ University database\n\ Total %d student, %d professors\n\ Menu:\n\ a) Add new student\n\ b) Add new professor\n\ c) Print information about student\n\ d) Print information about professor\n\ e) Print list of all students\n\ f) Print list of all professors\n\ g) Remove student\n\ i) Remove professor\n\ j) Transfer student\n\ k) Print advisor of student\n\ l) Print students of professor\n\ q) Quit\n", uni->get_number_of_students(), uni->get_number_of_professors()); } void application::update() { while (session_opened) { modification_event.wait(); cs.enter(); if (session_opened) { modification_event.reset(); uni->notify(modification_event); console::output("\b\n"); print_menu(); } cs.leave(); } term_event.signal(); } void application::dialogue() { char buf[3][256]; uni->notify(modification_event); task::create(start_update_process, this); while (True) { print_menu(); input(">> ", buf[0], sizeof buf[0]); cs.enter(); switch (toupper(*buf[0])) { case 'A': input("New student name: ", buf[0], sizeof buf[0]); input("Advisor name: ", buf[1], sizeof buf[1]); input("Diplom work: ", buf[2], sizeof buf[2]); uni->add_student(buf[0], buf[1], buf[2]); break; case 'B': input("New professor name: ", buf[0], sizeof buf[0]); input("Department: ", buf[1], sizeof buf[1]); uni->add_professor(buf[0], buf[1]); break; case 'C': input("Student name: ", buf[0], sizeof buf[0]); uni->print_student(buf[0]); break; case 'D': input("Professor name: ", buf[0], sizeof buf[0]); uni->print_professor(buf[0]); break; case 'E': uni->print_students(); break; case 'F': uni->print_professors(); break; case 'G': input("Student name to remove: ", buf[0], sizeof buf[0]); uni->rem_student(buf[0]); break; case 'I': input("Professor name to remove: ", buf[0], sizeof buf[0]); uni->rem_professor(buf[0]); break; case 'J': input("Student name to transfer: ", buf[0], sizeof buf[0]); input("New advisor name: ", buf[1], sizeof buf[1]); uni->transfer_student(buf[0], buf[1]); break; case 'K': input("Student name: ", buf[0], sizeof buf[0]); uni->print_advisor(buf[0]); break; case 'L': input("Advisor name: ", buf[0], sizeof buf[0]); uni->print_group(buf[0]); break; case 'Q': session_opened = False; cs.leave(); modification_event.signal(); term_event.wait(); return; default: cs.leave(); continue; } cs.leave(); console::output("<<< Press ENTER to continue >>>"); console::input(buf[0], sizeof buf[0]); } } int application::main() { database db; task::initialize(task::normal_stack); if (db.open("unidb.cfg")) { session_opened = True; db.get_root(uni); uni->initialize(); dialogue(); db.close(); console::output("Session is closed\n"); return EXIT_SUCCESS; } else { console::output("Failed to open database\n"); return EXIT_FAILURE; } } int main() { application app; return app.main(); } //-- End of university database example --------------------------------------