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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: impl/memory/gkvlite_tracing_utils.go
diff --git a/impl/memory/gkvlite_tracing_utils.go b/impl/memory/gkvlite_tracing_utils.go
new file mode 100644
index 0000000000000000000000000000000000000000..b6f799134f7e04d7e89845253cd98f0d7b6e6f48
--- /dev/null
+++ b/impl/memory/gkvlite_tracing_utils.go
@@ -0,0 +1,198 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package memory
+
+import (
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "sync"
+ "sync/atomic"
+
+ "github.com/luci/gkvlite"
+)
+
+var logMemCollectionFolder = flag.String(
+ "luci.gae.gkvlite_trace_folder", "",
+ "Set to a folder path to enable debugging traces to be dumped there. Set to '-' to dump to stdout.")
+var logMemCollectionFolderTmp string
+var logMemCollectionOnce sync.Once
+var logMemCounter uint32
+var logMemNameKey = "holds a string indicating the GKVLiteDebuggingTraceName"
+var stdoutLock sync.Mutex
+
+func wrapTracingMemStore(store memStore) memStore {
+ var writer traceWriter
+ logNum := atomic.AddUint32(&logMemCounter, 1) - 1
+ collName := fmt.Sprintf("coll%d", logNum)
+
+ if *logMemCollectionFolder == "-" {
+ writer = func(format string, a ...interface{}) {
+ stdoutLock.Lock()
+ defer stdoutLock.Unlock()
+ fmt.Printf(format+"\n", a...)
+ }
+ } else {
+ logMemCollectionOnce.Do(func() {
+ var err error
+ logMemCollectionFolderTmp, err = ioutil.TempDir(*logMemCollectionFolder, "luci-gae-gkvlite_trace")
+ if err != nil {
+ panic(err)
+ }
+ logMemCollectionFolderTmp, err = filepath.Abs(logMemCollectionFolderTmp)
+ if err != nil {
+ panic(err)
+ }
+ fmt.Fprintf(os.Stderr, "Saving GKVLite trace files to %q\n", logMemCollectionFolderTmp)
+ })
+ if logMemCollectionFolderTmp == "" {
+ panic("unable to create folder for tracefiles")
+ }
+
+ lck := sync.Mutex{}
+ fname := fmt.Sprintf(filepath.Join(logMemCollectionFolderTmp, fmt.Sprintf("%d.trace", logNum)))
+ fil, err := os.Create(fname)
+ if err != nil {
+ panic(err)
+ }
+ writer = func(format string, a ...interface{}) {
+ lck.Lock()
+ defer lck.Unlock()
+ fmt.Fprintf(fil, format+"\n", a...)
+ }
+ runtime.SetFinalizer(&writer, func(_ *traceWriter) { fil.Close() })
+ }
+ writer("%s := newMemStore()", collName)
+ return &tracingMemStoreImpl{store, writer, collName, 0, false}
+}
+
+type traceWriter func(format string, a ...interface{})
+
+type tracingMemStoreImpl struct {
+ i memStore
+ w traceWriter
+
+ collName string
+ // for the mutable store, this is a counter that increments for every
+ // Snapshot, and for snapshots, this is the number of the snapshot.
+ snapNum uint
+ isSnap bool
+}
+
+var _ memStore = (*tracingMemStoreImpl)(nil)
+
+func (t *tracingMemStoreImpl) ImATestingSnapshot() {}
+
+func (t *tracingMemStoreImpl) colWriter(action, name string) traceWriter {
+ ident := t.ident()
+ hexname := hex.EncodeToString([]byte(name))
+ writer := func(format string, a ...interface{}) {
+ if strings.HasPrefix(format, "//") { // comment
+ t.w(format, a...)
+ } else {
+ t.w(fmt.Sprintf("%s_%s%s", ident, hexname, format), a...)
+ }
+ }
+ writer(" := %s.%s(%q)", ident, action, name)
+ return writer
+}
+
+func (t *tracingMemStoreImpl) ident() string {
+ if t.isSnap {
+ return fmt.Sprintf("%s_snap%d", t.collName, t.snapNum)
+ }
+ return t.collName
+}
+
+func (t *tracingMemStoreImpl) GetCollection(name string) memCollection {
+ coll := t.i.GetCollection(name)
+ if coll == nil {
+ t.w("// %s.GetCollection(%q) -> nil", t.ident(), name)
+ return nil
+ }
+ writer := t.colWriter("GetCollection", name)
+ return &tracingMemCollectionImpl{coll, writer, 0}
+}
+
+func (t *tracingMemStoreImpl) GetCollectionNames() []string {
+ t.w("%s.GetCollectionNames()", t.ident())
+ return t.i.GetCollectionNames()
+}
+
+func (t *tracingMemStoreImpl) GetOrCreateCollection(name string) memCollection {
+ writer := t.colWriter("GetOrCreateCollection", name)
+ return &tracingMemCollectionImpl{t.i.GetOrCreateCollection(name), writer, 0}
+}
+
+func (t *tracingMemStoreImpl) Snapshot() memStore {
+ snap := t.i.Snapshot()
+ if snap == t.i {
+ t.w("// %s.Snapshot() -> self", t.ident())
+ return t
+ }
+ ret := &tracingMemStoreImpl{snap, t.w, t.collName, t.snapNum, true}
+ t.w("%s := %s.Snapshot()", ret.ident(), t.ident())
+ t.snapNum++
+ return ret
+}
+
+func (t *tracingMemStoreImpl) IsReadOnly() bool {
+ return t.i.IsReadOnly()
+}
+
+type tracingMemCollectionImpl struct {
+ i memCollection
+ w traceWriter
+ visitNumber uint
+}
+
+var _ memCollection = (*tracingMemCollectionImpl)(nil)
+
+func (t *tracingMemCollectionImpl) Name() string {
+ return t.i.Name()
+}
+
+func (t *tracingMemCollectionImpl) Delete(k []byte) bool {
+ t.w(".Delete(%#v)", k)
+ return t.i.Delete(k)
+}
+
+func (t *tracingMemCollectionImpl) Get(k []byte) []byte {
+ t.w(".Get(%#v)", k)
+ return t.i.Get(k)
+}
+
+func (t *tracingMemCollectionImpl) GetTotals() (numItems, numBytes uint64) {
+ t.w(".GetTotals()")
+ return t.i.GetTotals()
+}
+
+func (t *tracingMemCollectionImpl) MinItem(withValue bool) *gkvlite.Item {
+ t.w(".MinItem(%t)", withValue)
+ return t.i.MinItem(withValue)
+}
+
+func (t *tracingMemCollectionImpl) Set(k, v []byte) {
+ t.w(".Set(%#v, %#v)", k, v)
+ t.i.Set(k, v)
+}
+
+func (t *tracingMemCollectionImpl) VisitItemsAscend(target []byte, withValue bool, visitor gkvlite.ItemVisitor) {
+ vnum := t.visitNumber
+ t.visitNumber++
+
+ t.w(".VisitItemsAscend(%#v, %t, func(i *gkvlite.Item) bool{ return true }) // BEGIN VisitItemsAscend(%d)", target, withValue, vnum)
+ defer t.w("// END VisitItemsAscend(%d)", vnum)
+ t.i.VisitItemsAscend(target, withValue, visitor)
+}
+
+func (t *tracingMemCollectionImpl) IsReadOnly() bool {
+ return t.i.IsReadOnly()
+}
« 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