VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/ResourceStoreImpl.cpp@ 106061

Last change on this file since 106061 was 106061, checked in by vboxsync, 4 days ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1/* $Id: ResourceStoreImpl.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VirtualBox COM resource store class implementation
4 */
5
6/*
7 * Copyright (C) 2023-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN_RESOURCESTORE
29#include "LoggingNew.h"
30
31#include "ResourceStoreImpl.h"
32#include "ConsoleImpl.h"
33#include "VirtualBoxImpl.h"
34
35#include "AutoCaller.h"
36
37#include <VBox/com/array.h>
38#include <VBox/vmm/pdmdrv.h>
39#include <VBox/err.h>
40
41#include <iprt/cpp/utils.h>
42#include <iprt/file.h>
43#include <iprt/vfs.h>
44
45
46// defines
47////////////////////////////////////////////////////////////////////////////////
48
49
50// globals
51////////////////////////////////////////////////////////////////////////////////
52
53/**
54 * Resource store driver instance data.
55 */
56typedef struct DRVMAINRESOURCESTORE
57{
58 /** Pointer to the keyboard object. */
59 ResourceStore *pResourceStore;
60 /** Pointer to the driver instance structure. */
61 PPDMDRVINS pDrvIns;
62 /** Our VFS connector interface. */
63 PDMIVFSCONNECTOR IVfs;
64} DRVMAINRESOURCESTORE, *PDRVMAINRESOURCESTORE;
65
66/** The resource store map keyed by namespace/entity. */
67typedef std::map<Utf8Str, RTVFSFILE> ResourceStoreMap;
68/** The resource store map iterator. */
69typedef std::map<Utf8Str, RTVFSFILE>::iterator ResourceStoreIter;
70
71struct BackupableResourceStoreData
72{
73 BackupableResourceStoreData()
74 { }
75
76 /** The resource store. */
77 ResourceStoreMap mapResources;
78};
79
80/////////////////////////////////////////////////////////////////////////////
81// ResourceStore::Data structure
82/////////////////////////////////////////////////////////////////////////////
83
84struct ResourceStore::Data
85{
86 Data()
87 : pParent(NULL)
88 { }
89
90 /** The Console owning this resource store. */
91 Console * const pParent;
92 /** Number of references held to this resource store from the various devices/drivers. */
93 volatile uint32_t cRefs;
94
95 Backupable<BackupableResourceStoreData> bd;
96};
97
98// constructor / destructor
99////////////////////////////////////////////////////////////////////////////////
100
101DEFINE_EMPTY_CTOR_DTOR(ResourceStore)
102
103HRESULT ResourceStore::FinalConstruct()
104{
105 return BaseFinalConstruct();
106}
107
108void ResourceStore::FinalRelease()
109{
110 uninit();
111 BaseFinalRelease();
112}
113
114
115// public initializer/uninitializer for internal purposes only
116/////////////////////////////////////////////////////////////////////////////
117
118/**
119 * Initializes the resource store object.
120 *
121 * @returns COM result indicator
122 * @param aParent Handle of our parent object
123 */
124HRESULT ResourceStore::init(Console *aParent)
125{
126 LogFlowThisFunc(("aParent=%p\n", aParent));
127
128 ComAssertRet(aParent, E_INVALIDARG);
129
130 /* Enclose the state transition NotReady->InInit->Ready */
131 AutoInitSpan autoInitSpan(this);
132 AssertReturn(autoInitSpan.isOk(), E_FAIL);
133
134 m = new Data();
135
136 unconst(m->pParent) = aParent;
137
138 m->bd.allocate();
139
140 /* Confirm a successful initialization */
141 autoInitSpan.setSucceeded();
142
143 return S_OK;
144}
145
146
147/**
148 * Uninitializes the instance and sets the ready flag to FALSE.
149 * Called either from FinalRelease() or by the parent when it gets destroyed.
150 */
151void ResourceStore::uninit()
152{
153 LogFlowThisFuncEnter();
154
155 /* Enclose the state transition Ready->InUninit->NotReady */
156 AutoUninitSpan autoUninitSpan(this);
157 if (autoUninitSpan.uninitDone())
158 return;
159
160 unconst(m->pParent) = NULL;
161
162 /* Delete the store content. */
163 ResourceStoreIter it = m->bd->mapResources.begin();
164 while (it != m->bd->mapResources.end())
165 {
166 RTVfsFileRelease(it->second);
167 it++;
168 }
169
170 m->bd->mapResources.clear();
171 m->bd.free();
172
173 delete m;
174 m = NULL;
175
176 LogFlowThisFuncLeave();
177}
178
179
180/**
181 * Adds the given item to the store under the namespace and path.
182 *
183 * @returns VBox status code.
184 * @param pszNamespace The namespace of the item.
185 * @param pszPath The path to the item.
186 * @param hVfsFile The item data as a VFS file handle, a reference is retained on success.
187 */
188int ResourceStore::i_addItem(const char *pszNamespace, const char *pszPath, RTVFSFILE hVfsFile)
189{
190 Utf8Str strKey;
191 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
192 AssertRCReturn(vrc, vrc);
193
194 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
195 try
196 {
197 RTVfsFileRetain(hVfsFile);
198 m->bd->mapResources[strKey] = hVfsFile;
199 }
200 catch (...)
201 {
202 AssertLogRelFailed();
203 vrc = VERR_UNEXPECTED_EXCEPTION;
204 }
205
206 return vrc;
207}
208
209
210//
211// private methods
212//
213/*static*/
214DECLCALLBACK(int) ResourceStore::i_resourceStoreQuerySize(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath,
215 uint64_t *pcb)
216{
217 PDRVMAINRESOURCESTORE pThis = RT_FROM_MEMBER(pInterface, DRVMAINRESOURCESTORE, IVfs);
218
219 Utf8Str strKey;
220 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
221 AssertRCReturn(vrc, vrc);
222
223 AutoReadLock rlock(pThis->pResourceStore COMMA_LOCKVAL_SRC_POS);
224 ResourceStoreIter it = pThis->pResourceStore->m->bd->mapResources.find(strKey);
225 if (it != pThis->pResourceStore->m->bd->mapResources.end())
226 {
227 RTVFSFILE hVfsFile = it->second;
228 return RTVfsFileQuerySize(hVfsFile, pcb);
229 }
230
231 return VERR_NOT_FOUND;
232}
233
234
235/*static*/
236DECLCALLBACK(int) ResourceStore::i_resourceStoreReadAll(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath,
237 void *pvBuf, size_t cbRead)
238{
239 PDRVMAINRESOURCESTORE pThis = RT_FROM_MEMBER(pInterface, DRVMAINRESOURCESTORE, IVfs);
240
241 Utf8Str strKey;
242 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
243 AssertRCReturn(vrc, vrc);
244
245 AutoReadLock rlock(pThis->pResourceStore COMMA_LOCKVAL_SRC_POS);
246 ResourceStoreIter it = pThis->pResourceStore->m->bd->mapResources.find(strKey);
247 if (it != pThis->pResourceStore->m->bd->mapResources.end())
248 {
249 RTVFSFILE hVfsFile = it->second;
250
251 vrc = RTVfsFileSeek(hVfsFile, 0 /*offSeek*/, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
252 AssertLogRelRC(vrc);
253
254 return RTVfsFileRead(hVfsFile, pvBuf, cbRead, NULL /*pcbRead*/);
255 }
256
257 return VERR_NOT_FOUND;
258}
259
260
261/*static*/
262DECLCALLBACK(int) ResourceStore::i_resourceStoreWriteAll(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath,
263 const void *pvBuf, size_t cbWrite)
264{
265 PDRVMAINRESOURCESTORE pThis = RT_FROM_MEMBER(pInterface, DRVMAINRESOURCESTORE, IVfs);
266
267 Utf8Str strKey;
268 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
269 AssertRCReturn(vrc, vrc);
270
271 AutoWriteLock wlock(pThis->pResourceStore COMMA_LOCKVAL_SRC_POS);
272
273 ResourceStoreIter it = pThis->pResourceStore->m->bd->mapResources.find(strKey);
274 if (it != pThis->pResourceStore->m->bd->mapResources.end())
275 {
276 RTVFSFILE hVfsFile = it->second;
277
278 vrc = RTVfsFileSeek(hVfsFile, 0 /*offSeek*/, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
279 AssertLogRelRC(vrc);
280 vrc = RTVfsFileSetSize(hVfsFile, cbWrite, RTVFSFILE_SIZE_F_NORMAL);
281 if (RT_SUCCESS(vrc))
282 vrc = RTVfsFileWrite(hVfsFile, pvBuf, cbWrite, NULL /*pcbWritten*/);
283 }
284 else
285 {
286 /* Create a new entry. */
287 RTVFSFILE hVfsFile = NIL_RTVFSFILE;
288 vrc = RTVfsFileFromBuffer(RTFILE_O_READ | RTFILE_O_WRITE, pvBuf, cbWrite, &hVfsFile);
289 if (RT_SUCCESS(vrc))
290 {
291 try
292 {
293 pThis->pResourceStore->m->bd->mapResources[strKey] = hVfsFile;
294 }
295 catch (...)
296 {
297 AssertLogRelFailed();
298 RTVfsFileRelease(hVfsFile);
299 vrc = VERR_UNEXPECTED_EXCEPTION;
300 }
301 }
302 }
303
304 return vrc;
305}
306
307
308/*static*/
309DECLCALLBACK(int) ResourceStore::i_resourceStoreDelete(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath)
310{
311 PDRVMAINRESOURCESTORE pThis = RT_FROM_MEMBER(pInterface, DRVMAINRESOURCESTORE, IVfs);
312
313 Utf8Str strKey;
314 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
315 AssertRCReturn(vrc, vrc);
316
317 AutoWriteLock wlock(pThis->pResourceStore COMMA_LOCKVAL_SRC_POS);
318 ResourceStoreIter it = pThis->pResourceStore->m->bd->mapResources.find(strKey);
319 if (it != pThis->pResourceStore->m->bd->mapResources.end())
320 {
321 RTVFSFILE hVfsFile = it->second;
322 pThis->pResourceStore->m->bd->mapResources.erase(it);
323 RTVfsFileRelease(hVfsFile);
324 return VINF_SUCCESS;
325 }
326
327 return VERR_NOT_FOUND;
328}
329
330
331/**
332 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
333 */
334DECLCALLBACK(void *) ResourceStore::i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
335{
336 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
337 PDRVMAINRESOURCESTORE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINRESOURCESTORE);
338
339 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
340 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIVFSCONNECTOR, &pDrv->IVfs);
341 return NULL;
342}
343
344
345/**
346 * Destruct a resource store driver instance.
347 *
348 * @param pDrvIns The driver instance data.
349 */
350DECLCALLBACK(void) ResourceStore::i_drvDestruct(PPDMDRVINS pDrvIns)
351{
352 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
353 PDRVMAINRESOURCESTORE pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINRESOURCESTORE);
354 LogFlow(("ResourceStore::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
355
356 if (pThis->pResourceStore)
357 {
358 ASMAtomicDecU32(&pThis->pResourceStore->m->cRefs);
359 pThis->pResourceStore = NULL;
360 }
361}
362
363
364/**
365 * Construct a resource store driver instance.
366 *
367 * @copydoc FNPDMDRVCONSTRUCT
368 */
369DECLCALLBACK(int) ResourceStore::i_drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
370{
371 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
372 RT_NOREF(fFlags, pCfg);
373 PDRVMAINRESOURCESTORE pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINRESOURCESTORE);
374 LogFlow(("ResourceStore::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
375
376 /*
377 * Validate configuration.
378 */
379 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "", "");
380 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
381 ("Configuration error: Not possible to attach anything to this driver!\n"),
382 VERR_PDM_DRVINS_NO_ATTACH);
383
384 /*
385 * IBase.
386 */
387 pDrvIns->IBase.pfnQueryInterface = ResourceStore::i_drvQueryInterface;
388
389 pThis->IVfs.pfnQuerySize = ResourceStore::i_resourceStoreQuerySize;
390 pThis->IVfs.pfnReadAll = ResourceStore::i_resourceStoreReadAll;
391 pThis->IVfs.pfnWriteAll = ResourceStore::i_resourceStoreWriteAll;
392 pThis->IVfs.pfnDelete = ResourceStore::i_resourceStoreDelete;
393
394 /*
395 * Get the resource store object pointer.
396 */
397 com::Guid uuid(COM_IIDOF(IResourceStore));
398 pThis->pResourceStore = (ResourceStore *)PDMDrvHlpQueryGenericUserObject(pDrvIns, uuid.raw());
399 if (!pThis->pResourceStore)
400 {
401 AssertMsgFailed(("Configuration error: No/bad resource store object!\n"));
402 return VERR_NOT_FOUND;
403 }
404
405 ASMAtomicIncU32(&pThis->pResourceStore->m->cRefs);
406 return VINF_SUCCESS;
407}
408
409
410/**
411 * Resource store driver registration record.
412 */
413const PDMDRVREG ResourceStore::DrvReg =
414{
415 /* u32Version */
416 PDM_DRVREG_VERSION,
417 /* szName */
418 "ResourceStore",
419 /* szRCMod */
420 "",
421 /* szR0Mod */
422 "",
423 /* pszDescription */
424 "Main resource store driver (Main as in the API).",
425 /* fFlags */
426 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
427 /* fClass. */
428 PDM_DRVREG_CLASS_STATUS,
429 /* cMaxInstances */
430 ~0U,
431 /* cbInstance */
432 sizeof(DRVMAINRESOURCESTORE),
433 /* pfnConstruct */
434 ResourceStore::i_drvConstruct,
435 /* pfnDestruct */
436 ResourceStore::i_drvDestruct,
437 /* pfnRelocate */
438 NULL,
439 /* pfnIOCtl */
440 NULL,
441 /* pfnPowerOn */
442 NULL,
443 /* pfnReset */
444 NULL,
445 /* pfnSuspend */
446 NULL,
447 /* pfnResume */
448 NULL,
449 /* pfnAttach */
450 NULL,
451 /* pfnDetach */
452 NULL,
453 /* pfnPowerOff */
454 NULL,
455 /* pfnSoftReset */
456 NULL,
457 /* u32EndVersion */
458 PDM_DRVREG_VERSION
459};
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