AddChunk adds a new chunk of a cached object
(fp string, data []byte, offset int64)
| 482 | |
| 483 | // AddChunk adds a new chunk of a cached object |
| 484 | func (b *Persistent) AddChunk(fp string, data []byte, offset int64) error { |
| 485 | _ = os.MkdirAll(path.Join(b.dataPath, fp), os.ModePerm) |
| 486 | |
| 487 | filePath := path.Join(b.dataPath, fp, strconv.FormatInt(offset, 10)) |
| 488 | err := os.WriteFile(filePath, data, os.ModePerm) |
| 489 | if err != nil { |
| 490 | return err |
| 491 | } |
| 492 | |
| 493 | return b.db.Update(func(tx *bolt.Tx) error { |
| 494 | tsBucket := tx.Bucket([]byte(DataTsBucket)) |
| 495 | ts := time.Now() |
| 496 | found := false |
| 497 | |
| 498 | // delete (older) timestamps for the same object |
| 499 | c := tsBucket.Cursor() |
| 500 | for k, v := c.First(); k != nil; k, v = c.Next() { |
| 501 | var ci chunkInfo |
| 502 | err = json.Unmarshal(v, &ci) |
| 503 | if err != nil { |
| 504 | continue |
| 505 | } |
| 506 | if ci.Path == fp && ci.Offset == offset { |
| 507 | if tsInCache := time.Unix(0, btoi(k)); tsInCache.After(ts) && !found { |
| 508 | found = true |
| 509 | continue |
| 510 | } |
| 511 | err := c.Delete() |
| 512 | if err != nil { |
| 513 | fs.Debugf(fp, "failed to clean chunk: %v", err) |
| 514 | } |
| 515 | } |
| 516 | } |
| 517 | // don't overwrite if a newer one is already there |
| 518 | if found { |
| 519 | return nil |
| 520 | } |
| 521 | enc, err := json.Marshal(chunkInfo{Path: fp, Offset: offset, Size: int64(len(data))}) |
| 522 | if err != nil { |
| 523 | fs.Debugf(fp, "failed to timestamp chunk: %v", err) |
| 524 | } |
| 525 | err = tsBucket.Put(itob(ts.UnixNano()), enc) |
| 526 | if err != nil { |
| 527 | fs.Debugf(fp, "failed to timestamp chunk: %v", err) |
| 528 | } |
| 529 | return nil |
| 530 | }) |
| 531 | } |
| 532 | |
| 533 | // CleanChunksByAge will cleanup on a cron basis |
| 534 | func (b *Persistent) CleanChunksByAge(chunkAge time.Duration) { |
nothing calls this directly
no test coverage detected