2023-11-14 12:02:17 +00:00
|
|
|
## Nim-Codex
|
|
|
|
## Copyright (c) 2023 Status Research & Development GmbH
|
2022-03-17 13:56:46 +00:00
|
|
|
## Licensed under either of
|
|
|
|
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
|
|
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
|
|
## at your option.
|
|
|
|
## This file may not be copied, modified, or distributed except according to
|
|
|
|
## those terms.
|
|
|
|
|
2022-07-28 00:39:17 +00:00
|
|
|
import std/options
|
|
|
|
|
2022-03-21 18:09:59 +00:00
|
|
|
import pkg/upraises
|
|
|
|
|
|
|
|
push: {.upraises: [].}
|
2022-03-17 13:56:46 +00:00
|
|
|
|
|
|
|
import pkg/chronos
|
|
|
|
import pkg/stew/ptrops
|
|
|
|
|
2022-03-21 18:09:59 +00:00
|
|
|
import ../stores
|
|
|
|
import ../manifest
|
|
|
|
import ../blocktype
|
feat: create logging proxy (#663)
* implement a logging proxy
The logging proxy:
- prevents the need to import chronicles (as well as export except toJson),
- prevents the need to override `writeValue` or use or import nim-json-seralization elsewhere in the codebase, allowing for sole use of utils/json for de/serialization,
- and handles json formatting correctly in chronicles json sinks
* Rename logging -> logutils to avoid ambiguity with common names
* clean up
* add setProperty for JsonRecord, remove nim-json-serialization conflict
* Allow specifying textlines and json format separately
Not specifying a LogFormat will apply the formatting to both textlines and json sinks.
Specifying a LogFormat will apply the formatting to only that sink.
* remove unneeded usages of std/json
We only need to import utils/json instead of std/json
* move serialization from rest/json to utils/json so it can be shared
* fix NoColors ambiguity
Was causing unit tests to fail on Windows.
* Remove nre usage to fix Windows error
Windows was erroring with `could not load: pcre64.dll`. Instead of fixing that error, remove the pcre usage :)
* Add logutils module doc
* Shorten logutils.formatIt for `NBytes`
Both json and textlines formatIt were not needed, and could be combined into one formatIt
* remove debug integration test config
debug output and logformat of json for integration test logs
* Use ## module doc to support docgen
* bump nim-poseidon2 to export fromBytes
Before the changes in this branch, fromBytes was likely being resolved by nim-stew, or other dependency. With the changes in this branch, that dependency was removed and fromBytes could no longer be resolved. By exporting fromBytes from nim-poseidon, the correct resolution is now happening.
* fixes to get compiling after rebasing master
* Add support for Result types being logged using formatIt
2024-01-23 07:35:03 +00:00
|
|
|
import ../logutils
|
2023-11-14 12:02:17 +00:00
|
|
|
import ../utils
|
2022-03-21 18:09:59 +00:00
|
|
|
|
|
|
|
import ./seekablestream
|
2022-03-17 13:56:46 +00:00
|
|
|
|
2022-03-21 18:09:59 +00:00
|
|
|
export stores, blocktype, manifest, chronos
|
2022-03-17 13:56:46 +00:00
|
|
|
|
|
|
|
logScope:
|
2022-11-15 15:46:21 +00:00
|
|
|
topics = "codex storestream"
|
2022-03-17 13:56:46 +00:00
|
|
|
|
2023-06-22 18:01:21 +00:00
|
|
|
const
|
|
|
|
StoreStreamTrackerName* = "StoreStream"
|
|
|
|
|
2022-03-17 13:56:46 +00:00
|
|
|
type
|
2022-08-24 12:15:59 +00:00
|
|
|
# Make SeekableStream from a sequence of blocks stored in Manifest
|
|
|
|
# (only original file data - see StoreStream.size)
|
2022-03-21 18:09:59 +00:00
|
|
|
StoreStream* = ref object of SeekableStream
|
2022-08-24 12:15:59 +00:00
|
|
|
store*: BlockStore # Store where to lookup block contents
|
|
|
|
manifest*: Manifest # List of block CIDs
|
|
|
|
pad*: bool # Pad last block to manifest.blockSize?
|
2022-03-17 13:56:46 +00:00
|
|
|
|
2023-06-22 18:01:21 +00:00
|
|
|
method initStream*(s: StoreStream) =
|
|
|
|
if s.objName.len == 0:
|
|
|
|
s.objName = StoreStreamTrackerName
|
|
|
|
|
|
|
|
procCall SeekableStream(s).initStream()
|
|
|
|
|
2022-03-30 02:43:35 +00:00
|
|
|
proc new*(
|
2023-06-22 15:11:18 +00:00
|
|
|
T: type StoreStream,
|
|
|
|
store: BlockStore,
|
|
|
|
manifest: Manifest,
|
|
|
|
pad = true
|
|
|
|
): StoreStream =
|
|
|
|
## Create a new StoreStream instance for a given store and manifest
|
feat: create logging proxy (#663)
* implement a logging proxy
The logging proxy:
- prevents the need to import chronicles (as well as export except toJson),
- prevents the need to override `writeValue` or use or import nim-json-seralization elsewhere in the codebase, allowing for sole use of utils/json for de/serialization,
- and handles json formatting correctly in chronicles json sinks
* Rename logging -> logutils to avoid ambiguity with common names
* clean up
* add setProperty for JsonRecord, remove nim-json-serialization conflict
* Allow specifying textlines and json format separately
Not specifying a LogFormat will apply the formatting to both textlines and json sinks.
Specifying a LogFormat will apply the formatting to only that sink.
* remove unneeded usages of std/json
We only need to import utils/json instead of std/json
* move serialization from rest/json to utils/json so it can be shared
* fix NoColors ambiguity
Was causing unit tests to fail on Windows.
* Remove nre usage to fix Windows error
Windows was erroring with `could not load: pcre64.dll`. Instead of fixing that error, remove the pcre usage :)
* Add logutils module doc
* Shorten logutils.formatIt for `NBytes`
Both json and textlines formatIt were not needed, and could be combined into one formatIt
* remove debug integration test config
debug output and logformat of json for integration test logs
* Use ## module doc to support docgen
* bump nim-poseidon2 to export fromBytes
Before the changes in this branch, fromBytes was likely being resolved by nim-stew, or other dependency. With the changes in this branch, that dependency was removed and fromBytes could no longer be resolved. By exporting fromBytes from nim-poseidon, the correct resolution is now happening.
* fixes to get compiling after rebasing master
* Add support for Result types being logged using formatIt
2024-01-23 07:35:03 +00:00
|
|
|
##
|
2023-06-22 15:11:18 +00:00
|
|
|
result = StoreStream(
|
2022-03-17 13:56:46 +00:00
|
|
|
store: store,
|
|
|
|
manifest: manifest,
|
2022-08-24 12:15:59 +00:00
|
|
|
pad: pad,
|
|
|
|
offset: 0)
|
2022-03-17 13:56:46 +00:00
|
|
|
|
|
|
|
result.initStream()
|
|
|
|
|
2022-06-14 15:19:35 +00:00
|
|
|
method `size`*(self: StoreStream): int =
|
2023-07-06 23:23:27 +00:00
|
|
|
bytes(self.manifest, self.pad).int
|
2022-03-21 18:09:59 +00:00
|
|
|
|
2022-06-14 15:19:35 +00:00
|
|
|
proc `size=`*(self: StoreStream, size: int)
|
|
|
|
{.error: "Setting the size is forbidden".} =
|
|
|
|
discard
|
|
|
|
|
2022-07-28 00:39:17 +00:00
|
|
|
method atEof*(self: StoreStream): bool =
|
|
|
|
self.offset >= self.size
|
|
|
|
|
2022-03-17 13:56:46 +00:00
|
|
|
method readOnce*(
|
2023-06-22 15:11:18 +00:00
|
|
|
self: StoreStream,
|
|
|
|
pbytes: pointer,
|
|
|
|
nbytes: int
|
|
|
|
): Future[int] {.async.} =
|
2022-07-28 00:39:17 +00:00
|
|
|
## Read `nbytes` from current position in the StoreStream into output buffer pointed by `pbytes`.
|
|
|
|
## Return how many bytes were actually read before EOF was encountered.
|
|
|
|
## Raise exception if we are already at EOF.
|
feat: create logging proxy (#663)
* implement a logging proxy
The logging proxy:
- prevents the need to import chronicles (as well as export except toJson),
- prevents the need to override `writeValue` or use or import nim-json-seralization elsewhere in the codebase, allowing for sole use of utils/json for de/serialization,
- and handles json formatting correctly in chronicles json sinks
* Rename logging -> logutils to avoid ambiguity with common names
* clean up
* add setProperty for JsonRecord, remove nim-json-serialization conflict
* Allow specifying textlines and json format separately
Not specifying a LogFormat will apply the formatting to both textlines and json sinks.
Specifying a LogFormat will apply the formatting to only that sink.
* remove unneeded usages of std/json
We only need to import utils/json instead of std/json
* move serialization from rest/json to utils/json so it can be shared
* fix NoColors ambiguity
Was causing unit tests to fail on Windows.
* Remove nre usage to fix Windows error
Windows was erroring with `could not load: pcre64.dll`. Instead of fixing that error, remove the pcre usage :)
* Add logutils module doc
* Shorten logutils.formatIt for `NBytes`
Both json and textlines formatIt were not needed, and could be combined into one formatIt
* remove debug integration test config
debug output and logformat of json for integration test logs
* Use ## module doc to support docgen
* bump nim-poseidon2 to export fromBytes
Before the changes in this branch, fromBytes was likely being resolved by nim-stew, or other dependency. With the changes in this branch, that dependency was removed and fromBytes could no longer be resolved. By exporting fromBytes from nim-poseidon, the correct resolution is now happening.
* fixes to get compiling after rebasing master
* Add support for Result types being logged using formatIt
2024-01-23 07:35:03 +00:00
|
|
|
##
|
2022-03-17 13:56:46 +00:00
|
|
|
|
2023-11-14 12:02:17 +00:00
|
|
|
trace "Reading from manifest", cid = self.manifest.cid.get(), blocks = self.manifest.blocksCount
|
2022-03-17 13:56:46 +00:00
|
|
|
if self.atEof:
|
|
|
|
raise newLPStreamEOFError()
|
|
|
|
|
2022-07-28 00:39:17 +00:00
|
|
|
# The loop iterates over blocks in the StoreStream,
|
|
|
|
# reading them and copying their data into outbuf
|
|
|
|
var read = 0 # Bytes read so far, and thus write offset in the outbuf
|
2022-03-30 02:43:35 +00:00
|
|
|
while read < nbytes and not self.atEof:
|
2022-07-28 00:39:17 +00:00
|
|
|
# Compute from the current stream position `self.offset` the block num/offset to read
|
|
|
|
# Compute how many bytes to read from this block
|
2022-03-17 13:56:46 +00:00
|
|
|
let
|
2023-07-06 23:23:27 +00:00
|
|
|
blockNum = self.offset div self.manifest.blockSize.int
|
|
|
|
blockOffset = self.offset mod self.manifest.blockSize.int
|
|
|
|
readBytes = min([self.size - self.offset,
|
|
|
|
nbytes - read,
|
|
|
|
self.manifest.blockSize.int - blockOffset])
|
2023-11-14 12:02:17 +00:00
|
|
|
address = BlockAddress(leaf: true, treeCid: self.manifest.treeCid, index: blockNum)
|
2022-07-28 00:39:17 +00:00
|
|
|
|
|
|
|
# Read contents of block `blockNum`
|
2023-11-14 12:02:17 +00:00
|
|
|
without blk =? await self.store.getBlock(address), error:
|
2022-07-28 00:39:17 +00:00
|
|
|
raise newLPStreamReadError(error)
|
2022-08-19 00:56:36 +00:00
|
|
|
|
2022-07-28 00:39:17 +00:00
|
|
|
trace "Reading bytes from store stream", blockNum, cid = blk.cid, bytes = readBytes, blockOffset
|
|
|
|
|
|
|
|
# Copy `readBytes` bytes starting at `blockOffset` from the block into the outbuf
|
2022-08-24 12:15:59 +00:00
|
|
|
if blk.isEmpty:
|
|
|
|
zeroMem(pbytes.offset(read), readBytes)
|
|
|
|
else:
|
|
|
|
copyMem(pbytes.offset(read), blk.data[blockOffset].addr, readBytes)
|
2022-05-24 05:24:15 +00:00
|
|
|
|
2022-07-28 00:39:17 +00:00
|
|
|
# Update current positions in the stream and outbuf
|
2022-03-17 13:56:46 +00:00
|
|
|
self.offset += readBytes
|
|
|
|
read += readBytes
|
|
|
|
|
|
|
|
return read
|
|
|
|
|
|
|
|
method closeImpl*(self: StoreStream) {.async.} =
|
2022-08-24 12:15:59 +00:00
|
|
|
trace "Closing StoreStream"
|
|
|
|
self.offset = self.size # set Eof
|
2022-03-17 13:56:46 +00:00
|
|
|
await procCall LPStream(self).closeImpl()
|