]> Sergey Matveev's repositories - btrtrc.git/blobdiff - mmap_span/mmap_span.go
Big visibility/doc clean-up, and extract mmap_span package
[btrtrc.git] / mmap_span / mmap_span.go
diff --git a/mmap_span/mmap_span.go b/mmap_span/mmap_span.go
new file mode 100644 (file)
index 0000000..66635a1
--- /dev/null
@@ -0,0 +1,86 @@
+package mmap_span
+
+import (
+       "io"
+
+       "launchpad.net/gommap"
+)
+
+type segment struct {
+       gommap.MMap
+}
+
+func (me segment) Size() int64 {
+       return int64(len(me.MMap))
+}
+
+type MMapSpan []gommap.MMap
+
+func (me MMapSpan) span() (s span) {
+       for _, mmap := range me {
+               s = append(s, segment{mmap})
+       }
+       return
+}
+
+func (me MMapSpan) Close() {
+       for _, mMap := range me {
+               mMap.UnsafeUnmap()
+       }
+}
+
+func (me MMapSpan) Size() (ret int64) {
+       for _, seg := range me.span() {
+               ret += seg.Size()
+       }
+       return
+}
+
+func (me MMapSpan) ReadAt(p []byte, off int64) (n int, err error) {
+       me.span().ApplyTo(off, func(intervalOffset int64, interval sizer) (stop bool) {
+               _n := copy(p, interval.(segment).MMap[intervalOffset:])
+               p = p[_n:]
+               n += _n
+               return len(p) == 0
+       })
+       if len(p) != 0 {
+               err = io.EOF
+       }
+       return
+}
+
+func (me MMapSpan) WriteSectionTo(w io.Writer, off, n int64) (written int64, err error) {
+       me.span().ApplyTo(off, func(intervalOffset int64, interval sizer) (stop bool) {
+               var _n int
+               p := interval.(segment).MMap[intervalOffset:]
+               if n < int64(len(p)) {
+                       p = p[:n]
+               }
+               _n, err = w.Write(p)
+               written += int64(_n)
+               n -= int64(_n)
+               if err != nil {
+                       return true
+               }
+               return n == 0
+       })
+       return
+}
+
+func (me MMapSpan) WriteAt(p []byte, off int64) (n int, err error) {
+       me.span().ApplyTo(off, func(iOff int64, i sizer) (stop bool) {
+               mMap := i.(segment)
+               _n := copy(mMap.MMap[iOff:], p)
+               // err = mMap.Sync(gommap.MS_ASYNC)
+               // if err != nil {
+               //      return true
+               // }
+               p = p[_n:]
+               n += _n
+               return len(p) == 0
+       })
+       if err != nil && len(p) != 0 {
+               err = io.ErrShortWrite
+       }
+       return
+}