static bool wallet_eq(const struct wallet *wlt1, const struct wallet *wlt2) { unsigned int i; if (wlt1->version != wlt2->version) return false; if (wlt1->chain != wlt2->chain) return false; if (wlt1->keys->len != wlt2->keys->len) return false; for (i = 0; i < wlt1->keys->len; i++) { const struct bp_key *key1, *key2; key1 = parr_idx(wlt1->keys, i); key2 = parr_idx(wlt2->keys, i); if (!key_eq(key1, key2)) return false; } return true; }
void basic_test() { using value_type = std::pair<int, int>; const size_t value_size = sizeof(value_type); const size_t n_values = 6000; const size_t n_tests = 3000; // make sure all changes will be buffered (*) const size_t buffer_size = n_values * (value_size + sizeof(int*)); const size_t mem_to_sort = 32 * 1024 * 1024; const size_t subblock_raw_size = 4 * 1024; const size_t block_size = 4; using unordered_map = stxxl::unordered_map<int, int, hash_int, cmp, subblock_raw_size, block_size>; using iterator = unordered_map::iterator; using const_iterator = unordered_map::const_iterator; foxxll::stats_data stats_begin; unordered_map map; map.max_buffer_size(buffer_size); const unordered_map& cmap = map; // generate random values std::vector<value_type> values1(n_values); std::vector<value_type> values2(n_values); std::vector<value_type> values3(n_values / 2); { auto broadcast = [](uint64_t x) -> value_type { return { x, x }; }; random_fill_vector(values1, broadcast); random_fill_vector(values2, broadcast); random_fill_vector(values3, broadcast); } // --- initial import std::cout << "Initial import..."; stats_begin = *foxxll::stats::get_instance(); die_unless(map.begin() == map.end()); map.insert(values1.begin(), values1.end(), mem_to_sort); die_unless(map.begin() != map.end()); die_unless(map.size() == n_values); std::cout << "passed" << std::endl; LOG1 << foxxll::stats_data(*foxxll::stats::get_instance()) - stats_begin; // (*) all these values are stored in external memory; the remaining // changes will be buffered in internal memory // --- insert: new (from values2) and existing (from values1) values, with // --- and without checking std::cout << "Insert..."; stats_begin = *foxxll::stats::get_instance(); for (size_t i = 0; i < n_values / 2; i++) { // new without checking map.insert_oblivious(values2[2 * i]); // new with checking std::pair<iterator, bool> res = map.insert(values2[2 * i + 1]); die_unless(res.second && (*(res.first)).first == values2[2 * i + 1].first); // existing without checking map.insert_oblivious(values1[2 * i]); // exiting with checking res = map.insert(values1[2 * i + 1]); die_unless(!res.second && (*(res.first)).first == values1[2 * i + 1].first); } die_unless(map.size() == 2 * n_values); std::cout << "passed" << std::endl; LOG1 << foxxll::stats_data(*foxxll::stats::get_instance()) - stats_begin; // "old" values are stored in external memory, "new" values are stored in // internal memory // --- find: existing (from external and internal memory) and non-existing // --- values std::cout << "Find..."; stats_begin = *foxxll::stats::get_instance(); std::random_shuffle(values1.begin(), values1.end()); std::random_shuffle(values2.begin(), values2.end()); for (size_t i = 0; i < n_tests; i++) { die_unless(cmap.find(values1[i].first) != cmap.end()); die_unless(cmap.find(values2[i].first) != cmap.end()); die_unless(cmap.find(values3[i].first) == cmap.end()); } std::cout << "passed" << std::endl; LOG1 << foxxll::stats_data(*foxxll::stats::get_instance()) - stats_begin; // --- insert with overwriting std::cout << "Insert with overwriting..."; stats_begin = *foxxll::stats::get_instance(); std::random_shuffle(values1.begin(), values1.end()); std::random_shuffle(values2.begin(), values2.end()); for (size_t i = 0; i < n_tests; i++) { value_type value1 = values1[i]; // in external memory value1.second++; map.insert_oblivious(value1); value_type value2 = values2[i]; // in internal memory value2.second++; map.insert_oblivious(value2); } // now check die_unless(map.size() == 2 * n_values); // nothing added, nothing removed for (size_t i = 0; i < n_tests; i++) { const_iterator it1 = cmap.find(values1[i].first); const_iterator it2 = cmap.find(values2[i].first); die_unless((*it1).second == values1[i].second + 1); die_unless((*it2).second == values2[i].second + 1); } std::cout << "passed" << std::endl; LOG1 << foxxll::stats_data(*foxxll::stats::get_instance()) - stats_begin; // --- erase: existing and non-existing values, with and without checking std::cout << "Erase..."; stats_begin = *foxxll::stats::get_instance(); std::random_shuffle(values1.begin(), values1.end()); std::random_shuffle(values2.begin(), values2.end()); std::random_shuffle(values3.begin(), values3.end()); for (size_t i = 0; i < n_tests / 2; i++) { // external // existing without checking map.erase_oblivious(values1[2 * i].first); // existing with checking die_unless(map.erase(values1[2 * i + 1].first) == 1); } for (size_t i = 0; i < n_tests / 2; i++) { // internal // existing without checking map.erase_oblivious(values2[2 * i].first); // existing with checking die_unless(map.erase(values2[2 * i + 1].first) == 1); // non-existing without checking map.erase_oblivious(values3[i].first); // non-existing with checking } die_unless(map.size() == 2 * n_values - 2 * n_tests); std::cout << "passed" << std::endl; LOG1 << foxxll::stats_data(*foxxll::stats::get_instance()) - stats_begin; map.clear(); die_unless(map.size() == 0); // --- find and manipulate values by []-operator // make sure there are some values in our unordered_map: externally // [0..n/2) and internally [n/2..n) from values1 std::cout << "[ ]-operator..."; stats_begin = *foxxll::stats::get_instance(); map.insert(values1.begin(), values1.begin() + n_values / 2, mem_to_sort); for (size_t i = n_values / 2; i < n_values; i++) { map.insert_oblivious(values1[i]); } // lookup of existing values die_unless(map[values1[5].first] == values1[5].second); // external die_unless(map[values1[n_values / 2 + 5].first] == values1[n_values / 2 + 5].second); // internal // manipulate existing values ++(map[values1[7].first]); ++(map[values1[n_values / 2 + 7].first]); { const_iterator cit1 = cmap.find(values1[7].first); die_unless((*cit1).second == (*cit1).first + 1); const_iterator cit2 = cmap.find(values1[n_values / 2 + 7].first); die_unless((*cit2).second == (*cit2).first + 1); } // lookup of non-existing values die_unless(map[values2[5].first] == unordered_map::mapped_type()); // assignment of non-existing values map[values2[7].first] = values2[7].second; { const_iterator cit = cmap.find(values2[7].first); die_unless((*cit).first == values2[7].second); } die_unless(map.size() == n_values + 2); std::cout << "passed" << std::endl; LOG1 << foxxll::stats_data(*foxxll::stats::get_instance()) - stats_begin; map.clear(); die_unless(map.size() == 0); // --- additional bulk insert test std::cout << "additional bulk-insert..."; stats_begin = *foxxll::stats::get_instance(); map.insert(values1.begin(), values1.begin() + n_values / 2, mem_to_sort); map.insert(values1.begin() + n_values / 2, values1.end(), mem_to_sort); die_unless(map.size() == n_values); // lookup some random values std::random_shuffle(values1.begin(), values1.end()); for (size_t i = 0; i < n_tests; i++) die_unless(cmap.find(values1[i].first) != cmap.end()); std::cout << "passed" << std::endl; LOG1 << foxxll::stats_data(*foxxll::stats::get_instance()) - stats_begin; // --- test equality predicate unordered_map::key_equal key_eq = map.key_eq(); die_unless(key_eq(42, 42)); die_unless(!key_eq(42, 6 * 9)); std::cout << "\nAll tests passed" << std::endl; map.buffer_size(); }
Enum_Associators_Status Link_Provider::enum_associators( const Instance* instance, const String& result_class, const String& role, const String& result_role, Enum_Associators_Handler<Instance>* handler) { Auto_Mutex am(resource.mutex); // // This function implements the associators operation across the following // class. // // [Association] // class Link // { // [Key] Employee REF Emp; // [Key] Manager REF Mgr; // }; // // The instance parameter refers to the "source" instance of the // association. This function creates "result" instances and passes // them to the handler. If the source is a manager, the results will // be employees. If the source is an employee, the result will be // a single manager. // // // Client use cases: // // $ cimcli a Manager.Id=1001 // $ cimcli a Employee.Id=4001 // // Case 1: the source is a manager; results are employees. Manager* manager = cast<Manager*>(instance); if (manager) { // The result class must be Employee (or empty). if (result_class.size() && result_class != "Employee") return ENUM_ASSOCIATORS_FAILED; // [Source] role must be "Mgr" or empty. if (!role.empty() && !eqi(role, "Mgr")) return ENUM_ASSOCIATORS_FAILED; // Result_role must be "Emp" or empty. if (!result_role.empty() && !eqi(result_role, "Emp")) return ENUM_ASSOCIATORS_FAILED; // We only have one manager in this module. if (manager->Id.value == 1001) { for (size_t i = 0; i < resource.employees.size(); i++) handler->handle(resource.employees[i]->clone()); return ENUM_ASSOCIATORS_OK; } return ENUM_ASSOCIATORS_FAILED; } // Case 2: the source is an employee; result is a manager. Employee* employee = cast<Employee*>(instance); if (employee) { // The result class must be Manager (or empty). if (result_class.size() && result_class != "Manager") return ENUM_ASSOCIATORS_FAILED; // [Source] role must be "Emp" or empty. if (!role.empty() && !eqi(role, "Emp")) return ENUM_ASSOCIATORS_FAILED; // Result_role must be "Mgr" or empty. if (!result_role.empty() && !eqi(result_role, "Mgr")) return ENUM_ASSOCIATORS_FAILED; // Find this employee and send result instance. for (size_t i = 0; i < resource.employees.size(); i++) { if (key_eq(resource.employees[i], employee)) { handler->handle(resource.manager->clone()); return ENUM_ASSOCIATORS_OK; } } return ENUM_ASSOCIATORS_FAILED; } return ENUM_ASSOCIATORS_FAILED; }