VirtualBox

source: vbox/trunk/src/VBox/Main/BandwidthGroupImpl.cpp@ 34900

Last change on this file since 34900 was 34587, checked in by vboxsync, 14 years ago

Main: Bandwidth groups for disks (and later network)

This introduces two new interfaces. The first one named IBandwidthGroup
represents one I/O limit and can be assigned to several mediums which
share this limit (which works only for harddisk images with the disabled
host cache).
The second one IBandwdithControl manages the groups and can create new ones
and destroy them if not required anymore.

VBoxManage: commands to access the bandwidth groups

Syntax:
VBoxManage storageattach <uuid|vmname>

...
--bandwidthgroup <name>

--bandwidthgroup assigns the specified device to the given group.

VBoxManage bandwidthctl <uuid|vmname>

--name <name>
--add disk|network
--limit <megabytes per second>
--delete

The --name parameter gives the name of the bandwidth group.
--add creates a new group of the given type (only disk is implemented so far)

with the given name.

--limit sets the limit to the given amount of MB/s

Note that limit can be changed while the VM is running. The VM
will immediately pick up the new limit for the given group name.

--delete deletes the group with the given name if it isn't used anymore.

Trying to delete a still used group will result in an error.

Example:

VBoxManage bandwidthctl "Test VM" --name Limit --add disk --limit 20
Creates a group named Test having a 20 MB/s limit.

VBoxManage storageattach "Test VM" --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium test.vdi --bandwidthgroup Limit
Adds a new disk to the SATA controller and assigns the bandwidth group Limit to it.

VBoxManage storageattach "Test VM" --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium test.vdi --bandwidthgroup none
Removes the bandwidth limit from the disk.

VBoxManage bandwidthctl "Test VM" --name Limit --add disk --limit 10
Changes the limit of bandwidth group Limit to 10 MB/s. If the VM is running the limit will be picked up
immediately.

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