This commit is contained in:
Louis Seubert 2026-01-23 22:22:32 +01:00
commit eda52ab138
Signed by: louis9902
GPG key ID: 4B9DB28F826553BD

View file

@ -22,13 +22,12 @@ type PushResult struct {
Size int64
}
func PushBlob(ctx context.Context, url string, data io.Reader, chunkSize, maxParallel int) (int, string, error) {
var empty string
func PushBlob(ctx context.Context, r io.Reader, blobURL string, chunkSize int64, parallelism int) (*PushResult, error) {
if chunkSize <= 0 {
chunkSize = 4 * 1024 * 1024 // 4MB default
}
if maxParallel <= 0 {
maxParallel = 4
if parallelism <= 0 {
parallelism = 4
}
type chunk struct {
@ -36,19 +35,21 @@ func PushBlob(ctx context.Context, url string, data io.Reader, chunkSize, maxPar
data []byte
}
wrkinp := make(chan chunk)
wrkerr := make(chan error, maxParallel)
blockIDs := make([]string, 0)
wrkerr := make(chan error, parallelism)
var blockMu sync.Mutex
blockIDs := make([]string, 0)
var wg sync.WaitGroup
// Worker pool for parallel uploading
for i := 0; i < maxParallel; i++ {
for i := 0; i < parallelism; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for c := range wrkinp {
id := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%06d", c.index)))
address := fmt.Sprintf("%s&comp=block&blockid=%s", url, id)
address := fmt.Sprintf("%s&comp=block&blockid=%s", blobURL, id)
req, err := http.NewRequestWithContext(ctx, "PUT", address, bytes.NewReader(c.data))
if err != nil {
wrkerr <- err
@ -77,11 +78,13 @@ func PushBlob(ctx context.Context, url string, data io.Reader, chunkSize, maxPar
// Chunk the data and send to workers
index := 0
hash := sha256.New()
var size int64
for {
buf := make([]byte, chunkSize)
n, err := io.ReadFull(data, buf)
n, err := io.ReadFull(r, buf)
if err == io.EOF || err == io.ErrUnexpectedEOF {
if n > 0 {
size += int64(n)
hash.Write(buf[:n])
wrkinp <- chunk{index: index, data: buf[:n]}
index++
@ -91,7 +94,7 @@ func PushBlob(ctx context.Context, url string, data io.Reader, chunkSize, maxPar
if err != nil {
close(wrkinp)
wg.Wait()
return empty, err
return nil, err
}
hash.Write(buf)
wrkinp <- chunk{index: index, data: buf}
@ -102,53 +105,51 @@ func PushBlob(ctx context.Context, url string, data io.Reader, chunkSize, maxPar
select {
case err := <-wrkerr:
return empty, err
return nil, err
default:
}
type BlockList struct {
Latest []string `xml:"Latest"`
}
type Latest struct {
Value string `xml:",chardata"`
}
type BlockList struct {
Latest []Latest `xml:"Latest"`
}
// Sort block IDs to ensure correct order
blockMu.Lock()
defer blockMu.Unlock()
if len(blockIDs) == 0 {
return empty, fmt.Errorf("no blocks uploaded")
return nil, fmt.Errorf("no blocks uploaded")
}
blockList := &BlockList{}
for i := 0; i < len(blockIDs); i++ {
blockList.Latest = append(blockList.Blocks, xmlBlock{XMLName: xml.Name{Local: "Latest"}, ID: blockIDs[i]})
blockList.Latest = append(blockList.Latest, Latest{Value: blockIDs[i]})
}
blockListData, err := xml.Marshal(blockList)
if err != nil {
return empty, err
return nil, err
}
req, err := http.NewRequestWithContext(ctx, "PUT", fmt.Sprintf("%s&comp=blocklist", url), bytes.NewReader(blockListData))
req, err := http.NewRequestWithContext(ctx, "PUT", fmt.Sprintf("%s&comp=blocklist", blobURL), bytes.NewReader(blockListData))
if err != nil {
return empty, err
return nil, err
}
req.Header.Set("Content-Type", "application/xml")
req.ContentLength = int64(len(blockListData))
resp, err := http.DefaultClient.Do(req)
if err != nil {
return empty, err
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
body, _ := io.ReadAll(resp.Body)
return empty, fmt.Errorf("blocklist commit failed: %s body: %s", resp.Status, string(body))
return nil, fmt.Errorf("blocklist commit failed: %s body: %s", resp.Status, string(body))
}
return hex.EncodeToString(hash.Sum(nil)), nil
return &PushResult{SHA256Sum: hex.EncodeToString(hash.Sum(nil)), Size: size}, nil
}
func PushBlob_(ctx context.Context, r io.Reader, blobURL string, chunkSize int64, parallelism int) (*PushResult, error) {
}
func PullBlob_(ctx context.Context, w io.Writer, blobURL string, chunkSize int64, parallelism int) (*PullResult, error) {
func PullBlob(ctx context.Context, w io.Writer, blobURL string, chunkSize int64, parallelism int) (*PullResult, error) {
return nil, nil
}