Browse Source

adding special handling to recover data if possible

For bug #87 and #93, add special handling to recover data if possible.
pull/114/head
chrislusf 10 years ago
parent
commit
d48d76cb4f
  1. 30
      go/storage/volume.go

30
go/storage/volume.go

@ -123,16 +123,21 @@ func (v *Volume) Size() int64 {
glog.V(0).Infof("Failed to read file size %s %v", v.dataFile.Name(), e) glog.V(0).Infof("Failed to read file size %s %v", v.dataFile.Name(), e)
return -1 return -1
} }
// Close cleanly shuts down this volume
func (v *Volume) Close() { func (v *Volume) Close() {
v.accessLock.Lock() v.accessLock.Lock()
defer v.accessLock.Unlock() defer v.accessLock.Unlock()
v.nm.Close() v.nm.Close()
_ = v.dataFile.Close() _ = v.dataFile.Close()
} }
func (v *Volume) NeedToReplicate() bool { func (v *Volume) NeedToReplicate() bool {
return v.ReplicaPlacement.GetCopyCount() > 1 return v.ReplicaPlacement.GetCopyCount() > 1
} }
// isFileUnchanged checks whether this needle to write is same as last one.
// It requires serialized access in the same volume.
func (v *Volume) isFileUnchanged(n *Needle) bool { func (v *Volume) isFileUnchanged(n *Needle) bool {
nv, ok := v.nm.Get(n.Id) nv, ok := v.nm.Get(n.Id)
if ok && nv.Offset > 0 { if ok && nv.Offset > 0 {
@ -146,6 +151,7 @@ func (v *Volume) isFileUnchanged(n *Needle) bool {
return false return false
} }
// Destroy removes everything related to this volume
func (v *Volume) Destroy() (err error) { func (v *Volume) Destroy() (err error) {
if v.readOnly { if v.readOnly {
err = fmt.Errorf("%s is read-only", v.dataFile.Name()) err = fmt.Errorf("%s is read-only", v.dataFile.Name())
@ -223,7 +229,7 @@ func (v *Volume) delete(n *Needle) (uint32, error) {
if _, err := v.dataFile.Seek(0, 2); err != nil { if _, err := v.dataFile.Seek(0, 2); err != nil {
return size, err return size, err
} }
n.Data = make([]byte, 0)
n.Data = nil
_, err := n.Append(v.dataFile, v.Version()) _, err := n.Append(v.dataFile, v.Version())
return size, err return size, err
} }
@ -304,20 +310,36 @@ func ScanVolumeFile(dirname string, collection string, id VolumeId,
for n != nil { for n != nil {
if readNeedleBody { if readNeedleBody {
if err = n.ReadNeedleBody(v.dataFile, version, offset+int64(NeedleHeaderSize), rest); err != nil { if err = n.ReadNeedleBody(v.dataFile, version, offset+int64(NeedleHeaderSize), rest); err != nil {
err = fmt.Errorf("cannot read needle body: %v", err)
return
glog.V(0).Infof("cannot read needle body: %v", err)
//err = fmt.Errorf("cannot read needle body: %v", err)
//return
}
if n.DataSize >= n.Size {
// this should come from a bug reported on #87 and #93
// fixed in v0.69
// remove this whole "if" clause later, long after 0.69
oldRest, oldSize := rest, n.Size
padding := NeedlePaddingSize - ((n.Size + NeedleHeaderSize + NeedleChecksumSize) % NeedlePaddingSize)
n.Size = 0
rest = n.Size + NeedleChecksumSize + padding
if rest%NeedlePaddingSize != 0 {
rest += (NeedlePaddingSize - rest%NeedlePaddingSize)
}
glog.V(4).Infof("Adjusting n.Size %d=>0 rest:%d=>%d %+v", oldSize, oldRest, rest, n)
} }
} }
if err = visitNeedle(n, offset); err != nil { if err = visitNeedle(n, offset); err != nil {
return
glog.V(0).Infof("visit needle error: %v", err)
} }
offset += int64(NeedleHeaderSize) + int64(rest) offset += int64(NeedleHeaderSize) + int64(rest)
glog.V(4).Infof("==> new entry offset %d", offset)
if n, rest, err = ReadNeedleHeader(v.dataFile, version, offset); err != nil { if n, rest, err = ReadNeedleHeader(v.dataFile, version, offset); err != nil {
if err == io.EOF { if err == io.EOF {
return nil return nil
} }
return fmt.Errorf("cannot read needle header: %v", err) return fmt.Errorf("cannot read needle header: %v", err)
} }
glog.V(4).Infof("new entry needle size:%d rest:%d", n.Size, rest)
} }
return return

Loading…
Cancel
Save