From 9b4eafcc4c027649806aaa9fa5c22326f5c1121a Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Tue, 25 Apr 2017 19:40:52 +0200 Subject: [PATCH] Simplify and document postings serialization --- Documentation/format/index.md | 16 ++++++++++ index.go | 56 +++++++++++++++++------------------ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/Documentation/format/index.md b/Documentation/format/index.md index ca2beb3300..c5631c7255 100644 --- a/Documentation/format/index.md +++ b/Documentation/format/index.md @@ -126,5 +126,21 @@ The label index indexes holds lists of possible values for label names. A sequen Postings are postings lists that map label pairs to series they occur in. +``` + ┌─────────────────────────────────────────────────┐ + │ len │ + ├─────────────────────────────────────────────────┤ + │ ┌─────────────────────────────────────────────┐ │ + │ │ ref(series[0]) <4 byte> │ │ + │ ├─────────────────────────────────────────────┤ │ + │ │ ... │ │ + │ ├─────────────────────────────────────────────┤ │ + │ │ ref(series[n]) <4 byte> │ │ + │ └─────────────────────────────────────────────┘ │ + ├─────────────────────────────────────────────────┤ + │ CRC32 <4 byte> │ + └─────────────────────────────────────────────────┘ +``` + ### \ No newline at end of file diff --git a/index.go b/index.go index 7401434f8c..1e2ceb84e1 100644 --- a/index.go +++ b/index.go @@ -334,25 +334,18 @@ func (w *indexWriter) WritePostings(name, value string, it Postings) error { sort.Sort(uint32slice(refs)) - w.b = append(w.b[:0], flagStd, 0, 0, 0, 0) - buf := make([]byte, 4) - + w.buf2.reset() for _, r := range refs { - binary.BigEndian.PutUint32(buf, r) - w.b = append(w.b, buf...) + w.buf2.putBE32(r) } - w.uint32s = refs[:0] + w.buf1.reset() + w.buf1.putUvarint(w.buf2.len()) - binary.BigEndian.PutUint32(w.b[1:], uint32(len(w.b)-5)) + w.buf2.putHash(w.crc32) - w.crc32.Reset() - if _, err := w.crc32.Write(w.b[5:]); err != nil { - return errors.Wrap(err, "calculate label index CRC32 checksum") - } - w.b = w.crc32.Sum(w.b) - - return w.write(w.b) + err := w.write(w.buf1.get(), w.buf2.get()) + return errors.Wrap(err, "write postings") } type uint32slice []uint32 @@ -580,6 +573,21 @@ func (r *indexReader) lookupSymbol(o uint32) (string, error) { return yoloString(b), nil } +func (r *indexReader) getSized(off uint32) ([]byte, error) { + if int(off) > len(r.b) { + return nil, errInvalidSize + } + b := r.b[off:] + l, n := binary.Uvarint(b) + if n < 1 { + return nil, errInvalidSize + } + if int(l) > len(b[n:]) { + return nil, errInvalidSize + } + return b[n : n+int(l)], nil +} + func (r *indexReader) LabelValues(names ...string) (StringTuples, error) { key := strings.Join(names, string(sep)) off, ok := r.labels[key] @@ -590,15 +598,10 @@ func (r *indexReader) LabelValues(names ...string) (StringTuples, error) { //return nil, fmt.Errorf("label index doesn't exist") } - b := r.b[off:] - l, n := binary.Uvarint(b) - if n < 0 { - return nil, errors.New("reading symbol length failed") + b, err := r.getSized(off) + if err != nil { + return nil, errors.Wrapf(err, "get sized region at %d", off) } - if int(l) > len(b[n:]) { - return nil, errInvalidSize - } - b = b[n : n+int(l)] c, n := binary.Uvarint(b) if n < 1 { @@ -718,15 +721,10 @@ func (r *indexReader) Postings(name, value string) (Postings, error) { return emptyPostings, nil } - flag, b, err := r.section(off) + b, err := r.getSized(off) if err != nil { - return nil, errors.Wrapf(err, "section at %d", off) + return nil, errors.Wrapf(err, "get sized region at %d", off) } - - if flag != flagStd { - return nil, errors.Wrapf(errInvalidFlag, "section at %d", off) - } - // Add iterator over the bytes. if len(b)%4 != 0 { return nil, errors.Wrap(errInvalidSize, "plain postings entry")