1// Copyright 2016 Keybase Inc. All rights reserved.
2// Use of this source code is governed by a BSD
3// license that can be found in the LICENSE file.
4
5package libkbfs
6
7import (
8	"github.com/keybase/client/go/kbfs/kbfsblock"
9	"github.com/keybase/client/go/kbfs/kbfscrypto"
10	"github.com/keybase/client/go/kbfs/tlf"
11	"github.com/keybase/client/go/protocol/keybase1"
12	metrics "github.com/rcrowley/go-metrics"
13	"golang.org/x/net/context"
14)
15
16// BlockServerMeasured delegates to another BlockServer instance but
17// also keeps track of stats.
18type BlockServerMeasured struct {
19	delegate                    BlockServer
20	getTimer                    metrics.Timer
21	getEncodedSizeTimer         metrics.Timer
22	putTimer                    metrics.Timer
23	putAgainTimer               metrics.Timer
24	addBlockReferenceTimer      metrics.Timer
25	removeBlockReferencesTimer  metrics.Timer
26	archiveBlockReferencesTimer metrics.Timer
27	getLiveBlockReferencesTimer metrics.Timer
28	isUnflushedTimer            metrics.Timer
29}
30
31var _ BlockServer = BlockServerMeasured{}
32
33// NewBlockServerMeasured creates and returns a new
34// BlockServerMeasured instance with the given delegate and registry.
35func NewBlockServerMeasured(delegate BlockServer, r metrics.Registry) BlockServerMeasured {
36	getTimer := metrics.GetOrRegisterTimer("BlockServer.Get", r)
37	getEncodedSizeTimer := metrics.GetOrRegisterTimer(
38		"BlockServer.GetEncodedSize", r)
39	putTimer := metrics.GetOrRegisterTimer("BlockServer.Put", r)
40	addBlockReferenceTimer := metrics.GetOrRegisterTimer("BlockServer.AddBlockReference", r)
41	removeBlockReferencesTimer := metrics.GetOrRegisterTimer("BlockServer.RemoveBlockReferences", r)
42	archiveBlockReferencesTimer := metrics.GetOrRegisterTimer("BlockServer.ArchiveBlockReferences", r)
43	getLiveBlockReferencesTimer := metrics.GetOrRegisterTimer("BlockServer.GetLiveBlockReferences", r)
44	isUnflushedTimer := metrics.GetOrRegisterTimer("BlockServer.IsUnflushed", r)
45	return BlockServerMeasured{
46		delegate:                    delegate,
47		getTimer:                    getTimer,
48		getEncodedSizeTimer:         getEncodedSizeTimer,
49		putTimer:                    putTimer,
50		addBlockReferenceTimer:      addBlockReferenceTimer,
51		removeBlockReferencesTimer:  removeBlockReferencesTimer,
52		archiveBlockReferencesTimer: archiveBlockReferencesTimer,
53		getLiveBlockReferencesTimer: getLiveBlockReferencesTimer,
54		isUnflushedTimer:            isUnflushedTimer,
55	}
56}
57
58// FastForwardBackoff implements the BlockServer interface.
59func (b BlockServerMeasured) FastForwardBackoff() {
60	b.delegate.FastForwardBackoff()
61}
62
63// Get implements the BlockServer interface for BlockServerMeasured.
64func (b BlockServerMeasured) Get(
65	ctx context.Context, tlfID tlf.ID, id kbfsblock.ID,
66	context kbfsblock.Context, cacheType DiskBlockCacheType) (
67	buf []byte, serverHalf kbfscrypto.BlockCryptKeyServerHalf, err error) {
68	b.getTimer.Time(func() {
69		buf, serverHalf, err = b.delegate.Get(
70			ctx, tlfID, id, context, cacheType)
71	})
72	return buf, serverHalf, err
73}
74
75// GetEncodedSizes implements the BlockServer interface for BlockServerMeasured.
76func (b BlockServerMeasured) GetEncodedSizes(
77	ctx context.Context, tlfID tlf.ID, ids []kbfsblock.ID,
78	contexts []kbfsblock.Context) (
79	sizes []uint32, statuses []keybase1.BlockStatus, err error) {
80	b.getEncodedSizeTimer.Time(func() {
81		sizes, statuses, err = b.delegate.GetEncodedSizes(
82			ctx, tlfID, ids, contexts)
83	})
84	return sizes, statuses, err
85}
86
87// Put implements the BlockServer interface for BlockServerMeasured.
88func (b BlockServerMeasured) Put(
89	ctx context.Context, tlfID tlf.ID, id kbfsblock.ID,
90	context kbfsblock.Context, buf []byte,
91	serverHalf kbfscrypto.BlockCryptKeyServerHalf,
92	cacheType DiskBlockCacheType) (err error) {
93	b.putTimer.Time(func() {
94		err = b.delegate.Put(
95			ctx, tlfID, id, context, buf, serverHalf, cacheType)
96	})
97	return err
98}
99
100// PutAgain implements the BlockServer interface for BlockServerMeasured.
101func (b BlockServerMeasured) PutAgain(
102	ctx context.Context, tlfID tlf.ID, id kbfsblock.ID,
103	context kbfsblock.Context, buf []byte,
104	serverHalf kbfscrypto.BlockCryptKeyServerHalf,
105	cacheType DiskBlockCacheType) (err error) {
106	b.putAgainTimer.Time(func() {
107		err = b.delegate.PutAgain(
108			ctx, tlfID, id, context, buf, serverHalf, cacheType)
109	})
110	return err
111}
112
113// AddBlockReference implements the BlockServer interface for
114// BlockServerMeasured.
115func (b BlockServerMeasured) AddBlockReference(ctx context.Context, tlfID tlf.ID,
116	id kbfsblock.ID, context kbfsblock.Context) (err error) {
117	b.addBlockReferenceTimer.Time(func() {
118		err = b.delegate.AddBlockReference(ctx, tlfID, id, context)
119	})
120	return err
121}
122
123// RemoveBlockReferences implements the BlockServer interface for
124// BlockServerMeasured.
125func (b BlockServerMeasured) RemoveBlockReferences(ctx context.Context,
126	tlfID tlf.ID, contexts kbfsblock.ContextMap) (
127	liveCounts map[kbfsblock.ID]int, err error) {
128	b.removeBlockReferencesTimer.Time(func() {
129		liveCounts, err = b.delegate.RemoveBlockReferences(
130			ctx, tlfID, contexts)
131	})
132	return liveCounts, err
133}
134
135// ArchiveBlockReferences implements the BlockServer interface for
136// BlockServerMeasured.
137func (b BlockServerMeasured) ArchiveBlockReferences(ctx context.Context,
138	tlfID tlf.ID, contexts kbfsblock.ContextMap) (err error) {
139	b.archiveBlockReferencesTimer.Time(func() {
140		err = b.delegate.ArchiveBlockReferences(ctx, tlfID, contexts)
141	})
142	return err
143}
144
145// GetLiveBlockReferences implements the BlockServer interface for
146// BlockServerMeasured.
147func (b BlockServerMeasured) GetLiveBlockReferences(
148	ctx context.Context, tlfID tlf.ID, contexts kbfsblock.ContextMap) (
149	liveCounts map[kbfsblock.ID]int, err error) {
150	b.getLiveBlockReferencesTimer.Time(func() {
151		liveCounts, err = b.delegate.GetLiveBlockReferences(
152			ctx, tlfID, contexts)
153	})
154	return liveCounts, err
155}
156
157// IsUnflushed implements the BlockServer interface for BlockServerMeasured.
158func (b BlockServerMeasured) IsUnflushed(ctx context.Context, tlfID tlf.ID,
159	id kbfsblock.ID) (isUnflushed bool, err error) {
160	b.isUnflushedTimer.Time(func() {
161		isUnflushed, err = b.delegate.IsUnflushed(ctx, tlfID, id)
162	})
163	return isUnflushed, err
164
165}
166
167// Shutdown implements the BlockServer interface for
168// BlockServerMeasured.
169func (b BlockServerMeasured) Shutdown(ctx context.Context) {
170	b.delegate.Shutdown(ctx)
171}
172
173// RefreshAuthToken implements the BlockServer interface for
174// BlockServerMeasured.
175func (b BlockServerMeasured) RefreshAuthToken(ctx context.Context) {
176	b.delegate.RefreshAuthToken(ctx)
177}
178
179// GetUserQuotaInfo implements the BlockServer interface for BlockServerMeasured
180func (b BlockServerMeasured) GetUserQuotaInfo(ctx context.Context) (info *kbfsblock.QuotaInfo, err error) {
181	return b.delegate.GetUserQuotaInfo(ctx)
182}
183
184// GetTeamQuotaInfo implements the BlockServer interface for BlockServerMeasured
185func (b BlockServerMeasured) GetTeamQuotaInfo(
186	ctx context.Context, tid keybase1.TeamID) (
187	info *kbfsblock.QuotaInfo, err error) {
188	return b.delegate.GetTeamQuotaInfo(ctx, tid)
189}
190