VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/BandwidthGroupImpl.cpp@ 47561

Last change on this file since 47561 was 41882, checked in by vboxsync, 13 years ago

NetShaper: Runtime shaper disabling support (#5582)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "BandwidthGroupImpl.h"
19#include "MachineImpl.h"
20#include "Global.h"
21
22#include "AutoCaller.h"
23#include "Logging.h"
24
25#include <iprt/cpp/utils.h>
26
27////////////////////////////////////////////////////////////////////////////////
28//
29// private member data definition
30//
31////////////////////////////////////////////////////////////////////////////////
32
33struct BackupableBandwidthGroupData
34{
35 BackupableBandwidthGroupData()
36 : enmType(BandwidthGroupType_Null),
37 aMaxBytesPerSec(0),
38 cReferences(0)
39 { }
40
41 Utf8Str strName;
42 BandwidthGroupType_T enmType;
43 LONG64 aMaxBytesPerSec;
44 ULONG cReferences;
45};
46
47struct BandwidthGroup::Data
48{
49 Data(BandwidthControl * const aBandwidthControl)
50 : pParent(aBandwidthControl),
51 pPeer(NULL)
52 { }
53
54 BandwidthControl * const pParent;
55 ComObjPtr<BandwidthGroup> pPeer;
56
57 // use the XML settings structure in the members for simplicity
58 Backupable<BackupableBandwidthGroupData> bd;
59};
60
61// constructor / destructor
62/////////////////////////////////////////////////////////////////////////////
63
64HRESULT BandwidthGroup::FinalConstruct()
65{
66 return BaseFinalConstruct();
67}
68
69void BandwidthGroup::FinalRelease()
70{
71 uninit();
72 BaseFinalRelease();
73}
74
75// public initializer/uninitializer for internal purposes only
76/////////////////////////////////////////////////////////////////////////////
77
78/**
79 * Initializes the bandwidth group object.
80 *
81 * @returns COM result indicator.
82 * @param aParent Pointer to our parent object.
83 * @param aName Name of the storage controller.
84 * @param aInstance Instance number of the storage controller.
85 */
86HRESULT BandwidthGroup::init(BandwidthControl *aParent,
87 const Utf8Str &aName,
88 BandwidthGroupType_T aType,
89 LONG64 aMaxBytesPerSec)
90{
91 LogFlowThisFunc(("aParent=%p aName=\"%s\"\n",
92 aParent, aName.c_str()));
93
94 ComAssertRet(aParent && !aName.isEmpty(), E_INVALIDARG);
95 if ( (aType <= BandwidthGroupType_Null)
96 || (aType > BandwidthGroupType_Network))
97 return setError(E_INVALIDARG,
98 tr("Invalid bandwidth group type type"));
99
100 /* Enclose the state transition NotReady->InInit->Ready */
101 AutoInitSpan autoInitSpan(this);
102 AssertReturn(autoInitSpan.isOk(), E_FAIL);
103
104 m = new Data(aParent);
105
106 /* m->pPeer is left null */
107
108 m->bd.allocate();
109
110 m->bd->strName = aName;
111 m->bd->enmType = aType;
112 m->bd->cReferences = 0;
113 m->bd->aMaxBytesPerSec = aMaxBytesPerSec;
114
115 /* Confirm a successful initialization */
116 autoInitSpan.setSucceeded();
117
118 return S_OK;
119}
120
121/**
122 * Initializes the object given another object
123 * (a kind of copy constructor). This object shares data with
124 * the object passed as an argument.
125 *
126 * @param aReshare
127 * When false, the original object will remain a data owner.
128 * Otherwise, data ownership will be transferred from the original
129 * object to this one.
130 *
131 * @note This object must be destroyed before the original object
132 * it shares data with is destroyed.
133 *
134 * @note Locks @a aThat object for writing if @a aReshare is @c true, or for
135 * reading if @a aReshare is false.
136 */
137HRESULT BandwidthGroup::init(BandwidthControl *aParent,
138 BandwidthGroup *aThat,
139 bool aReshare /* = false */)
140{
141 LogFlowThisFunc(("aParent=%p, aThat=%p, aReshare=%RTbool\n",
142 aParent, aThat, aReshare));
143
144 ComAssertRet(aParent && aThat, E_INVALIDARG);
145
146 /* Enclose the state transition NotReady->InInit->Ready */
147 AutoInitSpan autoInitSpan(this);
148 AssertReturn(autoInitSpan.isOk(), E_FAIL);
149
150 m = new Data(aParent);
151
152 /* sanity */
153 AutoCaller thatCaller(aThat);
154 AssertComRCReturnRC(thatCaller.rc());
155
156 if (aReshare)
157 {
158 AutoWriteLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
159
160 unconst(aThat->m->pPeer) = this;
161 m->bd.attach (aThat->m->bd);
162 }
163 else
164 {
165 unconst(m->pPeer) = aThat;
166
167 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
168 m->bd.share (aThat->m->bd);
169 }
170
171 /* Confirm successful initialization */
172 autoInitSpan.setSucceeded();
173
174 return S_OK;
175}
176
177/**
178 * Initializes the storage controller object given another guest object
179 * (a kind of copy constructor). This object makes a private copy of data
180 * of the original object passed as an argument.
181 */
182HRESULT BandwidthGroup::initCopy(BandwidthControl *aParent, BandwidthGroup *aThat)
183{
184 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
185
186 ComAssertRet(aParent && aThat, E_INVALIDARG);
187
188 /* Enclose the state transition NotReady->InInit->Ready */
189 AutoInitSpan autoInitSpan(this);
190 AssertReturn(autoInitSpan.isOk(), E_FAIL);
191
192 m = new Data(aParent);
193 /* m->pPeer is left null */
194
195 AutoCaller thatCaller(aThat);
196 AssertComRCReturnRC(thatCaller.rc());
197
198 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
199 m->bd.attachCopy(aThat->m->bd);
200
201 /* Confirm a successful initialization */
202 autoInitSpan.setSucceeded();
203
204 return S_OK;
205}
206
207
208/**
209 * Uninitializes the instance and sets the ready flag to FALSE.
210 * Called either from FinalRelease() or by the parent when it gets destroyed.
211 */
212void BandwidthGroup::uninit()
213{
214 LogFlowThisFunc(("\n"));
215
216 /* Enclose the state transition Ready->InUninit->NotReady */
217 AutoUninitSpan autoUninitSpan(this);
218 if (autoUninitSpan.uninitDone())
219 return;
220
221 m->bd.free();
222
223 unconst(m->pPeer) = NULL;
224 unconst(m->pParent) = NULL;
225
226 delete m;
227 m = NULL;
228}
229
230STDMETHODIMP BandwidthGroup::COMGETTER(Name)(BSTR *aName)
231{
232 CheckComArgOutPointerValid(aName);
233
234 AutoCaller autoCaller(this);
235 if (FAILED(autoCaller.rc())) return autoCaller.rc();
236
237 /* mName is constant during life time, no need to lock */
238 m->bd.data()->strName.cloneTo(aName);
239
240 return S_OK;
241}
242
243STDMETHODIMP BandwidthGroup::COMGETTER(Type)(BandwidthGroupType_T *aType)
244{
245 CheckComArgOutPointerValid(aType);
246
247 AutoCaller autoCaller(this);
248 if (FAILED(autoCaller.rc())) return autoCaller.rc();
249
250 /* type is constant during life time, no need to lock */
251 *aType = m->bd->enmType;
252
253 return S_OK;
254}
255
256STDMETHODIMP BandwidthGroup::COMGETTER(Reference)(ULONG *aReferences)
257{
258 CheckComArgOutPointerValid(aReferences);
259
260 AutoCaller autoCaller(this);
261 if (FAILED(autoCaller.rc())) return autoCaller.rc();
262
263 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
264
265 *aReferences = m->bd->cReferences;
266
267 return S_OK;
268}
269
270STDMETHODIMP BandwidthGroup::COMGETTER(MaxBytesPerSec)(LONG64 *aMaxBytesPerSec)
271{
272 CheckComArgOutPointerValid(aMaxBytesPerSec);
273
274 AutoCaller autoCaller(this);
275 if (FAILED(autoCaller.rc())) return autoCaller.rc();
276
277 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
278
279 *aMaxBytesPerSec = m->bd->aMaxBytesPerSec;
280
281 return S_OK;
282}
283
284STDMETHODIMP BandwidthGroup::COMSETTER(MaxBytesPerSec)(LONG64 aMaxBytesPerSec)
285{
286 if (aMaxBytesPerSec < 0)
287 return setError(E_INVALIDARG,
288 tr("Bandwidth group limit cannot be negative"));
289
290 AutoCaller autoCaller(this);
291 if (FAILED(autoCaller.rc())) return autoCaller.rc();
292
293 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
294
295 m->bd.backup();
296 m->bd->aMaxBytesPerSec = aMaxBytesPerSec;
297
298 /* inform direct session if any. */
299 ComObjPtr<Machine> pMachine = m->pParent->getMachine();
300 alock.release();
301 pMachine->onBandwidthGroupChange(this);
302
303 return S_OK;
304}
305
306// public methods only for internal purposes
307/////////////////////////////////////////////////////////////////////////////
308
309/** @note Locks objects for writing! */
310void BandwidthGroup::rollback()
311{
312 AutoCaller autoCaller(this);
313 AssertComRCReturnVoid(autoCaller.rc());
314
315 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
316
317 m->bd.rollback();
318}
319
320/**
321 * @note Locks this object for writing, together with the peer object (also
322 * for writing) if there is one.
323 */
324void BandwidthGroup::commit()
325{
326 /* sanity */
327 AutoCaller autoCaller(this);
328 AssertComRCReturnVoid (autoCaller.rc());
329
330 /* sanity too */
331 AutoCaller peerCaller (m->pPeer);
332 AssertComRCReturnVoid (peerCaller.rc());
333
334 /* lock both for writing since we modify both (m->pPeer is "master" so locked
335 * first) */
336 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
337
338 if (m->bd.isBackedUp())
339 {
340 m->bd.commit();
341 if (m->pPeer)
342 {
343 // attach new data to the peer and reshare it
344 m->pPeer->m->bd.attach (m->bd);
345 }
346 }
347}
348
349
350/**
351 * Cancels sharing (if any) by making an independent copy of data.
352 * This operation also resets this object's peer to NULL.
353 *
354 * @note Locks this object for writing, together with the peer object
355 * represented by @a aThat (locked for reading).
356 */
357void BandwidthGroup::unshare()
358{
359 /* sanity */
360 AutoCaller autoCaller(this);
361 AssertComRCReturnVoid (autoCaller.rc());
362
363 /* sanity too */
364 AutoCaller peerCaller (m->pPeer);
365 AssertComRCReturnVoid (peerCaller.rc());
366
367 /* peer is not modified, lock it for reading (m->pPeer is "master" so locked
368 * first) */
369 AutoReadLock rl(m->pPeer COMMA_LOCKVAL_SRC_POS);
370 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
371
372 if (m->bd.isShared())
373 {
374 if (!m->bd.isBackedUp())
375 m->bd.backup();
376
377 m->bd.commit();
378 }
379
380 unconst(m->pPeer) = NULL;
381}
382
383ComObjPtr<BandwidthGroup> BandwidthGroup::getPeer()
384{
385 return m->pPeer;
386}
387
388const Utf8Str& BandwidthGroup::getName() const
389{
390 return m->bd->strName;
391}
392
393BandwidthGroupType_T BandwidthGroup::getType() const
394{
395 return m->bd->enmType;
396}
397
398LONG64 BandwidthGroup::getMaxBytesPerSec() const
399{
400 return m->bd->aMaxBytesPerSec;
401}
402
403ULONG BandwidthGroup::getReferences() const
404{
405 return m->bd->cReferences;
406}
407
408void BandwidthGroup::reference()
409{
410 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
411 m->bd.backup();
412 m->bd->cReferences++;
413}
414
415void BandwidthGroup::release()
416{
417 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
418 m->bd.backup();
419 m->bd->cReferences--;
420}
421
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette