getChunk is called by the FS to retrieve a specific chunk of known start and size from where it can find it it can be from transient or persistent cache it will also build the chunk from the cache's specific chunk boundaries and build the final desired chunk in a buffer
(chunkStart int64)
| 201 | // it can be from transient or persistent cache |
| 202 | // it will also build the chunk from the cache's specific chunk boundaries and build the final desired chunk in a buffer |
| 203 | func (r *Handle) getChunk(chunkStart int64) ([]byte, error) { |
| 204 | var data []byte |
| 205 | var err error |
| 206 | |
| 207 | // we calculate the modulus of the requested offset with the size of a chunk |
| 208 | offset := chunkStart % int64(r.cacheFs().opt.ChunkSize) |
| 209 | |
| 210 | // we align the start offset of the first chunk to a likely chunk in the storage |
| 211 | chunkStart -= offset |
| 212 | r.queueOffset(chunkStart) |
| 213 | found := false |
| 214 | |
| 215 | if r.UseMemory { |
| 216 | data, err = r.memory.GetChunk(r.cachedObject, chunkStart) |
| 217 | if err == nil { |
| 218 | found = true |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | if !found { |
| 223 | // we're gonna give the workers a chance to pickup the chunk |
| 224 | // and retry a couple of times |
| 225 | for i := range r.cacheFs().opt.ReadRetries * 8 { |
| 226 | data, err = r.storage().GetChunk(r.cachedObject, chunkStart) |
| 227 | if err == nil { |
| 228 | found = true |
| 229 | break |
| 230 | } |
| 231 | |
| 232 | fs.Debugf(r, "%v: chunk retry storage: %v", chunkStart, i) |
| 233 | time.Sleep(time.Millisecond * 500) |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | // not found in ram or |
| 238 | // the worker didn't managed to download the chunk in time so we abort and close the stream |
| 239 | if err != nil || len(data) == 0 || !found { |
| 240 | if r.workers == 0 { |
| 241 | fs.Errorf(r, "out of workers") |
| 242 | return nil, io.ErrUnexpectedEOF |
| 243 | } |
| 244 | |
| 245 | return nil, fmt.Errorf("chunk not found %v", chunkStart) |
| 246 | } |
| 247 | |
| 248 | // first chunk will be aligned with the start |
| 249 | if offset > 0 { |
| 250 | if offset > int64(len(data)) { |
| 251 | fs.Errorf(r, "unexpected conditions during reading. current position: %v, current chunk position: %v, current chunk size: %v, offset: %v, chunk size: %v, file size: %v", |
| 252 | r.offset, chunkStart, len(data), offset, r.cacheFs().opt.ChunkSize, r.cachedObject.Size()) |
| 253 | return nil, io.ErrUnexpectedEOF |
| 254 | } |
| 255 | data = data[int(offset):] |
| 256 | } |
| 257 | |
| 258 | return data, nil |
| 259 | } |
| 260 |