package fuse import ( "sync" "time" ) // TimingRawFilesystem is a wrapper to collect timings for a RawFilesystem type TimingRawFilesystem struct { WrappingRawFilesystem statisticsLock sync.Mutex latencies map[string]int64 counts map[string]int64 } func NewTimingRawFilesystem(fs RawFileSystem) *TimingRawFilesystem { t := new(TimingRawFilesystem) t.Original = fs t.latencies = make(map[string]int64) t.counts = make(map[string]int64) return t } func (me *TimingRawFilesystem) startTimer(name string) (closure func()) { start := time.Nanoseconds() return func() { dt := (time.Nanoseconds() - start) / 1e6 me.statisticsLock.Lock() defer me.statisticsLock.Unlock() me.counts[name] += 1 me.latencies[name] += dt } } func (me *TimingRawFilesystem) Latencies() map[string]float64 { me.statisticsLock.Lock() defer me.statisticsLock.Unlock() r := make(map[string]float64) for k, v := range me.counts { r[k] = float64(me.latencies[k]) / float64(v) } return r } func (me *TimingRawFilesystem) Init(h *InHeader, input *InitIn) (*InitOut, Status) { defer me.startTimer("Init")() return me.Original.Init(h, input) } func (me *TimingRawFilesystem) Destroy(h *InHeader, input *InitIn) { defer me.startTimer("Destroy")() me.Original.Destroy(h, input) } func (me *TimingRawFilesystem) Lookup(h *InHeader, name string) (out *EntryOut, code Status) { defer me.startTimer("Lookup")() return me.Original.Lookup(h, name) } func (me *TimingRawFilesystem) Forget(h *InHeader, input *ForgetIn) { defer me.startTimer("Forget")() me.Original.Forget(h, input) } func (me *TimingRawFilesystem) GetAttr(header *InHeader, input *GetAttrIn) (out *AttrOut, code Status) { defer me.startTimer("GetAttr")() return me.Original.GetAttr(header, input) } func (me *TimingRawFilesystem) Open(header *InHeader, input *OpenIn) (flags uint32, handle uint64, status Status) { defer me.startTimer("Open")() return me.Original.Open(header, input) } func (me *TimingRawFilesystem) SetAttr(header *InHeader, input *SetAttrIn) (out *AttrOut, code Status) { defer me.startTimer("SetAttr")() return me.Original.SetAttr(header, input) } func (me *TimingRawFilesystem) Readlink(header *InHeader) (out []byte, code Status) { defer me.startTimer("Readlink")() return me.Original.Readlink(header) } func (me *TimingRawFilesystem) Mknod(header *InHeader, input *MknodIn, name string) (out *EntryOut, code Status) { defer me.startTimer("Mknod")() return me.Original.Mknod(header, input, name) } func (me *TimingRawFilesystem) Mkdir(header *InHeader, input *MkdirIn, name string) (out *EntryOut, code Status) { defer me.startTimer("Mkdir")() return me.Original.Mkdir(header, input, name) } func (me *TimingRawFilesystem) Unlink(header *InHeader, name string) (code Status) { defer me.startTimer("Unlink")() return me.Original.Unlink(header, name) } func (me *TimingRawFilesystem) Rmdir(header *InHeader, name string) (code Status) { defer me.startTimer("Rmdir")() return me.Original.Rmdir(header, name) } func (me *TimingRawFilesystem) Symlink(header *InHeader, pointedTo string, linkName string) (out *EntryOut, code Status) { defer me.startTimer("Symlink")() return me.Original.Symlink(header, pointedTo, linkName) } func (me *TimingRawFilesystem) Rename(header *InHeader, input *RenameIn, oldName string, newName string) (code Status) { defer me.startTimer("Rename")() return me.Original.Rename(header, input, oldName, newName) } func (me *TimingRawFilesystem) Link(header *InHeader, input *LinkIn, name string) (out *EntryOut, code Status) { defer me.startTimer("Link")() return me.Original.Link(header, input, name) } func (me *TimingRawFilesystem) SetXAttr(header *InHeader, input *SetXAttrIn, attr string, data []byte) Status { defer me.startTimer("SetXAttr")() return me.Original.SetXAttr(header, input, attr, data) } func (me *TimingRawFilesystem) GetXAttr(header *InHeader, attr string) (data []byte, code Status) { defer me.startTimer("GetXAttr")() return me.Original.GetXAttr(header, attr) } func (me *TimingRawFilesystem) ListXAttr(header *InHeader) (data []byte, code Status) { defer me.startTimer("ListXAttr")() return me.Original.ListXAttr(header) } func (me *TimingRawFilesystem) RemoveXAttr(header *InHeader, attr string) Status { defer me.startTimer("RemoveXAttr")() return me.Original.RemoveXAttr(header, attr) } func (me *TimingRawFilesystem) Access(header *InHeader, input *AccessIn) (code Status) { defer me.startTimer("Access")() return me.Original.Access(header, input) } func (me *TimingRawFilesystem) Create(header *InHeader, input *CreateIn, name string) (flags uint32, handle uint64, out *EntryOut, code Status) { defer me.startTimer("Create")() return me.Original.Create(header, input, name) } func (me *TimingRawFilesystem) Bmap(header *InHeader, input *BmapIn) (out *BmapOut, code Status) { defer me.startTimer("Bmap")() return me.Original.Bmap(header, input) } func (me *TimingRawFilesystem) Ioctl(header *InHeader, input *IoctlIn) (out *IoctlOut, code Status) { defer me.startTimer("Ioctl")() return me.Original.Ioctl(header, input) } func (me *TimingRawFilesystem) Poll(header *InHeader, input *PollIn) (out *PollOut, code Status) { defer me.startTimer("Poll")() return me.Original.Poll(header, input) } func (me *TimingRawFilesystem) OpenDir(header *InHeader, input *OpenIn) (flags uint32, fuseFile RawFuseDir, status Status) { defer me.startTimer("OpenDir")() return me.Original.OpenDir(header, input) } func (me *TimingRawFilesystem) Release(header *InHeader, input *ReleaseIn) { defer me.startTimer("Release")() me.Original.Release(header, input) } func (me *TimingRawFilesystem) ReleaseDir(header *InHeader, f RawFuseDir) { defer me.startTimer("ReleaseDir")() me.Original.ReleaseDir(header, f) } func (me *TimingRawFilesystem) Read(input *ReadIn, bp *BufferPool) ([]byte, Status) { defer me.startTimer("Read")() return me.Original.Read(input, bp) } func (me *TimingRawFilesystem) Write(input *WriteIn, data []byte) (written uint32, code Status) { defer me.startTimer("Write")() return me.Original.Write(input, data) } func (me *TimingRawFilesystem) Flush(input *FlushIn) Status { defer me.startTimer("Flush")() return me.Original.Flush(input) } func (me *TimingRawFilesystem) Fsync(input *FsyncIn) (code Status) { defer me.startTimer("Fsync")() return me.Original.Fsync(input) }