Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(754)

Side by Side Diff: impl/memory/gkvlite_tracing_utils.go

Issue 1911263002: Fix memory corruption bug in impl/memory (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/gae@master
Patch Set: fix comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « impl/memory/gkvlite_iter_test.go ('k') | impl/memory/gkvlite_utils.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package memory
6
7 import (
8 "encoding/hex"
9 "flag"
10 "fmt"
11 "io/ioutil"
12 "os"
13 "path/filepath"
14 "runtime"
15 "strings"
16 "sync"
17 "sync/atomic"
18
19 "github.com/luci/gkvlite"
20 )
21
22 var logMemCollectionFolder = flag.String(
23 "luci.gae.gkvlite_trace_folder", "",
24 "Set to a folder path to enable debugging traces to be dumped there. Set to '-' to dump to stdout.")
25 var logMemCollectionFolderTmp string
26 var logMemCollectionOnce sync.Once
27 var logMemCounter uint32
28 var logMemNameKey = "holds a string indicating the GKVLiteDebuggingTraceName"
29 var stdoutLock sync.Mutex
30
31 func wrapTracingMemStore(store memStore) memStore {
32 var writer traceWriter
33 logNum := atomic.AddUint32(&logMemCounter, 1) - 1
34 collName := fmt.Sprintf("coll%d", logNum)
35
36 if *logMemCollectionFolder == "-" {
37 writer = func(format string, a ...interface{}) {
38 stdoutLock.Lock()
39 defer stdoutLock.Unlock()
40 fmt.Printf(format+"\n", a...)
41 }
42 } else {
43 logMemCollectionOnce.Do(func() {
44 var err error
45 logMemCollectionFolderTmp, err = ioutil.TempDir(*logMemC ollectionFolder, "luci-gae-gkvlite_trace")
46 if err != nil {
47 panic(err)
48 }
49 logMemCollectionFolderTmp, err = filepath.Abs(logMemColl ectionFolderTmp)
50 if err != nil {
51 panic(err)
52 }
53 fmt.Fprintf(os.Stderr, "Saving GKVLite trace files to %q \n", logMemCollectionFolderTmp)
54 })
55 if logMemCollectionFolderTmp == "" {
56 panic("unable to create folder for tracefiles")
57 }
58
59 lck := sync.Mutex{}
60 fname := fmt.Sprintf(filepath.Join(logMemCollectionFolderTmp, fm t.Sprintf("%d.trace", logNum)))
61 fil, err := os.Create(fname)
62 if err != nil {
63 panic(err)
64 }
65 writer = func(format string, a ...interface{}) {
66 lck.Lock()
67 defer lck.Unlock()
68 fmt.Fprintf(fil, format+"\n", a...)
69 }
70 runtime.SetFinalizer(&writer, func(_ *traceWriter) { fil.Close() })
71 }
72 writer("%s := newMemStore()", collName)
73 return &tracingMemStoreImpl{store, writer, collName, 0, false}
74 }
75
76 type traceWriter func(format string, a ...interface{})
77
78 type tracingMemStoreImpl struct {
79 i memStore
80 w traceWriter
81
82 collName string
83 // for the mutable store, this is a counter that increments for every
84 // Snapshot, and for snapshots, this is the number of the snapshot.
85 snapNum uint
86 isSnap bool
87 }
88
89 var _ memStore = (*tracingMemStoreImpl)(nil)
90
91 func (t *tracingMemStoreImpl) ImATestingSnapshot() {}
92
93 func (t *tracingMemStoreImpl) colWriter(action, name string) traceWriter {
94 ident := t.ident()
95 hexname := hex.EncodeToString([]byte(name))
96 writer := func(format string, a ...interface{}) {
97 if strings.HasPrefix(format, "//") { // comment
98 t.w(format, a...)
99 } else {
100 t.w(fmt.Sprintf("%s_%s%s", ident, hexname, format), a... )
101 }
102 }
103 writer(" := %s.%s(%q)", ident, action, name)
104 return writer
105 }
106
107 func (t *tracingMemStoreImpl) ident() string {
108 if t.isSnap {
109 return fmt.Sprintf("%s_snap%d", t.collName, t.snapNum)
110 }
111 return t.collName
112 }
113
114 func (t *tracingMemStoreImpl) GetCollection(name string) memCollection {
115 coll := t.i.GetCollection(name)
116 if coll == nil {
117 t.w("// %s.GetCollection(%q) -> nil", t.ident(), name)
118 return nil
119 }
120 writer := t.colWriter("GetCollection", name)
121 return &tracingMemCollectionImpl{coll, writer, 0}
122 }
123
124 func (t *tracingMemStoreImpl) GetCollectionNames() []string {
125 t.w("%s.GetCollectionNames()", t.ident())
126 return t.i.GetCollectionNames()
127 }
128
129 func (t *tracingMemStoreImpl) GetOrCreateCollection(name string) memCollection {
130 writer := t.colWriter("GetOrCreateCollection", name)
131 return &tracingMemCollectionImpl{t.i.GetOrCreateCollection(name), writer , 0}
132 }
133
134 func (t *tracingMemStoreImpl) Snapshot() memStore {
135 snap := t.i.Snapshot()
136 if snap == t.i {
137 t.w("// %s.Snapshot() -> self", t.ident())
138 return t
139 }
140 ret := &tracingMemStoreImpl{snap, t.w, t.collName, t.snapNum, true}
141 t.w("%s := %s.Snapshot()", ret.ident(), t.ident())
142 t.snapNum++
143 return ret
144 }
145
146 func (t *tracingMemStoreImpl) IsReadOnly() bool {
147 return t.i.IsReadOnly()
148 }
149
150 type tracingMemCollectionImpl struct {
151 i memCollection
152 w traceWriter
153 visitNumber uint
154 }
155
156 var _ memCollection = (*tracingMemCollectionImpl)(nil)
157
158 func (t *tracingMemCollectionImpl) Name() string {
159 return t.i.Name()
160 }
161
162 func (t *tracingMemCollectionImpl) Delete(k []byte) bool {
163 t.w(".Delete(%#v)", k)
164 return t.i.Delete(k)
165 }
166
167 func (t *tracingMemCollectionImpl) Get(k []byte) []byte {
168 t.w(".Get(%#v)", k)
169 return t.i.Get(k)
170 }
171
172 func (t *tracingMemCollectionImpl) GetTotals() (numItems, numBytes uint64) {
173 t.w(".GetTotals()")
174 return t.i.GetTotals()
175 }
176
177 func (t *tracingMemCollectionImpl) MinItem(withValue bool) *gkvlite.Item {
178 t.w(".MinItem(%t)", withValue)
179 return t.i.MinItem(withValue)
180 }
181
182 func (t *tracingMemCollectionImpl) Set(k, v []byte) {
183 t.w(".Set(%#v, %#v)", k, v)
184 t.i.Set(k, v)
185 }
186
187 func (t *tracingMemCollectionImpl) VisitItemsAscend(target []byte, withValue boo l, visitor gkvlite.ItemVisitor) {
188 vnum := t.visitNumber
189 t.visitNumber++
190
191 t.w(".VisitItemsAscend(%#v, %t, func(i *gkvlite.Item) bool{ return true }) // BEGIN VisitItemsAscend(%d)", target, withValue, vnum)
192 defer t.w("// END VisitItemsAscend(%d)", vnum)
193 t.i.VisitItemsAscend(target, withValue, visitor)
194 }
195
196 func (t *tracingMemCollectionImpl) IsReadOnly() bool {
197 return t.i.IsReadOnly()
198 }
OLDNEW
« no previous file with comments | « impl/memory/gkvlite_iter_test.go ('k') | impl/memory/gkvlite_utils.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698