diff --git a/genode/runtimes/blob_service/runtime b/genode/runtimes/blob_service/runtime
index 45b5af0..a88725b 100644
--- a/genode/runtimes/blob_service/runtime
+++ b/genode/runtimes/blob_service/runtime
@@ -3,6 +3,7 @@
+
@@ -27,6 +28,7 @@
+
diff --git a/genode/runtimes/blobsets_fs/runtime b/genode/runtimes/blobsets_fs/runtime
index 28bf5df..9f86c90 100644
--- a/genode/runtimes/blobsets_fs/runtime
+++ b/genode/runtimes/blobsets_fs/runtime
@@ -2,6 +2,7 @@
+
diff --git a/genode/src/blobsets_fs.nim b/genode/src/blobsets_fs.nim
index 322f1aa..b50a4fe 100644
--- a/genode/src/blobsets_fs.nim
+++ b/genode/src/blobsets_fs.nim
@@ -3,7 +3,7 @@ import std/tables, std/xmltree, std/strtabs, std/strutils, std/streams, std/xmlp
import genode, genode/signals, genode/parents, genode/servers, genode/roms
-import blobsets, blobsets/filestores, ./private/filesystemsession
+import blobsets, blobsets/filestores, ./private/filesystemsession, ./private/store_reporter
const
currentPath = currentSourcePath.rsplit("/", 1)[0]
@@ -297,8 +297,8 @@ componentConstructHook = proc(env: GenodeEnv) =
var
policies = newSeq[XmlNode](8)
sessions = initTable[ServerId, SessionRef]()
- let store = newFileStore("/store")
- # Use the file-system as the store backend
+ let store = env.newStoreReporter(newFileStore("/store"))
+ # Use the file-system as the store backend, with a reporter wrapper
proc createSession(env: GenodeEnv; store: BlobStore; id: ServerId; label: string; setId: SetId; txBufSize: int) =
let
diff --git a/genode/src/private/store_reporter.nim b/genode/src/private/store_reporter.nim
new file mode 100644
index 0000000..07aac21
--- /dev/null
+++ b/genode/src/private/store_reporter.nim
@@ -0,0 +1,47 @@
+import blobsets
+import genode, genode/reports
+import std/asyncdispatch, std/asyncfutures, std/streams, std/xmltree
+
+type
+ StoreReporter = ref StoreReporterObj
+ StoreReporterObj = object of BlobStoreObj
+ store: BlobStore
+ reporter: ReportClient
+ xml: XmlNode
+ # TODO: put missing objects in a table and add
+ # a weight value that increase for each miss
+
+proc reportMissing(sr: StoreReporter; id: BlobId; kind: BlobKind) =
+ sr.xml.add <>blob(id=id.toHex, kind=($kind))
+ sr.reporter.submit do (str: Stream):
+ str.writeLine(sr.xml)
+
+proc xContains(s: BlobStore; id: BlobId; kind: BlobKind): Future[bool] {.async.} =
+ var sr = StoreReporter(s)
+ let r = await sr.store.containsImpl(sr.store, id, kind)
+ if not r:
+ sr.reportMissing(id, kind)
+ return r
+
+proc xOpenBlobStream(s: BlobStore; id: BlobId; size: BiggestInt; kind: BlobKind): BlobStream =
+ var sr = StoreReporter(s)
+ try:
+ result = sr.store.openBlobStreamImpl(sr.store, id, size, kind)
+ except KeyError:
+ sr.reportMissing(id, kind)
+ raise newException(KeyError, "blob missing blob reported")
+
+proc xOpenIngestStream(s: BlobStore; size: BiggestInt; kind: BlobKind): IngestStream =
+ var sr = StoreReporter(s)
+ sr.store.openIngestStreamImpl(sr.store, size, kind)
+
+proc newStoreReporter*(env: GenodeEnv; store: BlobStore): BlobStore =
+ ## Create a new store that reports missing blobs via a Report session.
+ StoreReporter(
+ containsImpl: xcontains,
+ openBlobStreamImpl: xopenBlobStream,
+ openIngestStreamImpl: xopenIngestStream,
+ store: store,
+ reporter: env.newReportClient("missing"),
+ xml: <>missing(),
+ )