VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/BandwidthControlImpl.cpp@ 53390

Last change on this file since 53390 was 51498, checked in by vboxsync, 11 years ago

6813 - MachineImpl use of server side wrappers + misc mods on other classes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.6 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2014 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 "BandwidthControlImpl.h"
19#include "BandwidthGroupImpl.h"
20#include "MachineImpl.h"
21#include "Global.h"
22
23#include "AutoStateDep.h"
24#include "AutoCaller.h"
25#include "Logging.h"
26
27#include <iprt/cpp/utils.h>
28#include <VBox/com/array.h>
29#include <algorithm>
30
31// defines
32/////////////////////////////////////////////////////////////////////////////
33
34// constructor / destructor
35/////////////////////////////////////////////////////////////////////////////
36DEFINE_EMPTY_CTOR_DTOR(BandwidthControl)
37
38
39HRESULT BandwidthControl::FinalConstruct()
40{
41 return BaseFinalConstruct();
42}
43
44void BandwidthControl::FinalRelease()
45{
46 uninit();
47 BaseFinalRelease();
48}
49
50// public initializer/uninitializer for internal purposes only
51/////////////////////////////////////////////////////////////////////////////
52
53/**
54 * Initializes the bandwidth group object.
55 *
56 * @returns COM result indicator.
57 * @param aParent Pointer to our parent object.
58 */
59HRESULT BandwidthControl::init(Machine *aParent)
60{
61 LogFlowThisFunc(("aParent=%p\n", aParent));
62
63 ComAssertRet(aParent, E_INVALIDARG);
64
65 /* Enclose the state transition NotReady->InInit->Ready */
66 AutoInitSpan autoInitSpan(this);
67 AssertReturn(autoInitSpan.isOk(), E_FAIL);
68
69 m = new Data(aParent);
70
71 /* m->pPeer is left null */
72
73 m->llBandwidthGroups.allocate();
74
75 /* Confirm a successful initialization */
76 autoInitSpan.setSucceeded();
77
78 return S_OK;
79}
80
81/**
82 * Initializes the object given another object
83 * (a kind of copy constructor). This object shares data with
84 * the object passed as an argument.
85 *
86 * @note This object must be destroyed before the original object
87 * it shares data with is destroyed.
88 *
89 * @note Locks @a aThat object for writing if @a aReshare is @c true, or for
90 * reading if @a aReshare is false.
91 */
92HRESULT BandwidthControl::init(Machine *aParent,
93 BandwidthControl *aThat)
94{
95 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
96
97 ComAssertRet(aParent && aThat, E_INVALIDARG);
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 /* sanity */
106 AutoCaller thatCaller(aThat);
107 AssertComRCReturnRC(thatCaller.rc());
108
109 unconst(m->pPeer) = aThat;
110 AutoWriteLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
111
112 /* create copies of all groups */
113 m->llBandwidthGroups.allocate();
114 BandwidthGroupList::const_iterator it;
115 for (it = aThat->m->llBandwidthGroups->begin();
116 it != aThat->m->llBandwidthGroups->end();
117 ++it)
118 {
119 ComObjPtr<BandwidthGroup> group;
120 group.createObject();
121 group->init(this, *it);
122 m->llBandwidthGroups->push_back(group);
123 }
124
125 /* Confirm successful initialization */
126 autoInitSpan.setSucceeded();
127
128 return S_OK;
129}
130
131/**
132 * Initializes the bandwidth control object given another guest object
133 * (a kind of copy constructor). This object makes a private copy of data
134 * of the original object passed as an argument.
135 */
136HRESULT BandwidthControl::initCopy(Machine *aParent, BandwidthControl *aThat)
137{
138 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
139
140 ComAssertRet(aParent && aThat, E_INVALIDARG);
141
142 /* Enclose the state transition NotReady->InInit->Ready */
143 AutoInitSpan autoInitSpan(this);
144 AssertReturn(autoInitSpan.isOk(), E_FAIL);
145
146 m = new Data(aParent);
147 /* m->pPeer is left null */
148
149 AutoCaller thatCaller(aThat);
150 AssertComRCReturnRC(thatCaller.rc());
151
152 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
153
154 /* create copies of all groups */
155 m->llBandwidthGroups.allocate();
156 BandwidthGroupList::const_iterator it;
157 for (it = aThat->m->llBandwidthGroups->begin();
158 it != aThat->m->llBandwidthGroups->end();
159 ++it)
160 {
161 ComObjPtr<BandwidthGroup> group;
162 group.createObject();
163 group->initCopy(this, *it);
164 m->llBandwidthGroups->push_back(group);
165 }
166
167 /* Confirm a successful initialization */
168 autoInitSpan.setSucceeded();
169
170 return S_OK;
171}
172
173
174/**
175 * @note Locks this object for writing, together with the peer object
176 * represented by @a aThat (locked for reading).
177 */
178void BandwidthControl::i_copyFrom(BandwidthControl *aThat)
179{
180 AssertReturnVoid(aThat != NULL);
181
182 /* sanity */
183 AutoCaller autoCaller(this);
184 AssertComRCReturnVoid(autoCaller.rc());
185
186 /* sanity too */
187 AutoCaller thatCaller(aThat);
188 AssertComRCReturnVoid(thatCaller.rc());
189
190 /* even more sanity */
191 AutoAnyStateDependency adep(m->pParent);
192 AssertComRCReturnVoid(adep.rc());
193 /* Machine::copyFrom() may not be called when the VM is running */
194 AssertReturnVoid(!Global::IsOnline(adep.machineState()));
195
196 /* peer is not modified, lock it for reading (aThat is "master" so locked
197 * first) */
198 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
199 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
200
201 /* create private copies of all bandwidth groups */
202 m->llBandwidthGroups.backup();
203 m->llBandwidthGroups->clear();
204 BandwidthGroupList::const_iterator it;
205 for (it = aThat->m->llBandwidthGroups->begin();
206 it != aThat->m->llBandwidthGroups->end();
207 ++it)
208 {
209 ComObjPtr<BandwidthGroup> group;
210 group.createObject();
211 group->initCopy(this, *it);
212 m->llBandwidthGroups->push_back(group);
213 }
214}
215
216/** @note Locks objects for writing! */
217void BandwidthControl::i_rollback()
218{
219 AutoCaller autoCaller(this);
220 AssertComRCReturnVoid(autoCaller.rc());
221
222 /* we need the machine state */
223 AutoAnyStateDependency adep(m->pParent);
224 AssertComRCReturnVoid(adep.rc());
225
226 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
227 BandwidthGroupList::const_iterator it;
228
229 if (!m->llBandwidthGroups.isNull())
230 {
231 if (m->llBandwidthGroups.isBackedUp())
232 {
233 /* unitialize all new groups (absent in the backed up list). */
234 BandwidthGroupList *backedList = m->llBandwidthGroups.backedUpData();
235 for (it = m->llBandwidthGroups->begin();
236 it != m->llBandwidthGroups->end();
237 ++it)
238 {
239 if ( std::find(backedList->begin(), backedList->end(), *it)
240 == backedList->end())
241 (*it)->uninit();
242 }
243
244 /* restore the list */
245 m->llBandwidthGroups.rollback();
246 }
247
248 /* rollback any changes to groups after restoring the list */
249 for (it = m->llBandwidthGroups->begin();
250 it != m->llBandwidthGroups->end();
251 ++it)
252 (*it)->i_rollback();
253 }
254}
255
256void BandwidthControl::i_commit()
257{
258 bool commitBandwidthGroups = false;
259 BandwidthGroupList::const_iterator it;
260
261 if (m->llBandwidthGroups.isBackedUp())
262 {
263 m->llBandwidthGroups.commit();
264
265 if (m->pPeer)
266 {
267 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
268
269 /* Commit all changes to new groups (this will reshare data with
270 * peers for those who have peers) */
271 BandwidthGroupList *newList = new BandwidthGroupList();
272 for (it = m->llBandwidthGroups->begin();
273 it != m->llBandwidthGroups->end();
274 ++it)
275 {
276 (*it)->i_commit();
277
278 /* look if this group has a peer group */
279 ComObjPtr<BandwidthGroup> peer = (*it)->i_getPeer();
280 if (!peer)
281 {
282 /* no peer means the device is a newly created one;
283 * create a peer owning data this device share it with */
284 peer.createObject();
285 peer->init(m->pPeer, *it, true /* aReshare */);
286 }
287 else
288 {
289 /* remove peer from the old list */
290 m->pPeer->m->llBandwidthGroups->remove(peer);
291 }
292 /* and add it to the new list */
293 newList->push_back(peer);
294 }
295
296 /* uninit old peer's groups that are left */
297 for (it = m->pPeer->m->llBandwidthGroups->begin();
298 it != m->pPeer->m->llBandwidthGroups->end();
299 ++it)
300 (*it)->uninit();
301
302 /* attach new list of groups to our peer */
303 m->pPeer->m->llBandwidthGroups.attach(newList);
304 }
305 else
306 {
307 /* we have no peer (our parent is the newly created machine);
308 * just commit changes to devices */
309 commitBandwidthGroups = true;
310 }
311 }
312 else
313 {
314 /* the list of groups itself is not changed,
315 * just commit changes to groups themselves */
316 commitBandwidthGroups = true;
317 }
318
319 if (commitBandwidthGroups)
320 {
321 for (it = m->llBandwidthGroups->begin();
322 it != m->llBandwidthGroups->end();
323 ++it)
324 (*it)->i_commit();
325 }
326}
327
328/**
329 * Uninitializes the instance and sets the ready flag to FALSE.
330 * Called either from FinalRelease() or by the parent when it gets destroyed.
331 */
332void BandwidthControl::uninit()
333{
334 LogFlowThisFunc(("\n"));
335
336 /* Enclose the state transition Ready->InUninit->NotReady */
337 AutoUninitSpan autoUninitSpan(this);
338 if (autoUninitSpan.uninitDone())
339 return;
340
341 // uninit all groups on the list (it's a standard std::list not an ObjectsList
342 // so we must uninit() manually)
343 BandwidthGroupList::iterator it;
344 for (it = m->llBandwidthGroups->begin();
345 it != m->llBandwidthGroups->end();
346 ++it)
347 (*it)->uninit();
348
349 m->llBandwidthGroups.free();
350
351 unconst(m->pPeer) = NULL;
352 unconst(m->pParent) = NULL;
353
354 delete m;
355 m = NULL;
356}
357
358/**
359 * Returns a bandwidth group object with the given name.
360 *
361 * @param aName bandwidth group name to find
362 * @param aBandwidthGroup where to return the found bandwidth group
363 * @param aSetError true to set extended error info on failure
364 */
365HRESULT BandwidthControl::i_getBandwidthGroupByName(const com::Utf8Str &aName,
366 ComObjPtr<BandwidthGroup> &aBandwidthGroup,
367 bool aSetError /* = false */)
368{
369 AssertReturn(!aName.isEmpty(), E_INVALIDARG);
370
371 for (BandwidthGroupList::const_iterator it = m->llBandwidthGroups->begin();
372 it != m->llBandwidthGroups->end();
373 ++it)
374 {
375 if ((*it)->i_getName() == aName)
376 {
377 aBandwidthGroup = (*it);
378 return S_OK;
379 }
380 }
381
382 if (aSetError)
383 return setError(VBOX_E_OBJECT_NOT_FOUND,
384 tr("Could not find a bandwidth group named '%s'"),
385 aName.c_str());
386 return VBOX_E_OBJECT_NOT_FOUND;
387}
388// To do
389HRESULT BandwidthControl::createBandwidthGroup(const com::Utf8Str &aName,
390 BandwidthGroupType_T aType,
391 LONG64 aMaxBytesPerSec)
392{
393 if (aMaxBytesPerSec < 0)
394 return setError(E_INVALIDARG,
395 tr("Bandwidth group limit cannot be negative"));
396
397 /* the machine needs to be mutable */
398 AutoMutableStateDependency adep(m->pParent);
399 if (FAILED(adep.rc())) return adep.rc();
400
401 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
402
403 /* try to find one with the name first. */
404 ComObjPtr<BandwidthGroup> group;
405 HRESULT rc = i_getBandwidthGroupByName(aName, group, false /* aSetError */);
406
407 if (SUCCEEDED(rc))
408 return setError(VBOX_E_OBJECT_IN_USE,
409 tr("Bandwidth group named '%s' already exists"),
410 aName.c_str());
411
412 group.createObject();
413
414 rc = group->init(this, aName, aType, aMaxBytesPerSec);
415 if (FAILED(rc)) return rc;
416
417 m->pParent->i_setModified(Machine::IsModified_BandwidthControl);
418 m->llBandwidthGroups.backup();
419 m->llBandwidthGroups->push_back(group);
420
421 return S_OK;
422}
423
424HRESULT BandwidthControl::deleteBandwidthGroup(const com::Utf8Str &aName)
425{
426 /* the machine needs to be mutable */
427 AutoMutableStateDependency adep(m->pParent);
428 if (FAILED(adep.rc())) return adep.rc();
429
430 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
431
432 ComObjPtr<BandwidthGroup> group;
433 HRESULT rc = i_getBandwidthGroupByName(aName, group, true /* aSetError */);
434 if (FAILED(rc)) return rc;
435
436 if (group->i_getReferences() != 0)
437 return setError(VBOX_E_OBJECT_IN_USE,
438 tr("The bandwidth group '%s' is still in use"), aName.c_str());
439
440 /* We can remove it now. */
441 m->pParent->i_setModified(Machine::IsModified_BandwidthControl);
442 m->llBandwidthGroups.backup();
443
444 group->i_unshare();
445
446 m->llBandwidthGroups->remove(group);
447
448 /* inform the direct session if any */
449 alock.release();
450 //onStorageControllerChange(); @todo
451
452 return S_OK;
453}
454
455HRESULT BandwidthControl::getNumGroups(ULONG *aNumGroups)
456{
457 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
458
459 *aNumGroups = m->llBandwidthGroups->size();
460
461 return S_OK;
462}
463
464HRESULT BandwidthControl::getBandwidthGroup(const com::Utf8Str &aName, ComPtr<IBandwidthGroup> &aBandwidthGroup)
465{
466 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
467
468 ComObjPtr<BandwidthGroup> group;
469 HRESULT rc = i_getBandwidthGroupByName(aName, group, true /* aSetError */);
470
471 if (SUCCEEDED(rc))
472 group.queryInterfaceTo(aBandwidthGroup.asOutParam());
473
474 return rc;
475}
476
477HRESULT BandwidthControl::getAllBandwidthGroups(std::vector<ComPtr<IBandwidthGroup> > &aBandwidthGroups)
478{
479 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
480 aBandwidthGroups.resize(0);
481 BandwidthGroupList::const_iterator it;
482 for (it = m->llBandwidthGroups->begin();
483 it != m->llBandwidthGroups->end();
484 ++it)
485 aBandwidthGroups.push_back(*it);
486
487 return S_OK;
488}
489
490HRESULT BandwidthControl::i_loadSettings(const settings::IOSettings &data)
491{
492 HRESULT rc = S_OK;
493
494 AutoCaller autoCaller(this);
495 AssertComRCReturnRC(autoCaller.rc());
496 settings::BandwidthGroupList::const_iterator it;
497 for (it = data.llBandwidthGroups.begin();
498 it != data.llBandwidthGroups.end();
499 ++it)
500 {
501 const settings::BandwidthGroup &gr = *it;
502 rc = createBandwidthGroup(gr.strName, gr.enmType, gr.cMaxBytesPerSec);
503 if (FAILED(rc)) break;
504 }
505
506 return rc;
507}
508
509HRESULT BandwidthControl::i_saveSettings(settings::IOSettings &data)
510{
511 AutoCaller autoCaller(this);
512 if (FAILED(autoCaller.rc())) return autoCaller.rc();
513
514 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
515 data.llBandwidthGroups.clear();
516 BandwidthGroupList::const_iterator it;
517 for (it = m->llBandwidthGroups->begin();
518 it != m->llBandwidthGroups->end();
519 ++it)
520 {
521 AutoWriteLock groupLock(*it COMMA_LOCKVAL_SRC_POS);
522 settings::BandwidthGroup group;
523
524 group.strName = (*it)->i_getName();
525 group.enmType = (*it)->i_getType();
526 group.cMaxBytesPerSec = (*it)->i_getMaxBytesPerSec();
527
528 data.llBandwidthGroups.push_back(group);
529 }
530
531 return S_OK;
532}
533
534Machine * BandwidthControl::i_getMachine() const
535{
536 return m->pParent;
537}
538
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