func (s *storage) reindexOne(ctx *context.Context, index sorted.KeyValue, overwrite bool, packID int) error { var batch sorted.BatchMutation if overwrite { batch = index.BeginBatch() } allOk := true // TODO(tgulacsi): proper verbose from context verbose := camliDebug err := s.walkPack(verbose, packID, func(packID int, ref blob.Ref, offset int64, size uint32) error { if !ref.Valid() { if camliDebug { log.Printf("found deleted blob in %d at %d with size %d", packID, offset, size) } return nil } meta := blobMeta{packID, offset, size}.String() if overwrite && batch != nil { batch.Set(ref.String(), meta) } else { if old, err := index.Get(ref.String()); err != nil { allOk = false if err == sorted.ErrNotFound { log.Println(ref.String() + ": cannot find in index!") } else { log.Println(ref.String()+": error getting from index: ", err.Error()) } } else if old != meta { allOk = false log.Printf("%s: index mismatch - index=%s data=%s", ref.String(), old, meta) } } return nil }) if err != nil { return err } if overwrite && batch != nil { log.Printf("overwriting %s from %d", index, packID) if err = index.CommitBatch(batch); err != nil { return err } } else if !allOk { return fmt.Errorf("index does not match data in %d", packID) } return nil }
func (kv *KeyValue) CommitBatch(bm sorted.BatchMutation) error { kv.mu.RLock() defer kv.mu.RUnlock() b, ok := bm.(*batch) if !ok { return fmt.Errorf("unexpected BatchMutation type %T", bm) } var ( // A batch mutation for applying this mutation to the buffer. bmbuf = kv.buf.BeginBatch() // A lazily created batch mutation for deleting from the backing // storage; this should be rare. (See Delete above.) bmback sorted.BatchMutation ) for _, m := range b.mods { if m.isDelete { bmbuf.Delete(m.key) if bmback == nil { bmback = kv.back.BeginBatch() } bmback.Delete(m.key) continue } else { if err := sorted.CheckSizes(m.key, m.value); err != nil { log.Printf("Skipping storing (%q:%q): %v", m.key, m.value, err) continue } } bmbuf.Set(m.key, m.value) } if err := kv.buf.CommitBatch(bmbuf); err != nil { return err } if bmback != nil { return kv.back.CommitBatch(bmback) } return nil }
func (s *storage) reindexOne(ctx *context.Context, index sorted.KeyValue, overwrite bool, packID int) error { var batch sorted.BatchMutation if overwrite { batch = index.BeginBatch() } allOk := true // TODO(tgulacsi): proper verbose from context verbose := env.IsDebug() misses := make(map[blob.Ref]string, 8) err := s.walkPack(verbose, packID, func(packID int, ref blob.Ref, offset int64, size uint32) error { if !ref.Valid() { if verbose { log.Printf("found deleted blob in %d at %d with size %d", packID, offset, size) } return nil } meta := blobMeta{packID, offset, size}.String() if overwrite && batch != nil { batch.Set(ref.String(), meta) return nil } if _, ok := misses[ref]; ok { // maybe this is the last of this blob. delete(misses, ref) } if old, err := index.Get(ref.String()); err != nil { allOk = false if err == sorted.ErrNotFound { log.Println(ref.String() + ": cannot find in index!") } else { log.Println(ref.String()+": error getting from index: ", err.Error()) } } else if old != meta { if old > meta { misses[ref] = meta log.Printf("WARN: possible duplicate blob %s", ref.String()) } else { allOk = false log.Printf("ERROR: index mismatch for %s - index=%s, meta=%s!", ref.String(), old, meta) } } return nil }) if err != nil { return err } for ref, meta := range misses { log.Printf("ERROR: index mismatch for %s (%s)!", ref.String(), meta) allOk = false } if overwrite && batch != nil { if err := index.CommitBatch(batch); err != nil { return err } } else if !allOk { return fmt.Errorf("index does not match data in %d", packID) } return nil }
func reindexOne(index sorted.KeyValue, overwrite, verbose bool, r io.ReadSeeker, name string, packId int64) error { l, err := lock.Lock(name + ".lock") defer l.Close() var pos, size int64 errAt := func(prefix, suffix string) error { if prefix != "" { prefix = prefix + " " } if suffix != "" { suffix = " " + suffix } return fmt.Errorf(prefix+"at %d (0x%x) in %q:"+suffix, pos, pos, name) } var batch sorted.BatchMutation if overwrite { batch = index.BeginBatch() } allOk := true br := bufio.NewReaderSize(r, 512) for { if b, err := br.ReadByte(); err != nil { if err == io.EOF { break } return errAt("error while reading", err.Error()) } else if b != '[' { return errAt(fmt.Sprintf("found byte 0x%x", b), "but '[' should be here!") } chunk, err := br.ReadSlice(']') if err != nil { if err == io.EOF { break } return errAt("error reading blob header", err.Error()) } m := len(chunk) chunk = chunk[:m-1] i := bytes.IndexByte(chunk, byte(' ')) if i <= 0 { return errAt("", fmt.Sprintf("bad header format (no space in %q)", chunk)) } if size, err = strconv.ParseInt(string(chunk[i+1:]), 10, 64); err != nil { return errAt(fmt.Sprintf("cannot parse size %q as int", chunk[i+1:]), err.Error()) } ref, ok := blob.Parse(string(chunk[:i])) if !ok { return errAt("", fmt.Sprintf("cannot parse %q as blobref", chunk[:i])) } if verbose { log.Printf("found %s at %d", ref, pos) } meta := blobMeta{packId, pos + 1 + int64(m), size}.String() if overwrite && batch != nil { batch.Set(ref.String(), meta) } else { if old, err := index.Get(ref.String()); err != nil { allOk = false if err == sorted.ErrNotFound { log.Println(ref.String() + ": cannot find in index!") } else { log.Println(ref.String()+": error getting from index: ", err.Error()) } } else if old != meta { allOk = false log.Printf("%s: index mismatch - index=%s data=%s", ref.String(), old, meta) } } pos += 1 + int64(m) // TODO(tgulacsi78): not just seek, but check the hashes of the files // maybe with a different command-line flag, only. if pos, err = r.Seek(pos+size, 0); err != nil { return errAt("", "cannot seek +"+strconv.FormatInt(size, 10)+" bytes") } // drain the buffer after the underlying reader Seeks io.CopyN(ioutil.Discard, br, int64(br.Buffered())) } if overwrite && batch != nil { log.Printf("overwriting %s from %s", index, name) if err = index.CommitBatch(batch); err != nil { return err } } else if !allOk { return fmt.Errorf("index does not match data in %q", name) } return nil }