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

Unified Diff: client/internal/logdog/butler/bundler/builder.go

Issue 1412063008: logdog: Add bundler library. (Closed) Base URL: https://github.com/luci/luci-go@logdog-review-streamserver
Patch Set: Enhanced doc.go. Created 5 years, 1 month 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
Index: client/internal/logdog/butler/bundler/builder.go
diff --git a/client/internal/logdog/butler/bundler/builder.go b/client/internal/logdog/butler/bundler/builder.go
new file mode 100644
index 0000000000000000000000000000000000000000..d80f766f393070da45ced53875cf069accffd895
--- /dev/null
+++ b/client/internal/logdog/butler/bundler/builder.go
@@ -0,0 +1,116 @@
+// 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 bundler
+
+import (
+ "fmt"
+ "sort"
+
+ "github.com/luci/luci-go/common/logdog/protocol"
+)
+
+// builder incrementally constructs ButlerLogBundle entries.
+type builder struct {
+ // template is the base bundle template.
+ template protocol.ButlerLogBundle
+ // size is the maximum permitted bundle size.
+ size int
+
+ // templateCachedSize is the cached size of the ButlerLogBundle template.
+ templateCachedSize int
iannucci 2015/11/13 07:16:38 this should go up near template. I thought it was
dnj 2015/11/14 00:30:36 Done.
+ // entries is the set of ButlerLogBundle_Entry stream state.
+ beMap map[string]*protocol.ButlerLogBundle_Entry
iannucci 2015/11/13 07:16:38 comment what the 'string' is?
dnj 2015/11/14 00:30:36 Done.
+ // beSizes tracks the size of a ButlerLogBundle_Entry.
+ beSizes map[string]int
+}
+
+func (b *builder) remaining() int {
+ return b.size - b.bundleSize()
+}
+
+func (b *builder) ready() bool {
+ // Have we reached our desired size?
+ return b.hasContent() && (b.bundleSize() >= b.size)
+}
+
+func (b *builder) bundleSize() int {
+ if b.templateCachedSize == 0 {
+ b.templateCachedSize = protoSize(&b.template)
+ }
+
+ size := b.templateCachedSize
+ for _, sz := range b.beSizes {
+ size += sizeOfBundleEntryTag + varintLength(uint64(sz)) + sz
+ }
+
+ return size
+}
+
+func (b *builder) hasContent() bool {
+ return len(b.beMap) > 0
+}
+
+func (b *builder) add(template *protocol.ButlerLogBundle_Entry, le *protocol.LogEntry) {
+ be := b.getCreateBundleEntry(template)
+
+ be.Logs = append(be.Logs, le)
+ psize := protoSize(le)
+
+ // Pay the cost of the additional LogEntry.
+ b.beSizes[template.Desc.Name] += sizeOfLogEntryTag + varintLength(uint64(psize)) + psize
+}
+
+func (b *builder) setStreamTerminal(template *protocol.ButlerLogBundle_Entry, tidx uint64) {
+ be := b.getCreateBundleEntry(template)
+ if be.Terminal {
+ if be.TerminalIndex != tidx {
+ panic(fmt.Errorf("attempt to change terminal index %d => %d", be.TerminalIndex, tidx))
+ }
+ return
+ }
+
+ be.Terminal = true
+ be.TerminalIndex = tidx
+
+ // Pay the cost of the additional terminal fields.
+ b.beSizes[template.Desc.Name] += (sizeOfTerminalTag + sizeOfBoolTrue +
+ sizeOfTerminalIndexTag + varintLength(be.TerminalIndex))
+}
+
+func (b *builder) bundle() *protocol.ButlerLogBundle {
+ bundle := b.template
+
+ names := make([]string, 0, len(b.beMap))
+ for k := range b.beMap {
+ names = append(names, k)
+ }
+ sort.Strings(names)
+
+ bundle.Entries = make([]*protocol.ButlerLogBundle_Entry, len(names))
+ for idx, name := range names {
+ bundle.Entries[idx] = b.beMap[name]
+ }
+
+ return &bundle
+}
+
+func (b *builder) getCreateBundleEntry(template *protocol.ButlerLogBundle_Entry) *protocol.ButlerLogBundle_Entry {
+ if be := b.beMap[template.Desc.Name]; be != nil {
+ return be
+ }
+
+ // Initialize our maps (first time only).
+ if b.beMap == nil {
+ b.beMap = map[string]*protocol.ButlerLogBundle_Entry{}
+ b.beSizes = map[string]int{}
+ }
+
+ templateCopy := *template
+ b.beMap[template.Desc.Name] = &templateCopy
+
+ // Pay the up-front cost of the template.
+ b.beSizes[template.Desc.Name] += protoSize(&templateCopy)
+ return &templateCopy
+}

Powered by Google App Engine
This is Rietveld 408576698