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

     1  /*
     2  Copyright (c) 2024-2024 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package simulator
    18  
    19  import (
    20  	"container/list"
    21  	"sync"
    22  
    23  	"github.com/vmware/govmomi/vim25/methods"
    24  	"github.com/vmware/govmomi/vim25/mo"
    25  	"github.com/vmware/govmomi/vim25/soap"
    26  	"github.com/vmware/govmomi/vim25/types"
    27  )
    28  
    29  var (
    30  	maxPageSize           = 1000
    31  	maxCollectors   int32 = 32 // the VC default limit
    32  	defaultPageSize       = 10
    33  
    34  	errInvalidArgMaxCount = &types.InvalidArgument{InvalidProperty: "maxCount"}
    35  )
    36  
    37  type HistoryCollector struct {
    38  	parent *history
    39  	root   types.ManagedObjectReference
    40  	size   int
    41  
    42  	fill func(*Context)
    43  	page *list.List
    44  	pos  *list.Element
    45  }
    46  
    47  type history struct {
    48  	sync.Mutex
    49  
    50  	page       *list.List
    51  	collectors map[types.ManagedObjectReference]mo.Reference
    52  }
    53  
    54  func newHistory() *history {
    55  	return &history{
    56  		page:       list.New(),
    57  		collectors: make(map[types.ManagedObjectReference]mo.Reference),
    58  	}
    59  }
    60  
    61  func (c *history) add(ctx *Context, collector mo.Reference) types.ManagedObjectReference {
    62  	ref := ctx.Session.Put(collector).Reference()
    63  
    64  	c.Lock()
    65  	c.collectors[ref] = collector
    66  	c.Unlock()
    67  
    68  	return ref
    69  }
    70  
    71  func (c *history) remove(ctx *Context, ref types.ManagedObjectReference) {
    72  	ctx.Session.Remove(ctx, ref)
    73  
    74  	c.Lock()
    75  	delete(c.collectors, ref)
    76  	c.Unlock()
    77  }
    78  
    79  func newHistoryCollector(ctx *Context, h *history, size int) *HistoryCollector {
    80  	return &HistoryCollector{
    81  		parent: h,
    82  		root:   ctx.Map.content().RootFolder,
    83  		size:   size,
    84  		page:   list.New(),
    85  	}
    86  }
    87  
    88  func (c *HistoryCollector) SetCollectorPageSize(ctx *Context, req *types.SetCollectorPageSize) soap.HasFault {
    89  	body := new(methods.SetCollectorPageSizeBody)
    90  	size, err := validatePageSize(req.MaxCount)
    91  	if err != nil {
    92  		body.Fault_ = err
    93  		return body
    94  	}
    95  
    96  	c.size = size
    97  	c.page = list.New()
    98  	c.fill(ctx)
    99  
   100  	body.Res = new(types.SetCollectorPageSizeResponse)
   101  	return body
   102  }
   103  
   104  func (c *HistoryCollector) ResetCollector(ctx *Context, req *types.ResetCollector) soap.HasFault {
   105  	c.pos = c.page.Back()
   106  
   107  	return &methods.ResetCollectorBody{
   108  		Res: new(types.ResetCollectorResponse),
   109  	}
   110  }
   111  
   112  func (c *HistoryCollector) RewindCollector(ctx *Context, req *types.RewindCollector) soap.HasFault {
   113  	c.pos = c.page.Front()
   114  
   115  	return &methods.RewindCollectorBody{
   116  		Res: new(types.RewindCollectorResponse),
   117  	}
   118  }
   119  
   120  func (c *HistoryCollector) DestroyCollector(ctx *Context, req *types.DestroyCollector) soap.HasFault {
   121  	ctx.Session.Remove(ctx, req.This)
   122  
   123  	c.parent.remove(ctx, req.This)
   124  
   125  	return &methods.DestroyCollectorBody{
   126  		Res: new(types.DestroyCollectorResponse),
   127  	}
   128  }
   129  
   130  func (c *HistoryCollector) read(max int32, next func() *list.Element, take func(*list.Element)) {
   131  	for i := 0; i < int(max); i++ {
   132  		e := next()
   133  		if e == nil {
   134  			break
   135  		}
   136  
   137  		take(e)
   138  		c.pos = e
   139  	}
   140  }
   141  
   142  func (c *HistoryCollector) next(max int32, take func(*list.Element)) {
   143  	next := func() *list.Element {
   144  		if c.pos != nil {
   145  			return c.pos.Next()
   146  		}
   147  		return c.page.Front()
   148  	}
   149  
   150  	c.read(max, next, take)
   151  }
   152  
   153  func (c *HistoryCollector) prev(max int32, take func(*list.Element)) {
   154  	next := func() *list.Element {
   155  		if c.pos != nil {
   156  			return c.pos.Prev()
   157  		}
   158  		return c.page.Back()
   159  	}
   160  
   161  	c.read(max, next, take)
   162  }
   163  
   164  func pushHistory(l *list.List, item types.AnyType) {
   165  	if l.Len() > maxPageSize {
   166  		l.Remove(l.Front()) // Prune history
   167  	}
   168  	l.PushBack(item)
   169  }
   170  
   171  func validatePageSize(count int32) (int, *soap.Fault) {
   172  	size := int(count)
   173  
   174  	if size == 0 {
   175  		size = defaultPageSize
   176  	} else if size < 0 || size > maxPageSize {
   177  		return -1, Fault("", errInvalidArgMaxCount)
   178  	}
   179  
   180  	return size, nil
   181  }