// Consistency check. int test4() { Cache cache; const string filename = "testfile"; const int64_t size = 100; const int64_t timestamp = 101; cache.update(filename, timestamp, size); int* val = new int(1); cache.insert((char*)val, filename, 0, sizeof(int)); *val = 2; cache.insert((char*)val, filename, 0, sizeof(int)); int readval = 0; cache.read(filename, (char*)&readval, 0, sizeof(int)); assert(readval == *val); *val = 3; cache.insert((char*)val, filename, 0, sizeof(int)); cache.read(filename, (char*)&readval, 0, sizeof(int)); assert(readval == *val); cout << "consistency testing passed.\n"; return 0; }
// Test IO data cache int test2() { Cache cache; cache.setCacheBlockSize(200); const string filename = "testfile"; const int64_t size = 100; const int64_t timestamp = 101; cache.update(filename, timestamp, size); int64_t offset = 200; int64_t block = 201; char* buf = new char[block]; *buf = 'z'; cache.insert(buf, filename, offset, block); char data[block]; int64_t result = cache.read(filename, data, offset, block); assert((result == block) && (*data == 'z')); result = cache.read(filename, data, offset, block + 1); assert(result == block); // Test large block that cover multiple cache units. int64_t off2 = 900; int64_t block2 = 901; char* large_buf = new char[block2]; cache.insert(large_buf, filename, off2, block2); char data2[block2]; result = cache.read(filename, data2, off2, block2); assert(result == block2); // Read partial data. result = cache.read(filename, data2, off2 + 50, block2 - 100); assert(result == block2 - 100); // Test maximu cache size. cache.setMaxCacheSize(1000); // Insert overlapping buffer block. large_buf = new char[block2]; cache.insert(large_buf, filename, off2, block2); large_buf = new char[block2]; cache.insert(large_buf, filename, off2, block2); // Cache should constain most recent block only, assert(cache.getCacheSize() == 901); cout << "IO cache check passed.\n"; return 0; }
// performance and memory leak testing. int test3(const int64_t& max, int unit, int block) { Cache cache; cache.setMaxCacheSize(max); cache.setCacheBlockSize(unit); const string filename = "testfile"; const int64_t size = unit * 100; const int64_t timestamp = 101; cache.update(filename, timestamp, size); for (int i = 0; i < 100; ++ i) { char* buf = new char[block]; cache.insert(buf, filename, block * i, block); } assert(cache.getCacheSize() <= max); char* buf = new char[unit]; for (int i = 0; i < 100; ++ i) { cache.read(filename, buf, block * i, block); } cout << "performance and memory leak testing passed.\n"; return 0; }
block_activity(uint32_t n_insert, Cache& c) : reads() { std::vector<uint256> inserts; inserts.resize(n_insert); reads.reserve(n_insert / 2); for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)inserts[i].begin(); for (uint8_t j = 0; j < 8; ++j) *(ptr++) = insecure_rand.rand32(); } for (uint32_t i = 0; i < n_insert / 4; ++i) reads.push_back(inserts[i]); for (uint32_t i = n_insert - (n_insert / 4); i < n_insert; ++i) reads.push_back(inserts[i]); for (auto h : inserts) c.insert(h); }
void run () { beast::manual_clock <std::chrono::seconds> clock; clock.set (0); typedef std::string Key; typedef KeyCache <Key> Cache; // Insert an item, retrieve it, and age it so it gets purged. { Cache c ("test", clock, 1, 2); expect (c.size () == 0); expect (c.insert ("one")); expect (! c.insert ("one")); expect (c.size () == 1); expect (c.exists ("one")); expect (c.touch_if_exists ("one")); ++clock; c.sweep (); expect (c.size () == 1); expect (c.exists ("one")); ++clock; c.sweep (); expect (c.size () == 0); expect (! c.exists ("one")); expect (! c.touch_if_exists ("one")); } // Insert two items, have one expire { Cache c ("test", clock, 2, 2); expect (c.insert ("one")); expect (c.size () == 1); expect (c.insert ("two")); expect (c.size () == 2); ++clock; c.sweep (); expect (c.size () == 2); expect (c.touch_if_exists ("two")); ++clock; c.sweep (); expect (c.size () == 1); expect (c.exists ("two")); } // Insert three items (1 over limit), sweep { Cache c ("test", clock, 2, 3); expect (c.insert ("one")); ++clock; expect (c.insert ("two")); ++clock; expect (c.insert ("three")); ++clock; expect (c.size () == 3); c.sweep (); expect (c.size () < 3); } }
void write(Cache &cache, const FileTypeId &index, const IApplications::LinkedList &list) { cache.insert(index, LinkedList(list)); }
void run () { beast::Journal const j; beast::manual_clock <std::chrono::steady_clock> clock; clock.set (0); typedef int Key; typedef std::string Value; typedef TaggedCache <Key, Value> Cache; Cache c ("test", 1, 1, clock, j); // Insert an item, retrieve it, and age it so it gets purged. { expect (c.getCacheSize() == 0); expect (c.getTrackSize() == 0); expect (! c.insert (1, "one")); expect (c.getCacheSize() == 1); expect (c.getTrackSize() == 1); { std::string s; expect (c.retrieve (1, s)); expect (s == "one"); } ++clock; c.sweep (); expect (c.getCacheSize () == 0); expect (c.getTrackSize () == 0); } // Insert an item, maintain a strong pointer, age it, and // verify that the entry still exists. { expect (! c.insert (2, "two")); expect (c.getCacheSize() == 1); expect (c.getTrackSize() == 1); { Cache::mapped_ptr p (c.fetch (2)); expect (p != nullptr); ++clock; c.sweep (); expect (c.getCacheSize() == 0); expect (c.getTrackSize() == 1); } // Make sure its gone now that our reference is gone ++clock; c.sweep (); expect (c.getCacheSize() == 0); expect (c.getTrackSize() == 0); } // Insert the same key/value pair and make sure we get the same result { expect (! c.insert (3, "three")); { Cache::mapped_ptr const p1 (c.fetch (3)); Cache::mapped_ptr p2 (std::make_shared <Value> ("three")); c.canonicalize (3, p2); expect (p1.get() == p2.get()); } ++clock; c.sweep (); expect (c.getCacheSize() == 0); expect (c.getTrackSize() == 0); } // Put an object in but keep a strong pointer to it, advance the clock a lot, // then canonicalize a new object with the same key, make sure you get the // original object. { // Put an object in expect (! c.insert (4, "four")); expect (c.getCacheSize() == 1); expect (c.getTrackSize() == 1); { // Keep a strong pointer to it Cache::mapped_ptr p1 (c.fetch (4)); expect (p1 != nullptr); expect (c.getCacheSize() == 1); expect (c.getTrackSize() == 1); // Advance the clock a lot ++clock; c.sweep (); expect (c.getCacheSize() == 0); expect (c.getTrackSize() == 1); // Canonicalize a new object with the same key Cache::mapped_ptr p2 (std::make_shared <std::string> ("four")); expect (c.canonicalize (4, p2, false)); expect (c.getCacheSize() == 1); expect (c.getTrackSize() == 1); // Make sure we get the original object expect (p1.get() == p2.get()); } ++clock; c.sweep (); expect (c.getCacheSize() == 0); expect (c.getTrackSize() == 0); } }
void run () { TestStopwatch clock; clock.set (0); using Key = std::string; using Cache = KeyCache <Key>; // Insert an item, retrieve it, and age it so it gets purged. { Cache c ("test", clock, 1, 2); BEAST_EXPECT(c.size () == 0); BEAST_EXPECT(c.insert ("one")); BEAST_EXPECT(! c.insert ("one")); BEAST_EXPECT(c.size () == 1); BEAST_EXPECT(c.exists ("one")); BEAST_EXPECT(c.touch_if_exists ("one")); ++clock; c.sweep (); BEAST_EXPECT(c.size () == 1); BEAST_EXPECT(c.exists ("one")); ++clock; c.sweep (); BEAST_EXPECT(c.size () == 0); BEAST_EXPECT(! c.exists ("one")); BEAST_EXPECT(! c.touch_if_exists ("one")); } // Insert two items, have one expire { Cache c ("test", clock, 2, 2); BEAST_EXPECT(c.insert ("one")); BEAST_EXPECT(c.size () == 1); BEAST_EXPECT(c.insert ("two")); BEAST_EXPECT(c.size () == 2); ++clock; c.sweep (); BEAST_EXPECT(c.size () == 2); BEAST_EXPECT(c.touch_if_exists ("two")); ++clock; c.sweep (); BEAST_EXPECT(c.size () == 1); BEAST_EXPECT(c.exists ("two")); } // Insert three items (1 over limit), sweep { Cache c ("test", clock, 2, 3); BEAST_EXPECT(c.insert ("one")); ++clock; BEAST_EXPECT(c.insert ("two")); ++clock; BEAST_EXPECT(c.insert ("three")); ++clock; BEAST_EXPECT(c.size () == 3); c.sweep (); BEAST_EXPECT(c.size () < 3); } }