diff --git a/examples/golang/codex.go b/examples/golang/codex.go index 46813270..baafb170 100644 --- a/examples/golang/codex.go +++ b/examples/golang/codex.go @@ -144,6 +144,10 @@ package main return codex_download_manifest(codexCtx, cid, (CodexCallback) callback, resp); } + static int cGoCodexStorageList(void* codexCtx, void* resp) { + return codex_storage_list(codexCtx, (CodexCallback) callback, resp); + } + static int cGoCodexStart(void* codexCtx, void* resp) { return codex_start(codexCtx, (CodexCallback) callback, resp); } @@ -331,6 +335,7 @@ type bridgeCtx struct { } type CodexManifest struct { + Cid string TreeCid string `json:"treeCid"` DatasetSize int `json:"datasetSize"` BlockSize int `json:"blockSize"` @@ -339,6 +344,11 @@ type CodexManifest struct { Protected bool `json:"protected"` } +type CodexManifestWithCid struct { + Cid string `json:"cid"` + Manifest CodexManifest `json:"manifest"` +} + func newBridgeCtx() *bridgeCtx { bridge := &bridgeCtx{} bridge.wg = &sync.WaitGroup{} @@ -803,7 +813,7 @@ func (self CodexNode) CodexDownloadManifest(cid string) (CodexManifest, error) { return CodexManifest{}, err } - var manifest CodexManifest + manifest := CodexManifest{Cid: cid} err = json.Unmarshal([]byte(val), &manifest) if err != nil { return CodexManifest{}, err @@ -928,6 +938,33 @@ func (self CodexNode) CodexDownloadCancel(cid string) error { return err } +func (self CodexNode) CodexStorageList() ([]CodexManifest, error) { + bridge := newBridgeCtx() + defer bridge.free() + + if C.cGoCodexStorageList(self.ctx, bridge.resp) != C.RET_OK { + return nil, bridge.CallError("cGoCodexStorageList") + } + value, err := bridge.wait() + if err != nil { + return nil, err + } + + var items []CodexManifestWithCid + err = json.Unmarshal([]byte(value), &items) + if err != nil { + return nil, err + } + + var list []CodexManifest + for _, item := range items { + item.Manifest.Cid = item.Cid + list = append(list, item.Manifest) + } + + return list, err +} + func (self CodexNode) CodexStart() error { bridge := newBridgeCtx() defer bridge.free() @@ -1166,6 +1203,13 @@ func main() { } log.Println("Manifest content:", manifest) + + manifests, err := node.CodexStorageList() + if err != nil { + log.Fatal("Error happened:", err.Error()) + } + + log.Println("Storage List content:", manifests) // } // err = node.CodexConnect(peerId, []string{}) diff --git a/library/codex_thread_requests/codex_thread_request.nim b/library/codex_thread_requests/codex_thread_request.nim index d4a1e08c..c2eab9ad 100644 --- a/library/codex_thread_requests/codex_thread_request.nim +++ b/library/codex_thread_requests/codex_thread_request.nim @@ -12,6 +12,7 @@ import ./requests/node_debug_request import ./requests/node_p2p_request import ./requests/node_upload_request import ./requests/node_download_request +import ./requests/node_storage_request from ../../codex/codex import CodexServer @@ -22,6 +23,7 @@ type RequestType* {.pure.} = enum P2P UPLOAD DOWNLOAD + STORAGE type CodexThreadRequest* = object reqType: RequestType @@ -96,6 +98,8 @@ proc process*( cast[ptr NodeDebugRequest](request[].reqContent).process(codex) of P2P: cast[ptr NodeP2PRequest](request[].reqContent).process(codex) + of STORAGE: + cast[ptr NodeStorageRequest](request[].reqContent).process(codex) of DOWNLOAD: let onChunk = proc(bytes: seq[byte]) = if bytes.len > 0: diff --git a/library/codex_thread_requests/requests/node_storage_request.nim b/library/codex_thread_requests/requests/node_storage_request.nim new file mode 100644 index 00000000..bda7bbde --- /dev/null +++ b/library/codex_thread_requests/requests/node_storage_request.nim @@ -0,0 +1,109 @@ +{.push raises: [].} + +## This file contains the node storage request. + +import std/[options] +import chronos +import chronicles +import libp2p/stream/[lpstream] +import serde/json as serde +import ../../alloc +import ../../../codex/manifest + +from ../../../codex/codex import CodexServer, node +from ../../../codex/node import iterateManifests +from libp2p import Cid, init, `$` + +logScope: + topics = "codexlib codexlibstorage" + +type NodeStorageMsgType* = enum + LIST + DELETE + FETCH + SPACE + +type NodeStorageRequest* = object + operation: NodeStorageMsgType + cid: cstring + +proc createShared*( + T: type NodeStorageRequest, op: NodeStorageMsgType, cid: cstring = "" +): ptr type T = + var ret = createShared(T) + ret[].operation = op + ret[].cid = cid.alloc() + + return ret + +proc destroyShared(self: ptr NodeStorageRequest) = + deallocShared(self[].cid) + deallocShared(self) + +type ManifestWithCid = object + cid {.serialize.}: string + manifest {.serialize.}: Manifest + +proc list( + codex: ptr CodexServer +): Future[Result[string, string]] {.async: (raises: []).} = + var manifests = newSeq[ManifestWithCid]() + proc onManifest(cid: Cid, manifest: Manifest) {.raises: [], gcsafe.} = + manifests.add(ManifestWithCid(cid: $cid, manifest: manifest)) + + try: + let node = codex[].node + await node.iterateManifests(onManifest) + except CancelledError: + return err("Failed to list manifests: cancelled operation.") + except CatchableError as err: + return err("Failed to list manifest: : " & err.msg) + + return ok(serde.toJson(manifests)) + +proc delete( + codex: ptr CodexServer, cid: cstring +): Future[Result[string, string]] {.async: (raises: []).} = + return err("DELETE operation not implemented yet.") + +proc fetch( + codex: ptr CodexServer, cid: cstring +): Future[Result[string, string]] {.async: (raises: []).} = + return err("FETCH operation not implemented yet.") + +proc space( + codex: ptr CodexServer +): Future[Result[string, string]] {.async: (raises: []).} = + return err("SPACE operation not implemented yet.") + +proc process*( + self: ptr NodeStorageRequest, codex: ptr CodexServer +): Future[Result[string, string]] {.async: (raises: []).} = + defer: + destroyShared(self) + + case self.operation + of NodeStorageMsgType.LIST: + let res = (await list(codex)) + if res.isErr: + error "Failed to LIST.", error = res.error + return err($res.error) + return res + of NodeStorageMsgType.DELETE: + let res = (await delete(codex, self.cid)) + if res.isErr: + error "Failed to DELETE.", error = res.error + return err($res.error) + return res + of NodeStorageMsgType.FETCH: + let res = (await fetch(codex, self.cid)) + if res.isErr: + error "Failed to FETCH.", error = res.error + return err($res.error) + return res + of NodeStorageMsgType.SPACE: + let res = (await space(codex)) + if res.isErr: + error "Failed to SPACE.", error = res.error + return err($res.error) + return res diff --git a/library/libcodex.h b/library/libcodex.h index 85fb3c29..fa91f67a 100644 --- a/library/libcodex.h +++ b/library/libcodex.h @@ -150,6 +150,28 @@ int codex_download_manifest( CodexCallback callback, void* userData); +int codex_storage_list( + void* ctx, + CodexCallback callback, + void* userData); + +int codex_storage_space( + void* ctx, + CodexCallback callback, + void* userData); + +int codex_storage_delete( + void* ctx, + const char* cid, + CodexCallback callback, + void* userData); + +int codex_storage_fetch( + void* ctx, + const char* cid, + CodexCallback callback, + void* userData); + int codex_start(void* ctx, CodexCallback callback, void* userData); diff --git a/library/libcodex.nim b/library/libcodex.nim index 1911348b..566bbf67 100644 --- a/library/libcodex.nim +++ b/library/libcodex.nim @@ -35,6 +35,7 @@ import ./codex_thread_requests/requests/node_debug_request import ./codex_thread_requests/requests/node_p2p_request import ./codex_thread_requests/requests/node_upload_request import ./codex_thread_requests/requests/node_download_request +import ./codex_thread_requests/requests/node_storage_request import ./ffi_types from ../codex/conf import codexVersion, updateLogLevel @@ -441,6 +442,62 @@ proc codex_download_manifest( result = callback.okOrError(res, userData) +proc codex_storage_list( + ctx: ptr CodexContext, callback: CodexCallback, userData: pointer +): cint {.dynlib, exportc.} = + initializeLibrary() + checkLibcodexParams(ctx, callback, userData) + + let req = NodeStorageRequest.createShared(NodeStorageMsgType.LIST) + + let res = codex_context.sendRequestToCodexThread( + ctx, RequestType.STORAGE, req, callback, userData + ) + + result = callback.okOrError(res, userData) + +proc codex_storage_space( + ctx: ptr CodexContext, callback: CodexCallback, userData: pointer +): cint {.dynlib, exportc.} = + initializeLibrary() + checkLibcodexParams(ctx, callback, userData) + + let req = NodeStorageRequest.createShared(NodeStorageMsgType.SPACE) + + let res = codex_context.sendRequestToCodexThread( + ctx, RequestType.STORAGE, req, callback, userData + ) + + result = callback.okOrError(res, userData) + +proc codex_storage_delete( + ctx: ptr CodexContext, cid: cstring, callback: CodexCallback, userData: pointer +): cint {.dynlib, exportc.} = + initializeLibrary() + checkLibcodexParams(ctx, callback, userData) + + let req = NodeStorageRequest.createShared(NodeStorageMsgType.DELETE, cid = cid) + + let res = codex_context.sendRequestToCodexThread( + ctx, RequestType.STORAGE, req, callback, userData + ) + + result = callback.okOrError(res, userData) + +proc codex_storage_fetch( + ctx: ptr CodexContext, cid: cstring, callback: CodexCallback, userData: pointer +): cint {.dynlib, exportc.} = + initializeLibrary() + checkLibcodexParams(ctx, callback, userData) + + let req = NodeStorageRequest.createShared(NodeStorageMsgType.FETCH, cid = cid) + + let res = codex_context.sendRequestToCodexThread( + ctx, RequestType.STORAGE, req, callback, userData + ) + + result = callback.okOrError(res, userData) + proc codex_start( ctx: ptr CodexContext, callback: CodexCallback, userData: pointer ): cint {.dynlib, exportc.} =