forked from GPUOpen-Drivers/pal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpalCacheLayer.h
639 lines (583 loc) · 30.6 KB
/
palCacheLayer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
/*
***********************************************************************************************************************
*
* Copyright (c) 2018-2024 Advanced Micro Devices, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************************************************************************/
/**
***********************************************************************************************************************
* @file palCacheLayer.h
* @brief PAL cache-utility library cache layer common interface declaraion.
***********************************************************************************************************************
*/
#pragma once
#include "palUtil.h"
#include "palMetroHash.h"
#include "palHashSet.h"
#include "palSysMemory.h"
namespace Pal
{
class IDevice;
class IPlatform;
}
namespace Util
{
/// Common declaration for an expected 128-bit hash value
using Hash128 = MetroHash::Hash;
class ICacheLayer;
class IArchiveFile;
class IPlatformKey;
/**
***********************************************************************************************************************
* @brief Lookup result from ICacheLayer::Query, entryId is specific to the cache layer it was queried from
***********************************************************************************************************************
*/
struct QueryResult
{
ICacheLayer* pLayer; ///< Pointer to the layer that responded to the query
Hash128 hashId; ///< HashId referenced during query
size_t dataSize; ///< Size of original data submitted to cache
size_t storeSize; ///< Size of data stored in cache, which was possibly compressed down from dataSize.
size_t promotionSize; ///< Size to use when storing in another cache
union
{
uint64 entryId; ///< Unique entry id corresponding to found result
void* pEntryInfo; ///< Private pointer to entry data corresponding to found result
} context;
};
/**
***********************************************************************************************************************
* @brief Common cache layer interface. Allows all cache layers to be interfaced with agnostically
***********************************************************************************************************************
*/
class ICacheLayer
{
public:
// Link Policy bitfield. Provides a hint as to how this layer should interact with the next
enum LinkPolicy : uint32
{
// Common flags
PassData = 0x1 << 0, ///< Data should be passed to (or read from) the next layer
PassCalls = 0x1 << 1, ///< Function calls should be passed to the next layer
Skip = 0x1 << 2, ///< Load/Store Operations should skip this layer
// Store flags
BatchStore = 0x1 << 10, ///< Delay passing data to the next layer and batch for later
// Load flags
LoadOnQuery = 0x1 << 16 ///< Load data from the next layer at query time rather than load
};
// Query flags bitfield. Specify some behaviors to Query().
enum QueryFlags : uint32
{
ReserveEntryOnMiss = 0x1 << 0, ///< Reserve an entry on miss
AcquireEntryRef = 0x1 << 1, ///< Increase the cache entry reference, equivalent of AcquireCacheRef(), so
///< user must call ReleaseCacheRef() when not needing that entry.
};
/// Query for data by hash key
///
/// @param [in] pHashId 128-bit precomputed hash used as a reference id for the cache entry
/// @param [in] policy Allow Query to specify policy, like promote data from file layer to memory cache layer.
/// @param [in] flags Specify some behaviors to Query
/// @param [out] pQuery Query result containing the entry id and buffer size needed to call ICacheLayer::Load()
///
/// @return Success if the hash id was found. Otherwise, one of the following may be returned:
/// + Reserved returned if ReserveEntryOnMiss was specified, the entry was not found, and the entry was
/// successfully reserved.
/// + NotFound if no values was found for the given hash
/// + NotReady if the hash ID was found but the data is not yet ready
/// + ErrorInvalidPointer if pQuery or pHashId are nullptr
/// + ErrorUnknown if there is an internal error.
/// + Unsupported if the cache does not support it.
///
/// @note If pQuery->dataSize == 0, the result should be treated as if NotReady were returned
virtual Result Query(
const Hash128* pHashId,
uint32 policy,
uint32 flags,
QueryResult* pQuery) = 0;
/// Store data with corresponding hash key
///
/// @param [in] storeFlags Options for this store operation
/// @param [in] pHashId 128-bit precomputed hash used as a reference id for the cache entry
/// @param [in] pData Data to be stored in the cache
/// @param [in] dataSize Size of data to be stored
/// @param [in] storeSize Size of the buffer to be used to store the data.
/// Usually 0 except in cases of compression.
/// This allows us to *actually* store less than dataSize,
/// while tracking that we've stored dataSize worth of information.
///
/// @return Success if the data was stored under the hash id. Otherwise, one of the following may be returned:
/// + AlreadyExists if a value already exists for the given hash ID. Previous data will not be overwritten.
/// + Unsupported if the cache cannot complete the operation (eg: read-only or does not support reservation)
/// + ErrorInvalidPointer if pHashId is nullptr.
/// + ErrorUnknown if there is an internal error.
///
/// @note The id in the cache could be already reserved by Query with ReserveEntryOnMiss. Later, when the data is
/// ready, call `Store` again with the same hash ID but with valid pData and datasize. The expected return
/// code in this situation is expected to be Success and not AlreadyExists.
virtual Result Store(
Util::StoreFlags storeFlags,
const Hash128* pHashId,
const void* pData,
size_t dataSize,
size_t storeSize = 0
) = 0;
/// Accquire a long-lived reference to a cache object
///
/// @note The result populated by QueryResult will not be evicted until `ReleaseCacheRef()` is called.
///
/// The primary purpose is a "zero-copy" style hit where the underlying data in the cache can be directly
/// accessed by the caller using `ppData`. However in cases where the internal representation is not usable
/// this function may still serve as a way to ensure that a delayed call to `Load()` will not result in
/// failure due to eviction where supported.
///
/// @param [in] pQuery Query result containing the entry id and buffer size needed to call ICacheLayer::Load()
///
/// @return Success if the responder is able to provide an externally managed lifetime reference. Otherwise, one of
/// the following may be returned:
/// + ErrorInvalidPointer if pQuery or pHashId are nullptr
/// + NotFound if entryId is not present in cache
/// + Unsupported if the cache does not support external references
/// + ErrorUnknown if there is an internal error.
///
/// @note It is considered undefined behaviour to call function on any layer that did not directly respond to your
/// query as pQuery->pLayer
virtual Result AcquireCacheRef(
const QueryResult* pQuery)
{
PAL_ASSERT(pQuery != nullptr);
PAL_ASSERT(this == pQuery->pLayer);
return Result::Unsupported;
}
/// Decriment the external reference count for a cache item
///
/// @param [in] pQuery Query previously passed into ICacheLayer::AccquireCacheRef()
///
/// @return Success if the cache is able to release the external reference. Otherwise, one of the following may be
/// returned:
/// + Unsupported if the cache does not support external references
/// + ErrorUnknown if there is an internal error.
///
/// @note: The pointer to memory previously returned by AccquireCacheRef() is not garunteed to be valid after
/// this call and MUST not be accessed.
///
/// @note It is considered undefined behaviour to call function on any layer that did not directly respond to your
/// query as pQuery->pLayer
virtual Result ReleaseCacheRef(
const QueryResult* pQuery)
{
PAL_ASSERT(pQuery != nullptr);
PAL_ASSERT(this == pQuery->pLayer);
return Result::Unsupported;
}
/// Return the pointer to internal cache memory if available
///
/// @param [in] pQuery Result returned from ICacheLayer::Query()
/// @param [out] ppData Pointer to raw cache storage
///
/// @return Success if the cache is able to accquire a read-lock on ppData. Otherwise, one of the following may be
/// returned:
/// + NotFound if entryId is not present in cache
/// + NotReady if entryId is in the cache but the data cannot be accessed yet
/// + ErrorInvalidArgument if the entry has not previously been incremented by AddCacheRef()
/// + Unsupported if the cache (or entry) does not support internal data access
/// + ErrorUnknown if there is an internal error.
///
/// @note ppData is intended to be a "Zero-copy" return from this function. No additional buffer allocations
/// should be performed. Data within the cache layer may be in an internal format and not suitable for
/// direct use. In this case ppData MUST be set to nullptr and Result::Unsupported returned.
///
/// @note It is considered undefined behaviour to call function on any layer that did not directly respond to your
/// query as pQuery->pLayer
virtual Result GetCacheData(
const QueryResult* pQuery,
const void** ppData)
{
PAL_ASSERT(pQuery != nullptr);
PAL_ASSERT(ppData != nullptr);
PAL_ASSERT(this == pQuery->pLayer);
*ppData = nullptr;
return Result::Unsupported;
}
/// Wait for an entry that is not ready.
///
/// @param [in] pHashId 128-bit precomputed hash used as a reference id for the cache entry
///
/// @return Success if the entry is ready. Otherwise, one of the following may be returned:
/// + NotFound if no values was found for the given hash
/// + Unsupported if the cache does not support explicit eviction
/// + ErrorInvalidValue if the entry is bad.
/// + ErrorInvalidPointer if pHashId is nullptr.
/// + ErrorUnknown if there is an internal error.
virtual Result WaitForEntry(
const Hash128* pHashId)
{
return Result::Unsupported;
}
/// Explicitly remove data with corresponding hash key
///
/// @param [in] pHashId 128-bit precomputed hash used as a reference id for the cache entry
///
/// @return Success if the data was stored under the hash id. Otherwise, one of the following may be returned:
/// + NotFound if no values was found for the given hash
/// + Unsupported if the cache does not support explicit eviction
/// + ErrorInvalidPointer if pHashId is nullptr.
/// + ErrorUnknown if there is an internal error.
virtual Result Evict(
const Hash128* pHashId)
{
return Result::Unsupported;
}
/// Mark the Entry as bad with corresponding hash key
/// An Entry could be reserved first and update data later, if the data is generated failly, we need mark previous
/// reserved Entry as bad. After it's marked bad, it will be evicted when its refcount becomes zero.
///
/// @param [in] pHashId 128-bit precomputed hash used as a reference id for the cache entry
///
/// @return Success if the data is marked bad under the hash id. Otherwise, one of the following may be returned:
/// + NotFound if no values was found for the given hash
/// + Unsupported if the cache does not support this behavior
/// + ErrorInvalidPointer if pHashId is nullptr.
/// + ErrorUnknown if there is an internal error.
virtual Result MarkEntryBad(
const Hash128* pHashId)
{
return Result::Unsupported;
}
/// Load data from cache to buffer by entry id retrieved from Query()
///
/// @param [in] pQuery Result returned from ICacheLayer::Query()
/// @param [out] pBuffer Buffer to place data from cache
///
/// @return Success if data was loaded to the provided buffer. Otherwise, one of the following may be returned:
/// + NotFound if entryId is not present in cache
/// + NotReady if entryId is reserved in the cache but the data is not ready
/// + ErrorInvalidPointer if pBuffer is nullptr
/// + ErrorUnknown if there is an internal error.
virtual Result Load(
const QueryResult* pQuery,
void* pBuffer) = 0;
/// Link one cache layer on top of another, does not transfer ownership of the object
///
/// @param [in] pNextLayer ICacheLayer object to become the next layer under this layer
///
/// @return Success if the cache layers were linked together. Otherwise, one of the following may be returned:
/// + ErrorInvalidPointer if pNextLayer is nullptr
/// + ErrorUnknown if there is an internal error.
virtual Result Link(
ICacheLayer* pNextLayer) = 0;
/// Set the layer's link policy for loading
///
/// @param [in] loadPolicy LinkPolicy flags indicating preferred behaviour on Query/Load where available
///
/// @return Success if the load policy was applied. Otherwise, one of the following may be returned:
/// + ErrorInvalidValue if an invalid policy is provided
/// + ErrorUnknown if there is an internal error.
virtual Result SetLoadPolicy(
uint32 loadPolicy) = 0;
/// Set the layer's link policy for storing
///
/// @param [in] storePolicy LinkPolicy flags indicating preferred behaviour on Store where available
///
/// @return Success if the load policy was applied. Otherwise, one of the following may be returned:
/// + ErrorInvalidValue if an invalid policy is provided
/// + ErrorUnknown if there is an internal error.
virtual Result SetStorePolicy(
uint32 storePolicy) = 0;
/// Retrieve the layer beneath this layer
///
/// @return Pointer to the layer linked beneath this layer. Nullptr if layer is not linked.
virtual ICacheLayer* GetNextLayer() const = 0;
/// Retrieve the layer's link policy for loading
///
/// @return Link policy used during Load().
virtual uint32 GetLoadPolicy() const = 0;
/// Retrieve the layer's link policy for storing
///
/// @return Link policy used during Store().
virtual uint32 GetStorePolicy() const = 0;
/// Destroy Cache Layer
virtual void Destroy() = 0;
protected:
ICacheLayer() {}
virtual ~ICacheLayer() {}
private:
PAL_DISALLOW_COPY_AND_ASSIGN(ICacheLayer);
};
/**
***********************************************************************************************************************
* @brief Common cache layer construction information
***********************************************************************************************************************
*/
struct CacheLayerBaseCreateInfo
{
AllocCallbacks* pCallbacks; ///< Memory allocation callbacks to be used by the caching layer for all long term
/// storage. Allocation callbacks must be valid for the life of the cache layer
};
/**
***********************************************************************************************************************
* @brief Information needed to create an in-memory key-value store
***********************************************************************************************************************
*/
struct MemoryCacheCreateInfo
{
CacheLayerBaseCreateInfo baseInfo; ///< Base cache layer creation info
size_t maxObjectCount; ///< Maximum number of entries in cache
size_t maxMemorySize; ///< Maximum total size of entries in cache
uint32 expectedEntries; ///< Expected number of entries in cache
bool evictOnFull; ///< Whether or not the cache should evict entries based on LRU to
/// make room for new ones
bool evictDuplicates; ///< Whether or not the cache should evict entries with a duplicate hash
};
/// Get the memory size for a in-memory cache layer
///
/// @param [in] pCreateInfo Information about cache being created
///
/// @return Minimum size of memory buffer needed to pass to CreateMemoryCacheLayer()
size_t GetMemoryCacheLayerSize(
const MemoryCacheCreateInfo* pCreateInfo);
/// Create an in-memory key-value caching layer
///
/// @param [in] pCreateInfo Information about cache being created
/// @param [in] pPlacementAddr Pointer to the location where the interface should be constructed. There must
/// be as much size available here as reported by calling GetMemoryCacheLayerSize().
/// @param [out] ppCacheLayer Cache layer interface. On failure this value will be set to nullptr.
///
/// @returns Success if the cache layer was created. Otherwise, one of the following errors may be returned:
/// + ErrorUnknown if there is an internal error.
Result CreateMemoryCacheLayer(
const MemoryCacheCreateInfo* pCreateInfo,
void* pPlacementAddr,
ICacheLayer** ppCacheLayer);
/// Get memoryCache entries number and total cache data size
///
/// @param [in] pCacheLayer memory cache layer to be serialized.
/// @param [out] pCurCount return entries number in memoryCache.
/// @param [out] pCurSize return total cache data size in memoryCache.
///
/// @return Success if serialize is successful.
Result GetMemoryCacheLayerCurSize(
ICacheLayer* pCacheLayer,
size_t* pCurCount,
size_t* pCurSize);
/// Get all hashIds in entries in memoryCache
///
/// @param [in] pCacheLayer memory cache layer to be serialized.
/// @param [in] curCount return entries number in memoryCache.
/// @param [out] pHashIds return total cache HashIds in memoryCache.
///
/// @return Success if serialize is successful.
Result GetMemoryCacheLayerHashIds(
ICacheLayer* pCacheLayer,
size_t curCount,
Hash128* pHashIds);
/**
***********************************************************************************************************************
* @brief Information needed to create an archive file backed key-value store
***********************************************************************************************************************
*/
struct ArchiveFileCacheCreateInfo
{
CacheLayerBaseCreateInfo baseInfo; ///< Base cache layer creation info.
IArchiveFile* pFile; ///< Archive file to use for storage, must exist for the lifetime of the
/// cache layer. May be shared between multiple layers but no internal
/// thread safety is provided.
const IPlatformKey* pPlatformKey; ///< Optional platform key, allows for data stored to the archive file
/// to be keyed to a specific driver/platform fingerprint.
uint32 dataTypeId; ///< Optional 32-bit data type identifier, allows heterogenous data to be
/// stored within an archive file.
};
/// Get the memory size for a archive file backed cache layer
///
/// @param [in] pCreateInfo Information about cache being created
///
/// @return Minimum size of memory buffer needed to pass to CreateArchiveFileCacheLayer()
size_t GetArchiveFileCacheLayerSize(
const ArchiveFileCacheCreateInfo* pCreateInfo);
/// Create an archive file backed caching layer
///
/// @param [in] pCreateInfo Information about cache being created
/// @param [in] pPlacementAddr Pointer to the location where the interface should be constructed. There must
/// be as much size available here as reported by calling
/// GetArchiveFileCacheLayerSize().
/// @param [out] ppCacheLayer Cache layer interface. On failure this value will be set to nullptr.
///
/// @returns Success if the cache layer was created. Otherwise, one of the following errors may be returned:
/// + ErrorUnknown if there is an internal error.
Result CreateArchiveFileCacheLayer(
const ArchiveFileCacheCreateInfo* pCreateInfo,
void* pPlacementAddr,
ICacheLayer** ppCacheLayer);
/// Get file archive cache entry count and file size
///
/// @param [in] pCacheLayer file archive to be examined
/// @param [out] pCurCount return current entry count
/// @param [out] pCurSize return current file size
///
/// @return Success if read is successful.
Result GetArchiveFileCacheLayerCurSize(
ICacheLayer* pCacheLayer,
uint64* pCurCount,
uint64* pCurSize);
/**
***********************************************************************************************************************
* @brief Information needed to create a pipeline content tracker
***********************************************************************************************************************
*/
struct TrackingCacheCreateInfo
{
AllocCallbacks* pCallbacks; ///< Memory allocation callbacks to be used by the caching layer for all long term
/// storage. Allocation callbacks must be valid for the life of the cache layer
};
using TrackedHashSet = HashSet<
Hash128,
ForwardAllocator,
MetroHash::HashFunc>;
using TrackedHashIter = TrackedHashSet::Iterator;
using GetTrackedHashes = TrackedHashIter(*)(const ICacheLayer*);
/// Get the memory size for a pipeline tracking cache layer
///
/// @return Minimum size of memory buffer needed to pass to CreateTrackingCacheLayer()
size_t GetTrackingCacheLayerSize();
/// Create a pipeline tracking cache layer
///
/// @param [in] pCreateInfo Information about cache being created
/// @param [in] pPlacementAddr Pointer to the location where the interface should be constructed. There
/// must be as much size available here as reported by calling
/// GetTrackingCacheLayerSize().
/// @param [out] ppCacheLayer Cache layer interface. On failure this value will be set to nullptr.
/// @param [out] ppGetTrackedHashes Function pointer for entry retrieval. On failure this value will be set to
/// nullptr.
///
/// @returns Success if the cache layer was created. Otherwise, one of the following errors may be returned:
/// + ErrorUnknown if there is an internal error.
Result CreateTrackingCacheLayer(
const TrackingCacheCreateInfo* pCreateInfo,
void* pPlacementAddr,
ICacheLayer** ppCacheLayer,
GetTrackedHashes* ppGetTrackedHashes);
/**
***********************************************************************************************************************
* @brief Information needed to create a compressing cache layer
***********************************************************************************************************************
*/
struct CompressingCacheLayerCreateInfo
{
AllocCallbacks* pCallbacks; ///< Memory allocation callbacks to be used by the caching layer for all long term
/// storage. Allocation callbacks must be valid for the life of the cache layer
bool useHighCompression; ///< True if we want to use the high compression codec,
/// which takes a bit more time to compress but decompresses just as fast.
bool decompressOnly; ///< True if we want to use the layer as a pass-through to support reading of any
/// existing compressed data.
};
/// Get the memory size for a compressing cache layer
///
/// @return Minimum size of memory buffer needed to pass to CreateCompressingCacheLayer()
size_t GetCompressingCacheLayerSize();
/// Create a compressing cache layer
///
/// @param [in] pCreateInfo Information about cache being created
/// @param [in] pPlacementAddr Pointer to the location where the interface should be constructed. There
/// must be as much size available here as reported by calling
/// GetCompressingCacheLayerSize().
/// @param [out] ppCacheLayer Cache layer interface. On failure this value will be set to nullptr.
///
/// @returns Success if the cache layer was created. Otherwise, one of the following errors may be returned:
/// + ErrorUnknown if there is an internal error.
Result CreateCompressingCacheLayer(
const CompressingCacheLayerCreateInfo* pCreateInfo,
void* pPlacementAddr,
ICacheLayer** ppCacheLayer);
/**
***********************************************************************************************************************
* @brief Information needed to create an archive-splitting multi-ELF cache layer
***********************************************************************************************************************
*/
struct MultiElfCacheLayerCreateInfo
{
CacheLayerBaseCreateInfo baseInfo; // Base cache layer creation info
ICacheLayer* pNextDataLayer; // Next layer which could service/claim a query
};
/// Get the memory size for a multi-ELF cache layer
///
/// @return Minimum size of memory buffer needed to pass to CreateMultiElfCacheLayer()
size_t GetMultiElfCacheLayerSize();
/// Create a multi-ELF cache layer
///
/// @param [in] pCreateInfo Information about cache being created
/// @param [in] pPlacementAddr Pointer to the location where the interface should be constructed. There
/// must be as much size available here as reported by calling
/// GetMultiElfCacheLayerSize().
/// @param [out] ppCacheLayer Cache layer interface. On failure this value will be set to nullptr.
///
/// @returns Success if the cache layer was created. Otherwise, one of the following errors may be returned:
/// + ErrorUnknown if there is an internal error.
Result CreateMultiElfCacheLayer(
const MultiElfCacheLayerCreateInfo* pCreateInfo,
void* pPlacementAddr,
ICacheLayer** ppCacheLayer);
/**
***********************************************************************************************************************
* @brief Detailed optional statistics for a multi-ELF cache layer's inputs and outputs. For perf testing and debug.
***********************************************************************************************************************
*/
struct MultiElfCacheLayerStatistics
{
// Layer invocation and payload
uint32 queries; // queries/stores/loads seen by this layer
uint32 stores;
uint32 loads;
uint32 archiveQueries; // queries/stores/loads handled by this layer
uint32 archiveStores;
uint32 archiveStoreSkips;
uint32 archiveLoads;
uint32 archiveMaxLength; // max size of archive in ELF count
// Hit/miss/error
uint32 elfStores; // total ELF store attempts
uint32 elfStoresExists; // exists in lower layers
uint32 elfStoresUnique; // new to lower layers
uint32 elfLoads; // total ELF load attempts
uint32 elfErrors; // error count
// Memory
size_t overhead; // cache memory used for bookkeeping
size_t elfStoreSize; // cumulative bytes of attempted ELF stores
size_t elfStoreSavings; // cumulative bytes saved by ELF already being in cache
size_t elfLoadSize; // cumulative bytes of attempted ELF loads
size_t elfLoadSavings; // cumulative bytes saved by ELF already being in cache
};
/// Get detailed statistics for multi-ELF cache layer
///
/// @param [in] pCacheLayer Multi-Elf cache layer to get statistics for
/// @param [out] pStats Output struct to populate with statistics
///
/// @return Success if querying statistics was successful.
Result GetMultiElfCacheLayerStatistics(
ICacheLayer* pCacheLayer,
MultiElfCacheLayerStatistics* pStats);
/// Inform a multi-ELF cache layer what the next data layer is.
///
/// @param [in] pCacheLayer Multi-Elf cache layer
/// @param [out] pOtherLayer Other layer, which will be handling the multi-ELF layer's adjusted payloads
///
/// @return Success if querying statistics was successful.
Result SetMultiElfCacheLayerNextDataLayer(
ICacheLayer* pCacheLayer,
ICacheLayer* pOtherLayer);
} // namespace Util