Files
kata-containers/virtcontainers/factory/cache/cache.go
Peng Tao bdd5c66fc5 virtcontainers: add vm factory support
Add vm factory support per design in the VM Factory plugin section.
The vm factory controls how a new vm is created:

1. direct: vm is created directly
2. template: vm is created via vm template. A template vm is pre-created
   and saved. Later vm is just a clone of the template vm so that they
   readonly share a portion of initial memory (including kernel, initramfs
   and the kata agent). CPU and memory are hot plugged when necessary.
3. cache: vm is created via vm caches. A set of cached vm are pre-created
   and maintained alive. New vms are created by just picking a cached vm.
   CPU and memory are hot plugged when necessary.

Fixes: #303

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2018-07-19 12:44:58 +08:00

84 lines
1.6 KiB
Go

// Copyright (c) 2018 HyperHQ Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// cache implements base vm factory on top of other base vm factory.
package cache
import (
"fmt"
"sync"
vc "github.com/kata-containers/runtime/virtcontainers"
"github.com/kata-containers/runtime/virtcontainers/factory/base"
)
type cache struct {
base base.FactoryBase
cacheCh chan *vc.VM
closed chan<- int
wg sync.WaitGroup
closeOnce sync.Once
}
// New creates a new cached vm factory.
func New(count uint, b base.FactoryBase) base.FactoryBase {
if count < 1 {
return b
}
cacheCh := make(chan *vc.VM)
closed := make(chan int, count)
c := cache{base: b, cacheCh: cacheCh, closed: closed}
for i := 0; i < int(count); i++ {
c.wg.Add(1)
go func() {
for {
vm, err := b.GetBaseVM()
if err != nil {
c.wg.Done()
c.CloseFactory()
return
}
select {
case cacheCh <- vm:
case <-closed:
vm.Stop()
c.wg.Done()
return
}
}
}()
}
return &c
}
// Config returns cache vm factory's base factory config.
func (c *cache) Config() vc.VMConfig {
return c.base.Config()
}
// GetBaseVM returns a base VM from cache factory's base factory.
func (c *cache) GetBaseVM() (*vc.VM, error) {
vm, ok := <-c.cacheCh
if ok {
return vm, nil
}
return nil, fmt.Errorf("cache factory is closed")
}
// CloseFactory closes the cache factory.
func (c *cache) CloseFactory() {
c.closeOnce.Do(func() {
for len(c.closed) < cap(c.closed) { // send sufficient closed signal
c.closed <- 0
}
c.wg.Wait()
close(c.cacheCh)
c.base.CloseFactory()
})
}