mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 18:20:27 +00:00
This commit makes the LatestMap type a sort of a base class, that should not be used directly. This also adds a generator for LatestMap "concrete" types with a specific data type in the LatestEntry.
177 lines
5.6 KiB
Bash
Executable File
177 lines
5.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Generate concrete implementations of LatestMap.
|
|
#
|
|
# e.g.
|
|
# $ generate_latest_map ./report/out.go string NodeControlData ...
|
|
#
|
|
# Depends on:
|
|
# - gofmt
|
|
|
|
function generate_header {
|
|
local out_file="${1}"
|
|
local cmd="${2}"
|
|
|
|
cat << EOF >"${out_file}"
|
|
// Generated file, do not edit.
|
|
// To regenerate, run ${cmd}
|
|
|
|
package report
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/ugorji/go/codec"
|
|
)
|
|
EOF
|
|
}
|
|
|
|
function generate_latest_map {
|
|
local out_file="$1"
|
|
local data_type="$2"
|
|
local uppercase_data_type="${data_type^}"
|
|
local lowercase_data_type="${data_type,}"
|
|
local wire_entry_type="wire${uppercase_data_type}LatestEntry"
|
|
local decoder_type="${lowercase_data_type}LatestEntryDecoder"
|
|
local iface_decoder_variable="${uppercase_data_type}LatestEntryDecoder"
|
|
local latest_map_type="${uppercase_data_type}LatestMap"
|
|
local empty_latest_map_variable="Empty${latest_map_type}"
|
|
local make_function="Make${latest_map_type}"
|
|
|
|
local json_timestamp='`json:"timestamp"`'
|
|
local json_value='`json:"value"`'
|
|
|
|
cat << EOF >>"${out_file}"
|
|
type ${wire_entry_type} struct {
|
|
Timestamp time.Time ${json_timestamp}
|
|
Value ${data_type} ${json_value}
|
|
}
|
|
|
|
type ${decoder_type} struct {}
|
|
|
|
func (d *${decoder_type}) Decode(decoder *codec.Decoder, entry *LatestEntry) {
|
|
wire := ${wire_entry_type}{}
|
|
decoder.Decode(&wire)
|
|
entry.Timestamp = wire.Timestamp
|
|
entry.Value = wire.Value
|
|
}
|
|
|
|
// ${iface_decoder_variable} is an implementation of LatestEntryDecoder
|
|
// that decodes the LatestEntry instances having a ${data_type} value.
|
|
var ${iface_decoder_variable} LatestEntryDecoder = &${decoder_type}{}
|
|
|
|
// ${latest_map_type} holds latest ${data_type} instances.
|
|
type ${latest_map_type} LatestMap
|
|
|
|
// ${empty_latest_map_variable} is an empty ${latest_map_type}. Start with this.
|
|
var ${empty_latest_map_variable} = (${latest_map_type})(MakeLatestMapWithDecoder(${iface_decoder_variable}))
|
|
|
|
// ${make_function} makes an empty ${latest_map_type}.
|
|
func ${make_function}() ${latest_map_type} {
|
|
return ${empty_latest_map_variable}
|
|
}
|
|
|
|
// Copy is a noop, as ${latest_map_type}s are immutable.
|
|
func (m ${latest_map_type}) Copy() ${latest_map_type} {
|
|
return (${latest_map_type})((LatestMap)(m).Copy())
|
|
}
|
|
|
|
// Size returns the number of elements.
|
|
func (m ${latest_map_type}) Size() int {
|
|
return (LatestMap)(m).Size()
|
|
}
|
|
|
|
// Merge produces a fresh ${latest_map_type} containing the keys from both inputs.
|
|
// When both inputs contain the same key, the newer value is used.
|
|
func (m ${latest_map_type}) Merge(other ${latest_map_type}) ${latest_map_type} {
|
|
return (${latest_map_type})((LatestMap)(m).Merge((LatestMap)(other)))
|
|
}
|
|
|
|
// Lookup the value for the given key.
|
|
func (m ${latest_map_type}) Lookup(key string) (${data_type}, bool) {
|
|
v, ok := (LatestMap)(m).Lookup(key)
|
|
if !ok {
|
|
var zero ${data_type}
|
|
return zero, false
|
|
}
|
|
return v.(${data_type}), true
|
|
}
|
|
|
|
// LookupEntry returns the raw entry for the given key.
|
|
func (m ${latest_map_type}) LookupEntry(key string) (${data_type}, time.Time, bool) {
|
|
v, timestamp, ok := (LatestMap)(m).LookupEntry(key)
|
|
if !ok {
|
|
var zero ${data_type}
|
|
return zero, timestamp, false
|
|
}
|
|
return v.(${data_type}), timestamp, true
|
|
}
|
|
|
|
// Set the value for the given key.
|
|
func (m ${latest_map_type}) Set(key string, timestamp time.Time, value ${data_type}) ${latest_map_type} {
|
|
return (${latest_map_type})((LatestMap)(m).Set(key, timestamp, value))
|
|
}
|
|
|
|
// Delete the value for the given key.
|
|
func (m ${latest_map_type}) Delete(key string) ${latest_map_type} {
|
|
return (${latest_map_type})((LatestMap)(m).Delete(key))
|
|
}
|
|
|
|
// ForEach executes fn on each key value pair in the map.
|
|
func (m ${latest_map_type}) ForEach(fn func(k string, timestamp time.Time, v ${data_type})) {
|
|
(LatestMap)(m).ForEach(func(key string, ts time.Time, value interface{}) {
|
|
fn(key, ts, value.(${data_type}))
|
|
})
|
|
}
|
|
|
|
// String returns the ${latest_map_type}'s string representation.
|
|
func (m ${latest_map_type}) String() string {
|
|
return (LatestMap)(m).String()
|
|
}
|
|
|
|
// DeepEqual tests equality with other ${latest_map_type}.
|
|
func (m ${latest_map_type}) DeepEqual(n ${latest_map_type}) bool {
|
|
return (LatestMap)(m).DeepEqual((LatestMap)(n))
|
|
}
|
|
|
|
// CodecEncodeSelf implements codec.Selfer.
|
|
func (m *${latest_map_type}) CodecEncodeSelf(encoder *codec.Encoder) {
|
|
(*LatestMap)(m).CodecEncodeSelf(encoder)
|
|
}
|
|
|
|
// CodecDecodeSelf implements codec.Selfer.
|
|
func (m *${latest_map_type}) CodecDecodeSelf(decoder *codec.Decoder) {
|
|
bm := (*LatestMap)(m)
|
|
bm.decoder = ${iface_decoder_variable}
|
|
bm.CodecDecodeSelf(decoder)
|
|
}
|
|
|
|
// MarshalJSON shouldn't be used, use CodecEncodeSelf instead.
|
|
func (${latest_map_type}) MarshalJSON() ([]byte, error) {
|
|
panic("MarshalJSON shouldn't be used, use CodecEncodeSelf instead")
|
|
}
|
|
|
|
// UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead.
|
|
func (*${latest_map_type}) UnmarshalJSON(b []byte) error {
|
|
panic("UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead")
|
|
}
|
|
EOF
|
|
}
|
|
|
|
if [ -z "${1}" ]; then
|
|
echo "No output file given"
|
|
exit 1
|
|
fi
|
|
|
|
out="${1}"
|
|
outtmp="${out}.tmp"
|
|
|
|
generate_header "${outtmp}" "${0} ${*}"
|
|
shift
|
|
for t in ${*}; do
|
|
generate_latest_map "${outtmp}" "${t}"
|
|
done
|
|
|
|
gofmt -s -w "${outtmp}"
|
|
mv "${outtmp}" "${out}"
|