diff --git a/go/storage/needle_read_write.go b/go/storage/needle_read_write.go index bcb93f57b..5c2054344 100644 --- a/go/storage/needle_read_write.go +++ b/go/storage/needle_read_write.go @@ -130,9 +130,11 @@ func (n *Needle) Read(r io.Reader, size uint32, version Version) (ret int, err e n.readNeedleHeader(bytes) n.Data = bytes[NeedleHeaderSize : NeedleHeaderSize+size] checksum := util.BytesToUint32(bytes[NeedleHeaderSize+size : NeedleHeaderSize+size+NeedleChecksumSize]) - if checksum != NewCRC(n.Data).Value() { + newChecksum := NewCRC(n.Data) + if checksum != newChecksum.Value() { return 0, errors.New("CRC error! Data On Disk Corrupted!") } + n.Checksum = newChecksum return case Version2: if size == 0 { @@ -151,9 +153,11 @@ func (n *Needle) Read(r io.Reader, size uint32, version Version) (ret int, err e } n.readNeedleDataVersion2(bytes[NeedleHeaderSize : NeedleHeaderSize+int(n.Size)]) checksum := util.BytesToUint32(bytes[NeedleHeaderSize+n.Size : NeedleHeaderSize+n.Size+NeedleChecksumSize]) - if checksum != NewCRC(n.Data).Value() { + newChecksum := NewCRC(n.Data) + if checksum != newChecksum.Value() { return 0, errors.New("CRC error! Data On Disk Corrupted!") } + n.Checksum = newChecksum return } return 0, fmt.Errorf("Unsupported Version! (%d)", version) diff --git a/go/storage/volume.go b/go/storage/volume.go index 0ec24d7d1..5b7487580 100644 --- a/go/storage/volume.go +++ b/go/storage/volume.go @@ -158,6 +158,27 @@ func (v *Volume) NeedToReplicate() bool { return v.ReplicaType.GetCopyCount() > 1 } +func (v *Volume) isFileUnchanged(n *Needle) bool { + nv, ok := v.nm.Get(n.Id) + if ok && nv.Offset > 0 { + if _, err := v.dataFile.Seek(int64(nv.Offset)*NeedlePaddingSize, 0); err != nil { + return false + } + oldNeedle := new(Needle) + oldNeedle.Read(v.dataFile, nv.Size, v.Version()) + if len(oldNeedle.Data) == len(n.Data) && oldNeedle.Checksum == n.Checksum { + length := len(n.Data) + for i := 0; i < length; i++ { + if n.Data[i] != oldNeedle.Data[i] { + return false + } + } + n.Size = oldNeedle.Size + return true + } + } + return false +} func (v *Volume) write(n *Needle) (size uint32, err error) { if v.readOnly { err = fmt.Errorf("%s is read-only", v.dataFile) @@ -165,6 +186,10 @@ func (v *Volume) write(n *Needle) (size uint32, err error) { } v.accessLock.Lock() defer v.accessLock.Unlock() + if v.isFileUnchanged(n) { + size = n.Size + return + } var offset int64 if offset, err = v.dataFile.Seek(0, 2); err != nil { return