Add adds a chunk to the queue. It ignores chunks that already exist, returning false.
(chunk *chunk)
| 61 | |
| 62 | // Add adds a chunk to the queue. It ignores chunks that already exist, returning false. |
| 63 | func (q *chunkQueue) Add(chunk *chunk) (bool, error) { |
| 64 | if chunk == nil || chunk.Chunk == nil { |
| 65 | return false, errors.New("cannot add nil chunk") |
| 66 | } |
| 67 | q.Lock() |
| 68 | defer q.Unlock() |
| 69 | if q.snapshot == nil { |
| 70 | return false, nil // queue is closed |
| 71 | } |
| 72 | if chunk.Height != q.snapshot.Height { |
| 73 | return false, fmt.Errorf("invalid chunk height %v, expected %v", chunk.Height, q.snapshot.Height) |
| 74 | } |
| 75 | if chunk.Format != q.snapshot.Format { |
| 76 | return false, fmt.Errorf("invalid chunk format %v, expected %v", chunk.Format, q.snapshot.Format) |
| 77 | } |
| 78 | if chunk.Index >= q.snapshot.Chunks { |
| 79 | return false, fmt.Errorf("received unexpected chunk %v", chunk.Index) |
| 80 | } |
| 81 | if q.chunkFiles[chunk.Index] != "" { |
| 82 | return false, nil |
| 83 | } |
| 84 | |
| 85 | path := filepath.Join(q.dir, strconv.FormatUint(uint64(chunk.Index), 10)) |
| 86 | err := os.WriteFile(path, chunk.Chunk, 0o600) |
| 87 | if err != nil { |
| 88 | return false, fmt.Errorf("failed to save chunk %v to file %v: %w", chunk.Index, path, err) |
| 89 | } |
| 90 | q.chunkFiles[chunk.Index] = path |
| 91 | q.chunkSenders[chunk.Index] = chunk.Sender |
| 92 | |
| 93 | // Signal any waiters that the chunk has arrived. |
| 94 | for _, waiter := range q.waiters[chunk.Index] { |
| 95 | waiter <- chunk.Index |
| 96 | close(waiter) |
| 97 | } |
| 98 | delete(q.waiters, chunk.Index) |
| 99 | |
| 100 | return true, nil |
| 101 | } |
| 102 | |
| 103 | // Allocate allocates a chunk to the caller, making it responsible for fetching it. Returns |
| 104 | // errDone once no chunks are left or the queue is closed. |