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 }