@@ -70,22 +70,30 @@ func (r *limitedSocketReader) Read(p []byte) (int, error) {
7070 return n , nil
7171}
7272
73+ // DigestLookupFunc is a function that looks up a file by its digest.
74+ // It returns the open file, offset within the file, and chunk size.
75+ // A nil file means the digest was not found.
76+ // The caller is responsible for closing the returned file.
77+ type DigestLookupFunc func (digest string ) (file * os.File , offset int64 , size int64 , err error )
78+
7379// JSONRPCServer manages the JSON-RPC server for storage operations.
7480type JSONRPCServer struct {
75- driver any
76- listener net.Listener
77- socketPath string
78- shutdown chan struct {}
79- connections sync.WaitGroup
80- mu sync.RWMutex
81- running bool
81+ driver any
82+ digestLookup DigestLookupFunc
83+ listener net.Listener
84+ socketPath string
85+ shutdown chan struct {}
86+ connections sync.WaitGroup
87+ mu sync.RWMutex
88+ running bool
8289}
8390
8491// NewJSONRPCServer creates a new JSON-RPC server.
85- func NewJSONRPCServer (driver any ) * JSONRPCServer {
92+ func NewJSONRPCServer (driver any , digestLookup DigestLookupFunc ) * JSONRPCServer {
8693 return & JSONRPCServer {
87- driver : driver ,
88- shutdown : make (chan struct {}),
94+ driver : driver ,
95+ digestLookup : digestLookup ,
96+ shutdown : make (chan struct {}),
8997 }
9098}
9199
@@ -271,6 +279,8 @@ func (s *JSONRPCServer) handleRequest(fdPasser *FDPasser, requestLine string) {
271279 s .handleApplySplitFDStream (fdPasser , req )
272280 case MethodGetSplitFDStream :
273281 s .handleGetSplitFDStream (fdPasser , req )
282+ case MethodLookupDigest :
283+ s .handleLookupDigest (fdPasser , req )
274284 default :
275285 resp := NewErrorResponse (ErrorCodeMethodNotFound , "Method not found" , req .Method , req .ID )
276286 s .sendResponse (fdPasser , resp )
@@ -528,6 +538,71 @@ func (s *JSONRPCServer) handleGetSplitFDStream(fdPasser *FDPasser, req *SplitFDS
528538 }
529539}
530540
541+ // handleLookupDigest handles lookup_digest requests.
542+ // Protocol:
543+ // 1. Client sends JSON-RPC request with digest
544+ // 2. Server looks up the digest in the cache
545+ // 3. Server sends response with offset and size, plus the file descriptor
546+ func (s * JSONRPCServer ) handleLookupDigest (fdPasser * FDPasser , req * SplitFDStreamRequest ) {
547+ // Parse the lookup-specific parameters
548+ lookupParams , err := ParseLookupDigestParams (req .Params )
549+ if err != nil {
550+ resp := NewErrorResponse (ErrorCodeInvalidParams , err .Error (), nil , req .ID )
551+ s .sendResponse (fdPasser , resp )
552+ return
553+ }
554+
555+ // Check if digest lookup is available
556+ if s .digestLookup == nil {
557+ resp := NewErrorResponse (
558+ ErrorCodeStoreNotAvailable ,
559+ "digest lookup is not available" ,
560+ nil ,
561+ req .ID ,
562+ )
563+ s .sendResponse (fdPasser , resp )
564+ return
565+ }
566+
567+ // Look up the digest
568+ file , offset , size , err := s .digestLookup (lookupParams .Digest )
569+ if err != nil {
570+ resp := NewErrorResponse (ErrorCodeInternalError , fmt .Sprintf ("failed to lookup digest: %v" , err ), nil , req .ID )
571+ s .sendResponse (fdPasser , resp )
572+ return
573+ }
574+
575+ if file == nil {
576+ resp := NewErrorResponse (
577+ ErrorCodeDigestNotFound ,
578+ fmt .Sprintf ("digest %s not found" , lookupParams .Digest ),
579+ nil ,
580+ req .ID ,
581+ )
582+ s .sendResponse (fdPasser , resp )
583+ return
584+ }
585+
586+ defer file .Close ()
587+
588+ // Send success response with metadata
589+ responseResult := & SplitFDStreamResult {
590+ Offset : offset ,
591+ ChunkSize : size ,
592+ Message : "found" ,
593+ }
594+ numFDs := 1
595+ responseResult .FileDescriptors = & numFDs
596+ resp := NewSuccessResponse (responseResult , req .ID )
597+ s .sendResponse (fdPasser , resp )
598+
599+ // Send the file descriptor
600+ if err := fdPasser .SendFileDescriptors ([]* os.File {file }, []byte {0 }); err != nil {
601+ logrus .Errorf ("splitfdstream: failed to send file descriptor for digest lookup: %v" , err )
602+ return
603+ }
604+ }
605+
531606// waitForContinue reads "continue\n" from the client.
532607func (s * JSONRPCServer ) waitForContinue (fdPasser * FDPasser ) error {
533608 msg , err := fdPasser .ReadLine ()
0 commit comments