// positionsLocked returns the positions in the blockfile of all packets matched by // the passed-in query. b.mu must be locked. func (b *BlockFile) positionsLocked(ctx context.Context, q query.Query) (base.Positions, error) { if b.i == nil || b.f == nil { // If we're closed, just return nothing. return nil, nil } return q.LookupIn(ctx, b.i) }
// Lookup returns all packets in the blockfile matched by the passed-in query. func (b *BlockFile) Lookup(ctx context.Context, q query.Query, out *base.PacketChan) { b.mu.RLock() defer b.mu.RUnlock() var ci gopacket.CaptureInfo v(2, "Blockfile %q looking up query %q", q.String(), b.name) start := time.Now() positions, err := b.positionsLocked(ctx, q) if err != nil { out.Close(fmt.Errorf("index lookup failure: %v", err)) return } if positions.IsAllPositions() { v(2, "Blockfile %q reading all packets", b.name) iter := &allPacketsIter{BlockFile: b} all_packets_loop: for iter.Next() { select { case <-ctx.Done(): v(2, "Blockfile %q canceling packet read", b.name) break all_packets_loop case <-b.done: v(2, "Blockfile %q closing, breaking out of query", b.name) break all_packets_loop case out.C <- iter.Packet(): } } if iter.Err() != nil { out.Close(fmt.Errorf("error reading all packets from %q: %v", b.name, iter.Err())) return } } else { v(2, "Blockfile %q reading %v packets", b.name, len(positions)) query_packets_loop: for _, pos := range positions { buffer, err := b.readPacket(pos, &ci) if err != nil { v(2, "Blockfile %q error reading packet: %v", b.name, err) out.Close(fmt.Errorf("error reading packets from %q @ %v: %v", b.name, pos, err)) return } select { case <-ctx.Done(): v(2, "Blockfile %q canceling packet read", b.name) break query_packets_loop case <-b.done: v(2, "Blockfile %q closing, breaking out of query", b.name) break query_packets_loop case out.C <- &base.Packet{Data: buffer, CaptureInfo: ci}: } } } v(2, "Blockfile %q finished reading all packets in %v", b.name, time.Since(start)) out.Close(ctx.Err()) }