OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package memory | 5 package memory |
6 | 6 |
7 import ( | 7 import ( |
8 "encoding/hex" | 8 "encoding/hex" |
9 "flag" | 9 "flag" |
10 "fmt" | 10 "fmt" |
11 "io/ioutil" | 11 "io/ioutil" |
12 "os" | 12 "os" |
13 "path/filepath" | 13 "path/filepath" |
14 "runtime" | 14 "runtime" |
15 "strings" | 15 "strings" |
16 "sync" | 16 "sync" |
17 "sync/atomic" | 17 "sync/atomic" |
18 | |
19 "github.com/luci/gkvlite" | |
20 ) | 18 ) |
21 | 19 |
22 var logMemCollectionFolder = flag.String( | 20 var logMemCollectionFolder = flag.String( |
23 » "luci.gae.gkvlite_trace_folder", "", | 21 » "luci.gae.store_trace_folder", "", |
24 "Set to a folder path to enable debugging traces to be dumped there. Set
to '-' to dump to stdout.") | 22 "Set to a folder path to enable debugging traces to be dumped there. Set
to '-' to dump to stdout.") |
25 var logMemCollectionFolderTmp string | 23 var logMemCollectionFolderTmp string |
26 var logMemCollectionOnce sync.Once | 24 var logMemCollectionOnce sync.Once |
27 var logMemCounter uint32 | 25 var logMemCounter uint32 |
28 var logMemNameKey = "holds a string indicating the GKVLiteDebuggingTraceName" | 26 var logMemNameKey = "holds a string indicating the StoreDebuggingTraceName" |
29 var stdoutLock sync.Mutex | 27 var stdoutLock sync.Mutex |
30 | 28 |
31 func wrapTracingMemStore(store memStore) memStore { | 29 func wrapTracingMemStore(store memStore) memStore { |
32 var writer traceWriter | 30 var writer traceWriter |
33 logNum := atomic.AddUint32(&logMemCounter, 1) - 1 | 31 logNum := atomic.AddUint32(&logMemCounter, 1) - 1 |
34 collName := fmt.Sprintf("coll%d", logNum) | 32 collName := fmt.Sprintf("coll%d", logNum) |
35 | 33 |
36 if *logMemCollectionFolder == "-" { | 34 if *logMemCollectionFolder == "-" { |
37 writer = func(format string, a ...interface{}) { | 35 writer = func(format string, a ...interface{}) { |
38 stdoutLock.Lock() | 36 stdoutLock.Lock() |
39 defer stdoutLock.Unlock() | 37 defer stdoutLock.Unlock() |
40 fmt.Printf(format+"\n", a...) | 38 fmt.Printf(format+"\n", a...) |
41 } | 39 } |
42 } else { | 40 } else { |
43 logMemCollectionOnce.Do(func() { | 41 logMemCollectionOnce.Do(func() { |
44 var err error | 42 var err error |
45 » » » logMemCollectionFolderTmp, err = ioutil.TempDir(*logMemC
ollectionFolder, "luci-gae-gkvlite_trace") | 43 » » » logMemCollectionFolderTmp, err = ioutil.TempDir(*logMemC
ollectionFolder, "luci-gae-store_trace") |
46 if err != nil { | 44 if err != nil { |
47 panic(err) | 45 panic(err) |
48 } | 46 } |
49 logMemCollectionFolderTmp, err = filepath.Abs(logMemColl
ectionFolderTmp) | 47 logMemCollectionFolderTmp, err = filepath.Abs(logMemColl
ectionFolderTmp) |
50 if err != nil { | 48 if err != nil { |
51 panic(err) | 49 panic(err) |
52 } | 50 } |
53 » » » fmt.Fprintf(os.Stderr, "Saving GKVLite trace files to %q
\n", logMemCollectionFolderTmp) | 51 » » » fmt.Fprintf(os.Stderr, "Saving store trace files to %q\n
", logMemCollectionFolderTmp) |
54 }) | 52 }) |
55 if logMemCollectionFolderTmp == "" { | 53 if logMemCollectionFolderTmp == "" { |
56 panic("unable to create folder for tracefiles") | 54 panic("unable to create folder for tracefiles") |
57 } | 55 } |
58 | 56 |
59 lck := sync.Mutex{} | 57 lck := sync.Mutex{} |
60 fname := fmt.Sprintf(filepath.Join(logMemCollectionFolderTmp, fm
t.Sprintf("%d.trace", logNum))) | 58 fname := fmt.Sprintf(filepath.Join(logMemCollectionFolderTmp, fm
t.Sprintf("%d.trace", logNum))) |
61 fil, err := os.Create(fname) | 59 fil, err := os.Create(fname) |
62 if err != nil { | 60 if err != nil { |
63 panic(err) | 61 panic(err) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 return t.collName | 109 return t.collName |
112 } | 110 } |
113 | 111 |
114 func (t *tracingMemStoreImpl) GetCollection(name string) memCollection { | 112 func (t *tracingMemStoreImpl) GetCollection(name string) memCollection { |
115 coll := t.i.GetCollection(name) | 113 coll := t.i.GetCollection(name) |
116 if coll == nil { | 114 if coll == nil { |
117 t.w("// %s.GetCollection(%q) -> nil", t.ident(), name) | 115 t.w("// %s.GetCollection(%q) -> nil", t.ident(), name) |
118 return nil | 116 return nil |
119 } | 117 } |
120 writer := t.colWriter("GetCollection", name) | 118 writer := t.colWriter("GetCollection", name) |
121 » return &tracingMemCollectionImpl{coll, writer, 0} | 119 » return &tracingMemCollectionImpl{coll, writer, 0, 0} |
122 } | 120 } |
123 | 121 |
124 func (t *tracingMemStoreImpl) GetCollectionNames() []string { | 122 func (t *tracingMemStoreImpl) GetCollectionNames() []string { |
125 t.w("%s.GetCollectionNames()", t.ident()) | 123 t.w("%s.GetCollectionNames()", t.ident()) |
126 return t.i.GetCollectionNames() | 124 return t.i.GetCollectionNames() |
127 } | 125 } |
128 | 126 |
129 func (t *tracingMemStoreImpl) GetOrCreateCollection(name string) memCollection { | 127 func (t *tracingMemStoreImpl) GetOrCreateCollection(name string) memCollection { |
130 writer := t.colWriter("GetOrCreateCollection", name) | 128 writer := t.colWriter("GetOrCreateCollection", name) |
131 » return &tracingMemCollectionImpl{t.i.GetOrCreateCollection(name), writer
, 0} | 129 » return &tracingMemCollectionImpl{t.i.GetOrCreateCollection(name), writer
, 0, 0} |
132 } | 130 } |
133 | 131 |
134 func (t *tracingMemStoreImpl) Snapshot() memStore { | 132 func (t *tracingMemStoreImpl) Snapshot() memStore { |
135 snap := t.i.Snapshot() | 133 snap := t.i.Snapshot() |
136 if snap == t.i { | 134 if snap == t.i { |
137 t.w("// %s.Snapshot() -> self", t.ident()) | 135 t.w("// %s.Snapshot() -> self", t.ident()) |
138 return t | 136 return t |
139 } | 137 } |
140 ret := &tracingMemStoreImpl{snap, t.w, t.collName, t.snapNum, true} | 138 ret := &tracingMemStoreImpl{snap, t.w, t.collName, t.snapNum, true} |
141 t.w("%s := %s.Snapshot()", ret.ident(), t.ident()) | 139 t.w("%s := %s.Snapshot()", ret.ident(), t.ident()) |
142 t.snapNum++ | 140 t.snapNum++ |
143 return ret | 141 return ret |
144 } | 142 } |
145 | 143 |
146 func (t *tracingMemStoreImpl) IsReadOnly() bool { | 144 func (t *tracingMemStoreImpl) IsReadOnly() bool { |
147 return t.i.IsReadOnly() | 145 return t.i.IsReadOnly() |
148 } | 146 } |
149 | 147 |
150 type tracingMemCollectionImpl struct { | 148 type tracingMemCollectionImpl struct { |
151 » i memCollection | 149 » i memCollection |
152 » w traceWriter | 150 » w traceWriter |
153 » visitNumber uint | 151 |
| 152 » iterNumber uint |
| 153 » forEachNumber uint |
154 } | 154 } |
155 | 155 |
156 var _ memCollection = (*tracingMemCollectionImpl)(nil) | 156 var _ memCollection = (*tracingMemCollectionImpl)(nil) |
157 | 157 |
158 func (t *tracingMemCollectionImpl) Name() string { | 158 func (t *tracingMemCollectionImpl) Name() string { |
159 return t.i.Name() | 159 return t.i.Name() |
160 } | 160 } |
161 | 161 |
162 func (t *tracingMemCollectionImpl) Delete(k []byte) bool { | 162 func (t *tracingMemCollectionImpl) Delete(k []byte) { |
163 t.w(".Delete(%#v)", k) | 163 t.w(".Delete(%#v)", k) |
164 » return t.i.Delete(k) | 164 » t.i.Delete(k) |
165 } | 165 } |
166 | 166 |
167 func (t *tracingMemCollectionImpl) Get(k []byte) []byte { | 167 func (t *tracingMemCollectionImpl) Get(k []byte) []byte { |
168 t.w(".Get(%#v)", k) | 168 t.w(".Get(%#v)", k) |
169 return t.i.Get(k) | 169 return t.i.Get(k) |
170 } | 170 } |
171 | 171 |
172 func (t *tracingMemCollectionImpl) GetTotals() (numItems, numBytes uint64) { | 172 func (t *tracingMemCollectionImpl) MinItem() *storeEntry { |
173 » t.w(".GetTotals()") | 173 » t.w(".MinItem()") |
174 » return t.i.GetTotals() | 174 » return t.i.MinItem() |
175 } | |
176 | |
177 func (t *tracingMemCollectionImpl) MinItem(withValue bool) *gkvlite.Item { | |
178 » t.w(".MinItem(%t)", withValue) | |
179 » return t.i.MinItem(withValue) | |
180 } | 175 } |
181 | 176 |
182 func (t *tracingMemCollectionImpl) Set(k, v []byte) { | 177 func (t *tracingMemCollectionImpl) Set(k, v []byte) { |
183 t.w(".Set(%#v, %#v)", k, v) | 178 t.w(".Set(%#v, %#v)", k, v) |
184 t.i.Set(k, v) | 179 t.i.Set(k, v) |
185 } | 180 } |
186 | 181 |
187 func (t *tracingMemCollectionImpl) VisitItemsAscend(target []byte, withValue boo
l, visitor gkvlite.ItemVisitor) { | 182 func (t *tracingMemCollectionImpl) Iterator(pivot []byte) memIterator { |
188 » vnum := t.visitNumber | 183 » inum := t.iterNumber |
189 » t.visitNumber++ | 184 » t.iterNumber++ |
190 | 185 |
191 » t.w(".VisitItemsAscend(%#v, %t, func(i *gkvlite.Item) bool{ return true
}) // BEGIN VisitItemsAscend(%d)", target, withValue, vnum) | 186 » t.w(".Iterator(%#v) // Created Iterator #%d", pivot, inum) |
192 » defer t.w("// END VisitItemsAscend(%d)", vnum) | 187 » return &tracingMemIteratorImpl{t.i.Iterator(pivot), t.w, inum} |
193 » t.i.VisitItemsAscend(target, withValue, visitor) | 188 } |
| 189 |
| 190 func (t *tracingMemCollectionImpl) ForEachItem(fn memVisitor) { |
| 191 » vnum := t.forEachNumber |
| 192 » t.forEachNumber++ |
| 193 |
| 194 » t.w(".ForEachItem(func(k, v []byte) bool{ return true }) // BEGIN ForEac
hItem(%d)", vnum) |
| 195 » defer t.w("// END ForEachItem(%d)", vnum) |
| 196 » t.i.ForEachItem(fn) |
194 } | 197 } |
195 | 198 |
196 func (t *tracingMemCollectionImpl) IsReadOnly() bool { | 199 func (t *tracingMemCollectionImpl) IsReadOnly() bool { |
197 return t.i.IsReadOnly() | 200 return t.i.IsReadOnly() |
198 } | 201 } |
| 202 |
| 203 type tracingMemIteratorImpl struct { |
| 204 i memIterator |
| 205 w traceWriter |
| 206 num uint |
| 207 } |
| 208 |
| 209 func (t *tracingMemIteratorImpl) Next() *storeEntry { |
| 210 t.w(".Next() // Iterator #%d", t.num) |
| 211 return t.i.Next() |
| 212 } |
OLD | NEW |