github.com/vmware/govmomi@v0.43.0/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 }