func (c *CacheMap) Put(msg *message.Message) error { err := msg.Check() if err != nil { return err } c.lock.Lock() defer c.lock.Unlock() io := msg.IoPkt() if io.Blocks > 1 { // Have parent message wait for its children defer msg.Done() // // It does not matter that we send small blocks to the Log, since // it will buffer them before sending them out to the cache device // // We do need to send each one sperately now so that the cache // policy hopefully aligns them one after the other. // for block := uint32(0); block < io.Blocks; block++ { child := message.NewMsgPut() msg.Add(child) child_io := child.IoPkt() child_io.Address = io.Address + uint64(block) child_io.Buffer = SubBlockBuffer(io.Buffer, c.blocksize, block, 1) child_io.LogBlock = c.put(child_io.Address) child_io.Blocks = 1 // Send to next one in line c.pipeline <- child } } else { io.LogBlock = c.put(io.Address) c.pipeline <- msg } return nil }
func (c *CacheMap) Get(msg *message.Message) (*HitmapPkt, error) { err := msg.Check() if err != nil { return nil, err } c.lock.Lock() defer c.lock.Unlock() io := msg.IoPkt() hitmap := make([]bool, io.Blocks) hits := uint32(0) // Create a message var m *message.Message var mblock uint32 for block := uint32(0); block < io.Blocks; block++ { // Get current_address := io.Address + uint64(block) if index, ok := c.get(current_address); ok { hitmap[block] = true hits++ // Check if we already have a message ready if m == nil { // This is the first message, so let's set it up m = c.create_get_submsg(msg, current_address, index, SubBlockBuffer(io.Buffer, c.blocksize, block, 1)) mblock = block } else { // Let's check what block we are using starting from the block // setup by the message numblocks := block - mblock // If the next block is available on the log after this block, then // we can optimize the read by reading a larger amount from the log. if m.IoPkt().LogBlock+numblocks == index && hitmap[block-1] == true { // It is the next in both the cache and storage device mio := m.IoPkt() mio.Blocks++ mio.Buffer = SubBlockBuffer(io.Buffer, c.blocksize, mblock, mio.Blocks) } else { // Send the previous one c.pipeline <- m // This is the first message, so let's set it up m = c.create_get_submsg(msg, current_address, index, SubBlockBuffer(io.Buffer, c.blocksize, block, 1)) mblock = block } } } } // Check if we have one more message if m != nil { c.pipeline <- m } if hits > 0 { hitmappkt := &HitmapPkt{ Hitmap: hitmap, Hits: hits, } msg.Done() return hitmappkt, nil } else { return nil, ErrNotFound } }