github.com/vmware/govmomi@v0.51.0/simulator/history_collector.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package simulator
     6  
     7  import (
     8  	"container/list"
     9  	"sync"
    10  
    11  	"github.com/vmware/govmomi/vim25/methods"
    12  	"github.com/vmware/govmomi/vim25/mo"
    13  	"github.com/vmware/govmomi/vim25/soap"
    14  	"github.com/vmware/govmomi/vim25/types"
    15  )
    16  
    17  var (
    18  	maxPageSize           = 1000
    19  	maxCollectors   int32 = 32 // the VC default limit
    20  	defaultPageSize       = 10
    21  
    22  	errInvalidArgMaxCount = &types.InvalidArgument{InvalidProperty: "maxCount"}
    23  )
    24  
    25  type HistoryCollector struct {
    26  	parent *history
    27  	root   types.ManagedObjectReference
    28  	size   int
    29  
    30  	fill func(*Context)
    31  	page *list.List
    32  	pos  *list.Element
    33  }
    34  
    35  type history struct {
    36  	sync.Mutex
    37  
    38  	page       *list.List
    39  	collectors map[types.ManagedObjectReference]mo.Reference
    40  }
    41  
    42  func newHistory() *history {
    43  	return &history{
    44  		page:       list.New(),
    45  		collectors: make(map[types.ManagedObjectReference]mo.Reference),
    46  	}
    47  }
    48  
    49  func (c *history) add(ctx *Context, collector mo.Reference) types.ManagedObjectReference {
    50  	ref := ctx.Session.Put(collector).Reference()
    51  
    52  	c.Lock()
    53  	c.collectors[ref] = collector
    54  	c.Unlock()
    55  
    56  	return ref
    57  }
    58  
    59  func (c *history) remove(ctx *Context, ref types.ManagedObjectReference) {
    60  	ctx.Session.Remove(ctx, ref)
    61  
    62  	c.Lock()
    63  	delete(c.collectors, ref)
    64  	c.Unlock()
    65  }
    66  
    67  func newHistoryCollector(ctx *Context, h *history, size int) *HistoryCollector {
    68  	return &HistoryCollector{
    69  		parent: h,
    70  		root:   ctx.Map.content().RootFolder,
    71  		size:   size,
    72  		page:   list.New(),
    73  	}
    74  }
    75  
    76  func (c *HistoryCollector) SetCollectorPageSize(ctx *Context, req *types.SetCollectorPageSize) soap.HasFault {
    77  	body := new(methods.SetCollectorPageSizeBody)
    78  	size, err := validatePageSize(req.MaxCount)
    79  	if err != nil {
    80  		body.Fault_ = err
    81  		return body
    82  	}
    83  
    84  	c.size = size
    85  	c.page = list.New()
    86  	c.fill(ctx)
    87  
    88  	body.Res = new(types.SetCollectorPageSizeResponse)
    89  	return body
    90  }
    91  
    92  func (c *HistoryCollector) ResetCollector(ctx *Context, req *types.ResetCollector) soap.HasFault {
    93  	c.pos = c.page.Back()
    94  
    95  	return &methods.ResetCollectorBody{
    96  		Res: new(types.ResetCollectorResponse),
    97  	}
    98  }
    99  
   100  func (c *HistoryCollector) RewindCollector(ctx *Context, req *types.RewindCollector) soap.HasFault {
   101  	c.pos = c.page.Front()
   102  
   103  	return &methods.RewindCollectorBody{
   104  		Res: new(types.RewindCollectorResponse),
   105  	}
   106  }
   107  
   108  func (c *HistoryCollector) DestroyCollector(ctx *Context, req *types.DestroyCollector) soap.HasFault {
   109  	ctx.Session.Remove(ctx, req.This)
   110  
   111  	c.parent.remove(ctx, req.This)
   112  
   113  	return &methods.DestroyCollectorBody{
   114  		Res: new(types.DestroyCollectorResponse),
   115  	}
   116  }
   117  
   118  func (c *HistoryCollector) read(max int32, next func() *list.Element, take func(*list.Element)) {
   119  	for i := 0; i < int(max); i++ {
   120  		e := next()
   121  		if e == nil {
   122  			break
   123  		}
   124  
   125  		take(e)
   126  		c.pos = e
   127  	}
   128  }
   129  
   130  func (c *HistoryCollector) next(max int32, take func(*list.Element)) {
   131  	next := func() *list.Element {
   132  		if c.pos != nil {
   133  			return c.pos.Next()
   134  		}
   135  		return c.page.Front()
   136  	}
   137  
   138  	c.read(max, next, take)
   139  }
   140  
   141  func (c *HistoryCollector) prev(max int32, take func(*list.Element)) {
   142  	next := func() *list.Element {
   143  		if c.pos != nil {
   144  			return c.pos.Prev()
   145  		}
   146  		return c.page.Back()
   147  	}
   148  
   149  	c.read(max, next, take)
   150  }
   151  
   152  func pushHistory(l *list.List, item types.AnyType) {
   153  	if l.Len() > maxPageSize {
   154  		l.Remove(l.Front()) // Prune history
   155  	}
   156  	l.PushBack(item)
   157  }
   158  
   159  func validatePageSize(count int32) (int, *soap.Fault) {
   160  	size := int(count)
   161  
   162  	if size == 0 {
   163  		size = defaultPageSize
   164  	} else if size < 0 || size > maxPageSize {
   165  		return -1, Fault("", errInvalidArgMaxCount)
   166  	}
   167  
   168  	return size, nil
   169  }