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

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: Updated from comments. 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..29f6e4f26a0a1ba4d6bcf3129d84d2d3782ec37e
--- /dev/null
+++ b/client/internal/logdog/butler/bundler/builder.go
@@ -0,0 +1,122 @@
+// 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"
+)
+
+// builderStream is builder data that is tracked for each individual stream.
+type builderStream struct {
+ // ButlerLogBundle_Entry is the stream's in-progress bundle entry.
+ protocol.ButlerLogBundle_Entry
+ // size incrementally tracks the size of the stream's entry.
+ size int
+}
+
+// builder incrementally constructs ButlerLogBundle entries.
+type builder struct {
+ // size is the maximum permitted bundle size.
+ size int
+
+ // template is the base bundle template.
+ template protocol.ButlerLogBundle
+ // templateCachedSize is the cached size of the ButlerLogBundle template.
+ templateCachedSize int
+
+ // smap maps the builder state for each individual stream by stream name.
+ streams map[string]*builderStream
+}
+
+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 _, bs := range b.streams {
+ size += sizeOfBundleEntryTag + varintLength(uint64(bs.size)) + bs.size
+ }
+
+ return size
+}
+
+func (b *builder) hasContent() bool {
+ return len(b.streams) > 0
+}
+
+func (b *builder) add(template *protocol.ButlerLogBundle_Entry, le *protocol.LogEntry) {
+ bs := b.getCreateBuilderStream(template)
+
+ bs.Logs = append(bs.Logs, le)
+ psize := protoSize(le)
+
+ // Pay the cost of the additional LogEntry.
+ bs.size += sizeOfLogEntryTag + varintLength(uint64(psize)) + psize
+}
+
+func (b *builder) setStreamTerminal(template *protocol.ButlerLogBundle_Entry, tidx uint64) {
+ bs := b.getCreateBuilderStream(template)
+ if bs.Terminal {
+ if bs.TerminalIndex != tidx {
+ panic(fmt.Errorf("attempt to change terminal index %d => %d", bs.TerminalIndex, tidx))
+ }
+ return
+ }
+
+ bs.Terminal = true
+ bs.TerminalIndex = tidx
+
+ // Pay the cost of the additional terminal fields.
+ bs.size += ((sizeOfTerminalTag + sizeOfBoolTrue) +
+ (sizeOfTerminalIndexTag + varintLength(bs.TerminalIndex)))
+}
+
+func (b *builder) bundle() *protocol.ButlerLogBundle {
+ bundle := b.template
+
+ names := make([]string, 0, len(b.streams))
+ for k := range b.streams {
+ names = append(names, k)
+ }
+ sort.Strings(names)
+
+ bundle.Entries = make([]*protocol.ButlerLogBundle_Entry, len(names))
+ for idx, name := range names {
+ bundle.Entries[idx] = &b.streams[name].ButlerLogBundle_Entry
+ }
+
+ return &bundle
+}
+
+func (b *builder) getCreateBuilderStream(template *protocol.ButlerLogBundle_Entry) *builderStream {
+ if bs := b.streams[template.Desc.Name]; bs != nil {
+ return bs
+ }
+
+ // Initialize our maps (first time only).
+ if b.streams == nil {
+ b.streams = map[string]*builderStream{}
+ }
+
+ bs := builderStream{
+ ButlerLogBundle_Entry: *template,
+ size: protoSize(template),
+ }
+ b.streams[template.Desc.Name] = &bs
+ return &bs
+}
« no previous file with comments | « client/internal/logdog/butler/bundler/binaryParser_test.go ('k') | client/internal/logdog/butler/bundler/builder_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698