blobsets/src/ipld/replicator.nim
2018-08-13 09:49:49 +02:00

54 lines
1.8 KiB
Nim

import streams, strutils, os, ../ipld, cbor, ./multiformats, ./store
type
IpldReplicator* = ref IpldReplicatorObj
IpldReplicatorObj* = object of IpldStoreObj
toStore, fromStore: IpldStore
cache: string
cacheCid: Cid
proc replicatedPut(s: IpldStore; blk: string; hash: MulticodecTag): Cid =
var r = IpldReplicator s
r.toStore.put(blk, hash)
proc replicatedGetBuffer(s: IpldStore; cid: Cid; buf: pointer; len: Natural): int =
var r = IpldReplicator s
if r.cacheCid == cid:
assert(cid.verify(r.cache), "cached block is invalid from previous get")
if r.cache.len > len:
raise newException(BufferTooSmall, "")
result = r.cache.len
copyMem(buf, r.cache[0].addr, result)
else:
try:
result = r.toStore.getBuffer(cid, buf, len)
r.cacheCid = cid
r.cache.setLen result
copyMem(r.cache[0].addr, buf, result)
assert(cid.verify(r.cache), "cached block is invalid after copy from To store")
except MissingObject:
result = r.fromStore.getBuffer(cid, buf, len)
r.cacheCid = cid
r.cache.setLen result
copyMem(r.cache[0].addr, buf, result)
assert(cid.verify(r.cache), "replicate cache is invalid after copy from From store")
discard r.toStore.put(r.cache, cid.hash)
proc replicatedGet(s: IpldStore; cid: Cid; result: var string) =
var r = IpldReplicator s
try: r.toStore.get(cid, result)
except MissingObject:
r.fromStore.get(cid, result)
discard r.toStore.put(result, cid.hash)
proc newIpldReplicator*(toStore, fromStore: IpldStore): IpldReplicator =
## Blocks retrieved by `get` are not verified.
IpldReplicator(
putImpl: replicatedPut,
getBufferImpl: replicatedGetBuffer,
getImpl: replicatedGet,
toStore: toStore,
fromStore: fromStore,
cache: "",
cacheCid: initCid())