Beispiel #1
0
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
}
Beispiel #2
0
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
	}
}