Exemple #1
0
func TestCacheMapSimple(t *testing.T) {
	mocklog := make(chan *message.Message)

	// This service will run in its own goroutine
	// and send to mocklog any messages
	pipeline := message.NewNullPipeline(mocklog)
	pipeline.Start()
	defer pipeline.Close()

	c := NewCacheMap(8, 4096, pipeline.In)
	tests.Assert(t, c != nil)

	here := make(chan *message.Message)
	buffer := make([]byte, 4096)
	m := message.NewMsgPut()
	m.RetChan = here
	io := m.IoPkt()
	io.Buffer = buffer
	io.Address = 1
	m.Priv = c

	// First Put
	err := c.Put(m)
	tests.Assert(t, err == nil)

	logmsg := <-mocklog
	logio := logmsg.IoPkt()
	tests.Assert(t, m.Type == logmsg.Type)
	tests.Assert(t, logmsg.Priv.(*CacheMap) == c)
	tests.Assert(t, io.Blocks == logio.Blocks)
	tests.Assert(t, io.Address == logio.Address)
	tests.Assert(t, logio.LogBlock == 0)
	logmsg.Done()

	returnedmsg := <-here
	rio := returnedmsg.IoPkt()
	tests.Assert(t, m.Type == returnedmsg.Type)
	tests.Assert(t, returnedmsg.Priv.(*CacheMap) == c)
	tests.Assert(t, io.Blocks == rio.Blocks)
	tests.Assert(t, io.Address == rio.Address)
	tests.Assert(t, c.stats.insertions == 1)
	tests.Assert(t, returnedmsg.Err == nil)

	val, ok := c.addressmap[io.Address]
	tests.Assert(t, val == 0)
	tests.Assert(t, ok == true)

	// Check that we cannot resend this message
	err = c.Put(m)
	tests.Assert(t, err == message.ErrMessageUsed)

	// Insert again.  Should allocate
	// next block
	m = message.NewMsgPut()
	m.RetChan = here
	io = m.IoPkt()
	io.Buffer = buffer
	io.Address = 1
	m.Priv = c
	err = c.Put(m)
	tests.Assert(t, err == nil)

	logmsg = <-mocklog
	logio = logmsg.IoPkt()
	tests.Assert(t, logio.LogBlock == 1)
	logmsg.Done()

	returnedmsg = <-here
	rio = returnedmsg.IoPkt()
	tests.Assert(t, returnedmsg.Err == nil)
	tests.Assert(t, c.stats.insertions == 2)

	val, ok = c.addressmap[io.Address]
	tests.Assert(t, val == 1)
	tests.Assert(t, ok == true)

	// Send a Get
	mg := message.NewMsgGet()
	io = mg.IoPkt()
	io.Address = 1
	io.Buffer = buffer
	mg.RetChan = here

	hitmap, err := c.Get(mg)
	tests.Assert(t, err == nil)
	tests.Assert(t, hitmap.Hits == 1)
	tests.Assert(t, hitmap.Hitmap[0] == true)
	tests.Assert(t, hitmap.Hits == io.Blocks)

	logmsg = <-mocklog
	logio = logmsg.IoPkt()
	tests.Assert(t, logio.LogBlock == 1)
	logmsg.Done()

	returnedmsg = <-here
	io = returnedmsg.IoPkt()
	tests.Assert(t, returnedmsg.Err == nil)
	tests.Assert(t, c.stats.insertions == 2)
	tests.Assert(t, c.stats.readhits == 1)
	tests.Assert(t, c.stats.reads == 1)

	// Test we cannot send the same message
	hitmap, err = c.Get(mg)
	tests.Assert(t, err == message.ErrMessageUsed)
	tests.Assert(t, hitmap == nil)

	// Send Invalidate
	iopkt := &message.IoPkt{}
	iopkt.Address = 1
	iopkt.Blocks = 1
	c.Invalidate(iopkt)
	tests.Assert(t, c.stats.insertions == 2)
	tests.Assert(t, c.stats.readhits == 1)
	tests.Assert(t, c.stats.reads == 1)
	tests.Assert(t, c.stats.invalidations == 1)
	tests.Assert(t, c.stats.invalidatehits == 1)

	// Send Invalidate
	iopkt = &message.IoPkt{}
	iopkt.Address = 1
	iopkt.Blocks = 1
	c.Invalidate(iopkt)
	tests.Assert(t, c.stats.insertions == 2)
	tests.Assert(t, c.stats.readhits == 1)
	tests.Assert(t, c.stats.reads == 1)
	tests.Assert(t, c.stats.invalidations == 2)
	tests.Assert(t, c.stats.invalidatehits == 1)

	// Send a Get again, but it should not be there
	mg = message.NewMsgGet()
	io = mg.IoPkt()
	io.Address = 1
	io.Buffer = buffer
	mg.RetChan = here
	hitmap, err = c.Get(mg)
	tests.Assert(t, err == ErrNotFound)
	tests.Assert(t, hitmap == nil)
	tests.Assert(t, c.stats.insertions == 2)
	tests.Assert(t, c.stats.readhits == 1)
	tests.Assert(t, c.stats.reads == 2)
	tests.Assert(t, c.stats.invalidations == 2)
	tests.Assert(t, c.stats.invalidatehits == 1)

	// Check the stats
	stats := c.Stats()
	tests.Assert(t, stats.Readhits == c.stats.readhits)
	tests.Assert(t, stats.Invalidatehits == c.stats.invalidatehits)
	tests.Assert(t, stats.Reads == c.stats.reads)
	tests.Assert(t, stats.Evictions == c.stats.evictions)
	tests.Assert(t, stats.Invalidations == c.stats.invalidations)
	tests.Assert(t, stats.Insertions == c.stats.insertions)

	// Clear the stats
	c.StatsClear()
	tests.Assert(t, 0 == c.stats.readhits)
	tests.Assert(t, 0 == c.stats.invalidatehits)
	tests.Assert(t, 0 == c.stats.reads)
	tests.Assert(t, 0 == c.stats.evictions)
	tests.Assert(t, 0 == c.stats.invalidations)
	tests.Assert(t, 0 == c.stats.insertions)

	c.Close()
}
Exemple #2
0
// This test will check that the cache tries to place
// as many contigous blocks as possible. We will initialize
// the 8 slot cache with four slots, then remove slot 1 and 2
// to leave the following: [X__X____]
// When we put a message with 6 blocks the cache should be
// populated as follows:  [X45X01234]
//
// At the end, check multiblock Get()
//
func TestCacheMapMultiblock(t *testing.T) {
	// This service will run in its own goroutine
	// and send to mocklog any messages
	mocklog := make(chan *message.Message)
	pipe := message.NewNullPipeline(mocklog)
	pipe.Start()
	defer pipe.Close()

	c := NewCacheMap(8, 4096, pipe.In)
	tests.Assert(t, c != nil)

	here := make(chan *message.Message)
	buffer := make([]byte, 4096)

	// Initialize data in cache
	for i := uint64(0); i < 4; i++ {
		m := message.NewMsgPut()
		m.RetChan = here
		io := m.IoPkt()
		io.Buffer = buffer
		io.Address = i

		// First Put
		err := c.Put(m)
		tests.Assert(t, err == nil)
		retmsg := <-mocklog
		retmsg.Done()
		<-here
	}

	c.Invalidate(&message.IoPkt{Address: 1, Blocks: 2})
	tests.Assert(t, c.stats.insertions == 4)
	tests.Assert(t, c.stats.invalidatehits == 2)
	tests.Assert(t, c.bda.bds[0].used == true)
	tests.Assert(t, c.bda.bds[0].key == 0)
	tests.Assert(t, c.bda.bds[1].used == false)
	tests.Assert(t, c.bda.bds[2].used == false)
	tests.Assert(t, c.bda.bds[3].used == true)
	tests.Assert(t, c.bda.bds[3].key == 3)

	// Set the clock so they do not get erased
	c.bda.bds[0].clock_set = true
	c.bda.bds[3].clock_set = true

	// Insert multiblock
	largebuffer := make([]byte, 6*4096)
	m := message.NewMsgPut()
	m.RetChan = here
	io := m.IoPkt()
	io.Buffer = largebuffer
	io.Address = 10
	io.Blocks = 6

	// First Put
	err := c.Put(m)
	tests.Assert(t, err == nil)
	for i := uint32(0); i < io.Blocks; i++ {
		// Put send a message for each block
		retmsg := <-mocklog
		retmsg.Done()
	}
	<-here

	tests.Assert(t, c.stats.insertions == 10)
	tests.Assert(t, c.stats.invalidatehits == 2)

	// Check the two blocks left from before
	tests.Assert(t, c.bda.bds[0].used == true)
	tests.Assert(t, c.bda.bds[0].key == 0)
	tests.Assert(t, c.bda.bds[0].clock_set == false)

	tests.Assert(t, c.bda.bds[3].used == true)
	tests.Assert(t, c.bda.bds[3].key == 3)
	tests.Assert(t, c.bda.bds[3].clock_set == true)

	// Now check the blocks we inserted
	tests.Assert(t, c.bda.bds[4].used == true)
	tests.Assert(t, c.bda.bds[4].key == 10)
	tests.Assert(t, c.bda.bds[4].clock_set == false)

	tests.Assert(t, c.bda.bds[5].used == true)
	tests.Assert(t, c.bda.bds[5].key == 11)
	tests.Assert(t, c.bda.bds[5].clock_set == false)

	tests.Assert(t, c.bda.bds[6].used == true)
	tests.Assert(t, c.bda.bds[6].key == 12)
	tests.Assert(t, c.bda.bds[6].clock_set == false)

	tests.Assert(t, c.bda.bds[7].used == true)
	tests.Assert(t, c.bda.bds[7].key == 13)
	tests.Assert(t, c.bda.bds[7].clock_set == false)

	tests.Assert(t, c.bda.bds[1].used == true)
	tests.Assert(t, c.bda.bds[1].key == 14)
	tests.Assert(t, c.bda.bds[1].clock_set == false)

	tests.Assert(t, c.bda.bds[2].used == true)
	tests.Assert(t, c.bda.bds[2].key == 15)
	tests.Assert(t, c.bda.bds[2].clock_set == false)

	// Check for a block not in the cache
	m = message.NewMsgGet()
	m.RetChan = here
	io = m.IoPkt()
	io.Buffer = buffer
	io.Address = 20
	io.Blocks = 1
	hitmap, err := c.Get(m)
	tests.Assert(t, err == ErrNotFound)
	tests.Assert(t, hitmap == nil)
	tests.Assert(t, len(here) == 0)

	// Get offset 0, 4 blocks.  It should return
	// a bit map of [1001]
	buffer4 := make([]byte, 4*4096)
	m = message.NewMsgGet()
	m.RetChan = here
	io = m.IoPkt()
	io.Buffer = buffer4
	io.Address = 0
	io.Blocks = 4

	hitmap, err = c.Get(m)
	tests.Assert(t, err == nil)
	tests.Assert(t, hitmap.Hits == 2)
	tests.Assert(t, len(hitmap.Hitmap) == int(io.Blocks))
	tests.Assert(t, hitmap.Hitmap[0] == true)
	tests.Assert(t, hitmap.Hitmap[1] == false)
	tests.Assert(t, hitmap.Hitmap[2] == false)
	tests.Assert(t, hitmap.Hitmap[3] == true)
	for i := 0; i < 2; i++ {
		// Get sends a get for each contiguous blocks
		retmsg := <-mocklog
		retmsg.Done()
	}
	<-here

	// Get the 6 blocks we inserted previously.  This
	// should show that there are two sets of continguous
	// blocks
	m = message.NewMsgGet()
	m.RetChan = here
	io = m.IoPkt()
	io.Buffer = largebuffer
	io.Address = 10
	io.Blocks = 6

	hitmap, err = c.Get(m)
	tests.Assert(t, err == nil)
	tests.Assert(t, hitmap.Hits == 6)
	tests.Assert(t, len(hitmap.Hitmap) == int(io.Blocks))
	tests.Assert(t, hitmap.Hitmap[0] == true)
	tests.Assert(t, hitmap.Hitmap[1] == true)
	tests.Assert(t, hitmap.Hitmap[2] == true)
	tests.Assert(t, hitmap.Hitmap[3] == true)
	tests.Assert(t, hitmap.Hitmap[4] == true)
	tests.Assert(t, hitmap.Hitmap[5] == true)

	// The first message to the log
	retmsg := <-mocklog
	retio := retmsg.IoPkt()
	tests.Assert(t, retmsg.RetChan == nil)
	tests.Assert(t, retio.Address == 10)
	tests.Assert(t, retio.LogBlock == 4)
	tests.Assert(t, retio.Blocks == 4)
	retmsg.Done()

	// Second message will have the rest of the contigous block
	retmsg = <-mocklog
	retio = retmsg.IoPkt()
	tests.Assert(t, retmsg.RetChan == nil)
	tests.Assert(t, retio.Address == 14)
	tests.Assert(t, retio.LogBlock == 1)
	tests.Assert(t, retio.Blocks == 2)
	retmsg.Done()

	<-here

	// Save the cache metadata
	save := tests.Tempfile()
	defer os.Remove(save)
	err = c.Save(save, nil)
	tests.Assert(t, err == nil)

	c.Close()
	c = NewCacheMap(8, 4096, pipe.In)
	tests.Assert(t, c != nil)

	err = c.Load(save, nil)
	tests.Assert(t, err == nil)

	// Get data again.
	m = message.NewMsgGet()
	m.RetChan = here
	io = m.IoPkt()
	io.Buffer = largebuffer
	io.Address = 10
	io.Blocks = 6

	hitmap, err = c.Get(m)
	tests.Assert(t, err == nil)
	tests.Assert(t, hitmap.Hits == 6)
	tests.Assert(t, len(hitmap.Hitmap) == int(io.Blocks))
	tests.Assert(t, hitmap.Hitmap[0] == true)
	tests.Assert(t, hitmap.Hitmap[1] == true)
	tests.Assert(t, hitmap.Hitmap[2] == true)
	tests.Assert(t, hitmap.Hitmap[3] == true)
	tests.Assert(t, hitmap.Hitmap[4] == true)
	tests.Assert(t, hitmap.Hitmap[5] == true)

	// The first message to the log
	retmsg = <-mocklog
	retio = retmsg.IoPkt()
	tests.Assert(t, retmsg.RetChan == nil)
	tests.Assert(t, retio.Address == 10)
	tests.Assert(t, retio.LogBlock == 4)
	tests.Assert(t, retio.Blocks == 4)
	retmsg.Done()

	// Second message will have the rest of the contigous block
	retmsg = <-mocklog
	retio = retmsg.IoPkt()
	tests.Assert(t, retmsg.RetChan == nil)
	tests.Assert(t, retio.Address == 14)
	tests.Assert(t, retio.LogBlock == 1)
	tests.Assert(t, retio.Blocks == 2)
	retmsg.Done()

	<-here

	c.Close()
}