From 0642028735adcb2d431e5e146ca87accb4954900 Mon Sep 17 00:00:00 2001 From: Bernhard Guillon Date: Tue, 7 Jul 2026 09:20:10 +0200 Subject: Add Windows-assisted initial sync for faster startup New protocol: - Windows binary scans directory (fast native NTFS) and sends manifest - Container receives manifest, compares with local /data state - Only copies files that differ (size, modtime, mode, symlink) Protocol messages: - manifest: sends full file metadata from Windows - manifest_done: signals manifest transfer complete - event_create/write/remove: file change events Flow: 1. Container connects to socket 2. Windows binary sends manifest (file metadata) 3. Container scans /data (fast local volume) 4. Container copies only changed files from /host (9P bind mount) 5. Container enters event-waiting loop This dramatically speeds up initial sync by avoiding slow 9P scans. --- types.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'types.go') diff --git a/types.go b/types.go index 69d7702..bf5dd00 100644 --- a/types.go +++ b/types.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "os" "time" ) @@ -18,6 +19,59 @@ type FileMeta struct { Symlink string } +type FileMetaJSON struct { + Size int64 `json:"size"` + Mode uint32 `json:"mode"` + ModTime string `json:"modtime"` + Symlink string `json:"symlink,omitempty"` +} + type Manifest struct { Files map[string]FileMeta } + +type ProtocolMessage struct { + Type string `json:"type"` + Files map[string]FileMetaJSON `json:"files,omitempty"` + Path string `json:"path,omitempty"` + Content []byte `json:"content,omitempty"` +} + +func (m *Manifest) ToJSON() map[string]FileMetaJSON { + files := make(map[string]FileMetaJSON, len(m.Files)) + for k, v := range m.Files { + files[k] = FileMetaJSON{ + Size: v.Size, + Mode: uint32(v.Mode), + ModTime: v.ModTime.UTC().Format(time.RFC3339Nano), + Symlink: v.Symlink, + } + } + return files +} + +func ManifestFromJSON(files map[string]FileMetaJSON) *Manifest { + m := &Manifest{Files: make(map[string]FileMeta, len(files))} + for k, v := range files { + t, _ := time.Parse(time.RFC3339Nano, v.ModTime) + m.Files[k] = FileMeta{ + Size: v.Size, + Mode: os.FileMode(v.Mode), + ModTime: t, + Symlink: v.Symlink, + } + } + return m +} + +func DecodeMessage(data []byte) (*ProtocolMessage, error) { + var msg ProtocolMessage + if err := json.Unmarshal(data, &msg); err != nil { + return nil, err + } + return &msg, nil +} + +func EncodeMessage(msg *ProtocolMessage) ([]byte, error) { + return json.Marshal(msg) +} -- cgit v1.2.3