Example #1
0
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
}
Example #2
0
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
}
Example #3
0
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
}
Example #4
0
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
}