diff --git a/Makefile b/Makefile index 5046a8c..02b621a 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ SOURCE=\ metadata.cc PROGRAM_SOURCE=\ - block_t.cc + block_t.cc \ + space_map_t.cc OBJECTS=$(subst .cc,.o,$(SOURCE)) CPPFLAGS=-Wall -std=c++0x @@ -25,5 +26,8 @@ multisnap_display: $(OBJECTS) main.o block_t: block_t.o g++ -o $@ $+ $(LIBS) +space_map_t: space_map_t.o + g++ -o $@ $+ $(LIBS) + include $(subst .cc,.d,$(SOURCE)) include $(subst .cc,.d,$(PROGRAM_SOURCE)) \ No newline at end of file diff --git a/core-map.h b/core_map.h similarity index 66% rename from core-map.h rename to core_map.h index a759d2d..fcdf374 100644 --- a/core-map.h +++ b/core_map.h @@ -9,15 +9,16 @@ namespace persistent_data { class core_map : public space_map { public: core_map(block_address nr_blocks) - : counts_(nr_blocks, 0) { + : counts_(nr_blocks, 0), + nr_free_(nr_blocks) { } block_address get_nr_blocks() const { - counts_.size(); + return counts_.size(); } block_address get_nr_free() const { - nr_free_; + return nr_free_; } ref_t get_count(block_address b) const { @@ -25,34 +26,50 @@ namespace persistent_data { } void set_count(block_address b, ref_t c) { + if (counts_[b] == 0 && c > 0) + nr_free_--; + + else if (counts_[b] > 0 && c == 0) + nr_free_++; + counts_[b] = c; } void commit() { } - void inc_block(block_address b) { + void inc(block_address b) { + if (counts_[b] == 0) + nr_free_--; + counts_[b]++; } - void dec_block(block_address b) { + void dec(block_address b) { counts_[b]--; + + if (counts_[b] == 0) + nr_free_++; } block_address new_block() { for (block_address i = 0; i < counts_.size(); i++) if (counts_[i] == 0) { counts_[i] = 1; + nr_free_--; return i; } + + throw std::runtime_error("no space"); } bool count_possibly_greater_than_one(block_address b) const { - return counts_[i] > 1; + return counts_[b] > 1; } private: std::vector counts_; + unsigned nr_free_; }; } diff --git a/space_map.h b/space_map.h index f66644c..e1f9478 100644 --- a/space_map.h +++ b/space_map.h @@ -22,8 +22,8 @@ namespace persistent_data { virtual void set_count(block_address b, ref_t c) = 0; virtual void commit() = 0; - virtual void inc_block(block_address b) = 0; - virtual void dec_block(block_address b) = 0; + virtual void inc(block_address b) = 0; + virtual void dec(block_address b) = 0; virtual block_address new_block() = 0; virtual bool count_possibly_greater_than_one(block_address b) const = 0; diff --git a/space_map_t.cc b/space_map_t.cc new file mode 100644 index 0000000..3024629 --- /dev/null +++ b/space_map_t.cc @@ -0,0 +1,83 @@ +#include "space_map.h" +#include "core_map.h" + +#define BOOST_TEST_MODULE SpaceMapTests +#include + +using namespace std; +using namespace boost; + +unsigned const NR_BLOCKS = 1024; + +//---------------------------------------------------------------- + +namespace { +} + +//---------------------------------------------------------------- + +BOOST_AUTO_TEST_CASE(test_get_nr_blocks) +{ + core_map sm(NR_BLOCKS); + BOOST_CHECK_EQUAL(sm.get_nr_blocks(), NR_BLOCKS); +} + +BOOST_AUTO_TEST_CASE(test_get_nr_free) +{ + core_map sm(NR_BLOCKS); + BOOST_CHECK_EQUAL(sm.get_nr_free(), NR_BLOCKS); + + for (unsigned i = 0; i < NR_BLOCKS; i++) { + sm.new_block(); + BOOST_CHECK_EQUAL(sm.get_nr_free(), NR_BLOCKS - i - 1); + } + + for (unsigned i = 0; i < NR_BLOCKS; i++) { + sm.dec(i); + BOOST_CHECK_EQUAL(sm.get_nr_free(), i + 1); + } +} + +BOOST_AUTO_TEST_CASE(test_throws_no_space) +{ + core_map sm(NR_BLOCKS); + for (unsigned i = 0; i < NR_BLOCKS; i++) + sm.new_block(); + + BOOST_CHECK_THROW(sm.new_block(), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_inc_and_dec) +{ + core_map sm(NR_BLOCKS); + block_address b = 63; + + for (unsigned i = 0; i < 50; i++) { + BOOST_CHECK_EQUAL(sm.get_count(b), i); + sm.inc(b); + } + + for (unsigned i = 50; i > 0; i--) { + BOOST_CHECK_EQUAL(sm.get_count(b), i); + sm.dec(b); + } +} + +BOOST_AUTO_TEST_CASE(test_not_allocated_twice) +{ + core_map sm(NR_BLOCKS); + block_address b = sm.new_block(); + + try { + for (;;) + BOOST_CHECK(sm.new_block() != b); + } catch (...) { + } +} + +BOOST_AUTO_TEST_CASE(test_set_count) +{ + core_map sm(NR_BLOCKS); + sm.set_count(43, 5); + BOOST_CHECK_EQUAL(sm.get_count(43), 5); +}