diff --git a/pkg/lmd/a_helper_test.go b/pkg/lmd/a_helper_test.go index c6e002c..3abc318 100644 --- a/pkg/lmd/a_helper_test.go +++ b/pkg/lmd/a_helper_test.go @@ -441,8 +441,8 @@ func httpMockHandler(ctx context.Context, t *testing.T, wrt io.Writer, rdr *http // Credential string // unused Options struct { // Action string // unused - Args []string `json:"args"` Sub string `json:"sub"` + Args []string `json:"args"` } `json:"options"` } err := json.Unmarshal([]byte(rdr.PostFormValue("data")), &data) diff --git a/pkg/lmd/client_con.go b/pkg/lmd/client_con.go index 91d72ef..03c9f36 100644 --- a/pkg/lmd/client_con.go +++ b/pkg/lmd/client_con.go @@ -22,17 +22,17 @@ const ( // ClientConnection handles a single client connection. type ClientConnection struct { noCopy noCopy - lmd *Daemon connection net.Conn + lmd *Daemon + keepAliveTimer *time.Timer + queryStats *QueryStats + curRequest *Request localAddr string remoteAddr string - keepAlive bool - keepAliveTimer *time.Timer listenTimeout int logSlowQueryThreshold int logHugeQueryThreshold int - queryStats *QueryStats - curRequest *Request + keepAlive bool } // NewClientConnection creates a new client connection object. diff --git a/pkg/lmd/column.go b/pkg/lmd/column.go index e75e9a6..4fe4b8a 100644 --- a/pkg/lmd/column.go +++ b/pkg/lmd/column.go @@ -11,9 +11,9 @@ type VirtualColumnResolveFunc func(d *DataRow, col *Column) interface{} // VirtualColumnMapEntry is used to define the virtual key mapping in the VirtualColumnMap. type VirtualColumnMapEntry struct { noCopy noCopy + ResolveFunc VirtualColumnResolveFunc Name string StatusKey PeerStatusKey - ResolveFunc VirtualColumnResolveFunc } // VirtualColumnList maps the virtual columns with the peer status map entry. @@ -191,7 +191,7 @@ const ( ) // OptionalFlagsStrings maps available backend flags to their string value. -var OptionalFlagsStrings = []struct { +var OptionalFlagsStrings = []struct { //nolint:govet // no need to align this struct, use only once flag OptionalFlags name string }{ @@ -277,17 +277,17 @@ func (f *OptionalFlags) Clear() { // Column is the definition of a single column within a DataRow. type Column struct { noCopy noCopy + RefCol *Column // reference to column in other table, ex.: host_alias + Table *Table // // reference to the table holding this column + VirtualMap *VirtualColumnMapEntry // reference to resolver for virtual columns Name string // name and primary key Description string // human description Index int // position in datastore + RefColTableName TableName // shortcut to Column.RefCol.Table.Name + Optional OptionalFlags // flags if this column is used for certain backends only DataType DataType // Type of this column FetchType FetchType // flag wether this columns needs to be updated StorageType StorageType // flag how this column is stored - Optional OptionalFlags // flags if this column is used for certain backends only - RefCol *Column // reference to column in other table, ex.: host_alias - RefColTableName TableName // shortcut to Column.RefCol.Table.Name - Table *Table // reference to the table holding this column - VirtualMap *VirtualColumnMapEntry // reference to resolver for virtual columns } // NewColumn adds a column object. diff --git a/pkg/lmd/config.go b/pkg/lmd/config.go index 44a0fef..6a6f410 100644 --- a/pkg/lmd/config.go +++ b/pkg/lmd/config.go @@ -14,20 +14,20 @@ import ( // Connection defines a single connection configuration. type Connection struct { - Name string - ID string - Source []string - Auth string - RemoteName string `toml:"remote_name"` - Section string - TLSCertificate string - TLSKey string - TLSCA string - TLSSkipVerify int - TLSServerName string - Proxy string - Flags []string - NoConfigTool int `toml:"noconfigtool"` // skip adding config tool to sites query + TLSCertificate string `toml:"tlscertificate"` + Name string `toml:"name"` + Proxy string `toml:"proxy"` + Auth string `toml:"auth"` + RemoteName string `toml:"remote_name"` + Section string `toml:"section"` + ID string `toml:"id"` + TLSKey string `toml:"tlskey"` + TLSServerName string `toml:"tlsservername"` + TLSCA string `toml:"tlsca"` + Source []string `toml:"source"` + Flags []string `toml:"flags"` + TLSSkipVerify int `toml:"tlsskipverify"` + NoConfigTool int `toml:"noconfigtool"` // skip adding config tool to sites query } // Equals checks if two connection objects are identical. @@ -71,39 +71,39 @@ func (c *configFiles) Set(value string) (err error) { // Config defines the available configuration options from supplied config files. type Config struct { - Listen []string `toml:"Listen"` - Nodes []string `toml:"Nodes"` + GroupAuthorization string `toml:"GroupAuthorization"` + LogFile string `toml:"LogFile"` TLSCertificate string `toml:"TLSCertificate"` + TLSMinVersion string `toml:"TLSMinVersion"` + ServiceAuthorization string `toml:"ServiceAuthorization"` TLSKey string `toml:"TLSKey"` - TLSClientPems []string `toml:"TLSClientPems"` - UpdateInterval int64 `toml:"Updateinterval"` - FullUpdateInterval int64 `toml:"FullUpdateInterval"` - Connections []Connection `toml:"Connections"` - LogFile string `toml:"LogFile"` LogLevel string `toml:"LogLevel"` - LogSlowQueryThreshold int `toml:"LogSlowQueryThreshold"` + ListenPrometheus string `toml:"ListenPrometheus"` + Connections []Connection `toml:"Connections"` + Nodes []string `toml:"Nodes"` + Listen []string `toml:"Listen"` + TLSClientPems []string `toml:"TLSClientPems"` + StaleBackendTimeout int `toml:"StaleBackendTimeout"` LogHugeQueryThreshold int `toml:"LogHugeQueryThreshold"` - LogQueryStats bool `toml:"LogQueryStats"` - ConnectTimeout int `toml:"ConnectTimeout"` NetTimeout int `toml:"NetTimeout"` ListenTimeout int `toml:"ListenTimeout"` - SaveTempRequests bool `toml:"SaveTempRequests"` - ListenPrometheus string `toml:"ListenPrometheus"` - SkipSSLCheck int `toml:"SkipSSLCheck"` + UpdateInterval int64 `toml:"Updateinterval"` + MaxQueryFilter int `toml:"MaxQueryFilter"` + ConnectTimeout int `toml:"ConnectTimeout"` IdleTimeout int64 `toml:"IdleTimeout"` IdleInterval int64 `toml:"IdleInterval"` - StaleBackendTimeout int `toml:"StaleBackendTimeout"` - BackendKeepAlive bool `toml:"BackendKeepAlive"` - ServiceAuthorization string `toml:"ServiceAuthorization"` - GroupAuthorization string `toml:"GroupAuthorization"` - SyncIsExecuting bool `toml:"SyncIsExecuting"` + FullUpdateInterval int64 `toml:"FullUpdateInterval"` + MaxParallelPeerConnections int `toml:"MaxParallelPeerConnections"` + SkipSSLCheck int `toml:"SkipSSLCheck"` + LogSlowQueryThreshold int `toml:"LogSlowQueryThreshold"` + UpdateOffset int64 `toml:"UpdateOffset"` CompressionMinimumSize int `toml:"CompressionMinimumSize"` CompressionLevel int `toml:"CompressionLevel"` MaxClockDelta float64 `toml:"MaxClockDelta"` - UpdateOffset int64 `toml:"UpdateOffset"` - TLSMinVersion string `toml:"TLSMinVersion"` - MaxParallelPeerConnections int `toml:"MaxParallelPeerConnections"` - MaxQueryFilter int `toml:"MaxQueryFilter"` + SyncIsExecuting bool `toml:"SyncIsExecuting"` + SaveTempRequests bool `toml:"SaveTempRequests"` + BackendKeepAlive bool `toml:"BackendKeepAlive"` + LogQueryStats bool `toml:"LogQueryStats"` } // NewConfig reads all config files. diff --git a/pkg/lmd/datarow.go b/pkg/lmd/datarow.go index 06c4dfd..63e749f 100644 --- a/pkg/lmd/datarow.go +++ b/pkg/lmd/datarow.go @@ -15,19 +15,19 @@ const ListSepChar1 = "\x00" // DataRow represents a single entry in a DataTable. type DataRow struct { - noCopy noCopy // we don't want to make copies, use references + noCopy noCopy DataStore *DataStore // reference to the datastore itself Refs map[TableName]*DataRow // contains references to other objects, ex.: hosts from the services table - LastUpdate float64 // timestamp when this row has been updated + dataInt64List [][]int64 // stores lists of integers dataString []string // stores string data dataInt []int // stores integers dataInt64 []int64 // stores large integers dataFloat []float64 // stores floats dataStringList [][]string // stores stringlists - dataInt64List [][]int64 // stores lists of integers dataServiceMemberList [][]ServiceMember // stores list of servicemembers dataStringLarge []StringContainer // stores large strings - dataInterfaceList [][]interface{} + dataInterfaceList [][]interface{} // stores anything else + LastUpdate float64 // timestamp of last update } // NewDataRow creates a new DataRow. @@ -1660,8 +1660,7 @@ func (d *DataRow) checkAuth(authUser string) (canView bool) { } func (d *DataRow) CountStats(stats, result []*Filter) { - for idx, stat := range stats { - resultPos := idx + for resultPos, stat := range stats { if stat.StatsPos > 0 { resultPos = stat.StatsPos } diff --git a/pkg/lmd/datastore.go b/pkg/lmd/datastore.go index 9251e3e..748a9f9 100644 --- a/pkg/lmd/datastore.go +++ b/pkg/lmd/datastore.go @@ -9,20 +9,20 @@ import ( // DataStore contains the actual data rows with a reference to the table and peer. type DataStore struct { noCopy noCopy - DynamicColumnCache ColumnList // contains list of columns used to run periodic update - DynamicColumnNamesCache []string // contains list of keys used to run periodic update - Peer *Peer // reference to our peer - PeerName string // cached peer name - PeerKey string // cached peer key - PeerLockMode PeerLockMode // flag wether datarow have to set PeerLock when accessing status - DataSet *DataStoreSet // reference to parent DataSet - Data []*DataRow // the actual data rows Index map[string]*DataRow // access data rows from primary key, ex.: hostname or comment id Index2 map[string]map[string]*DataRow // access data rows from 2 primary keys, ex.: host and service + Peer *Peer // reference to our peer + LowerCaseColumns map[int]int // list of string column indexes with their coresponding lower case index + dupStringList map[[32]byte][]string // lookup pointer to other stringlists during initialization Table *Table // reference to table definition + DataSet *DataStoreSet // reference to parent DataSet + PeerKey string // cached peer key + PeerName string // cached peer name + DynamicColumnCache ColumnList // contains list of keys used to run periodic update + Data []*DataRow // the actual data rows Columns ColumnList // reference to the used columns - dupStringList map[[32]byte][]string // lookup pointer to other stringlists during initialization - LowerCaseColumns map[int]int // list of string column indexes with their coresponding lower case index + DynamicColumnNamesCache []string // contains list of keys used to run periodic update + PeerLockMode PeerLockMode // flag wether datarow have to set PeerLock when accessing status } // NewDataStore creates a new datastore with columns based on given flags. diff --git a/pkg/lmd/datastoreset.go b/pkg/lmd/datastoreset.go index 904f960..54a230b 100644 --- a/pkg/lmd/datastoreset.go +++ b/pkg/lmd/datastoreset.go @@ -117,7 +117,6 @@ func (ds *DataStoreSet) CreateObjectByType(ctx context.Context, table *Table) (s // SetReferences creates reference entries for all tables. func (ds *DataStoreSet) SetReferences() (err error) { for _, t := range ds.tables { - t := t err = t.SetReferences() if err != nil { logWith(ds).Debugf("setting references on table %s failed: %s", t.Table.Name.String(), err.Error()) diff --git a/pkg/lmd/filter.go b/pkg/lmd/filter.go index 4f80393..cb0bcde 100644 --- a/pkg/lmd/filter.go +++ b/pkg/lmd/filter.go @@ -47,33 +47,27 @@ func (op *StatsType) String() string { } // Filter defines a single filter object. +// filter can either be a single filter +// or a group of filters (GroupOperator). type Filter struct { - noCopy noCopy - // filter can either be a single filter - Column *Column - Operator Operator - StrValue string - FloatValue float64 - IntValue int - Regexp *regexp.Regexp - CustomTag string - IsEmpty bool - Negate bool - - // or a group of filters - Filter []*Filter - GroupOperator GroupOperator - - // stats query - Stats float64 - StatsCount int - StatsType StatsType - StatsPos int // position in stats result array - - // copy of Column.Optional - ColumnOptional OptionalFlags - // copy of Column.Index if Column is of type LocalStore - ColumnIndex int + noCopy noCopy + Regexp *regexp.Regexp + Column *Column // filter can either be a single filter + StrValue string + CustomTag string + Filter []*Filter // or a group of filters + Stats float64 // stats query + IntValue int + FloatValue float64 + StatsCount int + StatsPos int // position in stats result array + ColumnIndex int // copy of Column.Index if Column is of type LocalStore + ColumnOptional OptionalFlags // copy of Column.Optional + IsEmpty bool + Negate bool + GroupOperator GroupOperator + Operator Operator + StatsType StatsType } // Operator defines a filter operator. diff --git a/pkg/lmd/listener.go b/pkg/lmd/listener.go index 26d7ee1..7784372 100644 --- a/pkg/lmd/listener.go +++ b/pkg/lmd/listener.go @@ -32,15 +32,15 @@ const ( // Listener is the object which handles incoming connections. type Listener struct { noCopy noCopy + Connection net.Listener Lock *deadlock.RWMutex // must be used for when changing config lmd *Daemon - connectionString string - Connection net.Listener waitGroupDone *sync.WaitGroup waitGroupInit *sync.WaitGroup - openConnections int64 queryStats *QueryStats cleanup func() + connectionString string + openConnections int64 } // NewListener creates a new Listener object. diff --git a/pkg/lmd/main.go b/pkg/lmd/main.go index 0ebf0dc..b7c96b8 100644 --- a/pkg/lmd/main.go +++ b/pkg/lmd/main.go @@ -119,37 +119,37 @@ func (c ConnectionType) String() string { var dedup = stringdedup.New(xxhash.Checksum32) type Daemon struct { + waitGroupListener *sync.WaitGroup + Listeners map[string]*Listener // Listeners stores if we started a listener Config *Config // reference to global config object - PeerMap map[string]*Peer // PeerMap contains a map of available remote peers. - PeerMapOrder []string // PeerMapOrder contains the order of all remote peers as defined in the supplied config files. PeerMapLock *deadlock.RWMutex // PeerMapLock is the lock for the PeerMap map - Listeners map[string]*Listener // Listeners stores if we started a listener - ListenersLock *deadlock.RWMutex // ListenersLock is the lock for the Listeners map - nodeAccessor *Nodes // nodeAccessor manages cluster nodes and starts/stops peers. - waitGroupInit *sync.WaitGroup - waitGroupListener *sync.WaitGroup waitGroupPeers *sync.WaitGroup + ListenersLock *deadlock.RWMutex // ListenersLock is the lock for the Listeners map + nodeAccessor *Nodes // nodeAccessor manages cluster nodes and starts/stops peers. shutdownChannel chan bool + cpuProfileHandler *os.File + PeerMap map[string]*Peer // PeerMap contains a map of available remote peers. + waitGroupInit *sync.WaitGroup + initChannel chan bool + mainSignalChannel chan os.Signal + PeerMapOrder []string flags struct { - flagVerbose bool - flagVeryVerbose bool - flagTraceVerbose bool - flagConfigFile configFiles - flagVersion bool flagLogFile string flagPidfile string flagProfile string - flagDeadlock int flagCPUProfile string flagMemProfile string - flagCfgOption arrayFlags flagExport string flagImport string + flagConfigFile configFiles + flagCfgOption arrayFlags + flagDeadlock int + flagVerbose bool + flagVeryVerbose bool + flagTraceVerbose bool + flagVersion bool } - mainSignalChannel chan os.Signal - initChannel chan bool lastMainRestart float64 - cpuProfileHandler *os.File defaultReqestParseOption ParseOptions } @@ -445,7 +445,7 @@ func (lmd *Daemon) initializePeers(ctx context.Context) { // Get rid of obsolete peers (removed from config) lmd.PeerMapLock.Lock() - for peerKey := range lmd.PeerMap { + for peerKey, peer := range lmd.PeerMap { found := false // id exists for i := range lmd.Config.Connections { if lmd.Config.Connections[i].ID == peerKey { @@ -453,9 +453,8 @@ func (lmd *Daemon) initializePeers(ctx context.Context) { } } if !found { - p := lmd.PeerMap[peerKey] - p.Stop() - p.ClearData(true) + peer.Stop() + peer.ClearData(true) lmd.PeerMapRemove(peerKey) } } @@ -652,7 +651,7 @@ func applyArgFlags(opts arrayFlags, localConfig *Config) { continue } found := false - for i := 0; i < val.NumField(); i++ { + for i := range val.NumField() { cfgname := typeOfV.Field(i).Name if strings.EqualFold(cfgname, optname) { field := val.Field(i) diff --git a/pkg/lmd/nodes.go b/pkg/lmd/nodes.go index bbf5b83..76a3095 100644 --- a/pkg/lmd/nodes.go +++ b/pkg/lmd/nodes.go @@ -20,28 +20,28 @@ var reNodeAddress = regexp.MustCompile(`^(https?)?(://)?(.*?)(:(\d+))?(/.*)?$`) // Nodes is the cluster management object. type Nodes struct { noCopy noCopy - ID string HTTPClient *http.Client WaitGroupInit *sync.WaitGroup ShutdownChannel chan bool - loopInterval int - heartbeatTimeout int - backends []string + lmd *Daemon + stopChannel chan bool + nodeBackends map[string][]string thisNode *NodeAddress + ID string nodeAddresses NodeAddressList onlineNodes NodeAddressList assignedBackends []string - nodeBackends map[string][]string - stopChannel chan bool - lmd *Daemon + backends []string + heartbeatTimeout int + loopInterval int } // NodeAddress contains the ip of a node (plus url/port, if necessary). type NodeAddress struct { id string ip string - port int url string + port int isMe bool } @@ -327,7 +327,7 @@ func (n *Nodes) redistribute(ctx context.Context) { continue } list := make([]string, 0) - for j := 0; j < number; j++ { + for j := range number { if len(n.backends) > distributedCount+j { if n.backends[distributedCount+j] != "" { list = append(list, n.backends[distributedCount+j]) diff --git a/pkg/lmd/peer.go b/pkg/lmd/peer.go index b0f918e..b6eb993 100644 --- a/pkg/lmd/peer.go +++ b/pkg/lmd/peer.go @@ -65,62 +65,62 @@ const ( // Peer is the object which handles collecting and updating data and connections. type Peer struct { noCopy noCopy - // Attributes - Name string // Name of this peer, aka peer_name - ID string // ID for this peer, aka peer_key - PeerAddr string - Section string - PeerParent string - PeerState PeerStatus + cache struct { + HTTPClient *http.Client // cached http client for http backends + connectionPool chan net.Conn // tcp connection get stored here for reuse + maxParallelConnections chan bool // limit max parallel connections + } + stopChannel chan bool // channel to stop this peer + waitGroup *sync.WaitGroup // wait group used to wait on shutdowns + ConfigTool *string + ThrukExtras *string + lock *deadlock.RWMutex // must be used for Peer.* access + data *DataStoreSet // the cached remote data tables + lmd *Daemon // reference to main lmd instance + Config *Connection // reference to the peer configuration from the config file + SubPeerStatus map[ // cached http client for http backends + // limit max parallel connections + string]interface{} + shutdownChannel chan bool // channel used to wait to finish shutdown + Name string // Name of this peer, aka peer_name + ID string // ID for this peer, aka peer_key + PeerAddr string + ParentID string // ID of parent Peer + PeerParent string + LastError string + Section string + last struct { + Request *Request // reference to last query (used in error reports) + Response []byte // reference to last response + } + Source []string // reference to all connection strings + SubName []string + SubType []string + SubAddr []string + SubKey []string + ProgramStart int64 // unix time when this peer started, aka program_start + LastFullHostUpdate float64 CurPeerAddrNum int + BytesReceived int64 + BytesSend int64 + ThrukVersion float64 LastPid int LastTimeperiodUpdateMinute int + Queries int64 + ResponseTime float64 LastUpdate float64 + LastOnline float64 + ErrorCount int // count times this backend has failed LastFullUpdate float64 - LastFullHostUpdate float64 - LastFullServiceUpdate float64 LastQuery float64 - LastOnline float64 - ResponseTime float64 - ThrukVersion float64 - LastError string - BytesSend int64 - BytesReceived int64 - Queries int64 - Idling bool + LastFullServiceUpdate float64 + Flags uint32 // optional flags, like LMD, Icinga2, etc... Paused bool - SubKey []string - SubName []string - SubAddr []string - SubType []string - SubPeerStatus map[string]interface{} - ConfigTool *string - ThrukExtras *string - ForceFull bool + ErrorLogged bool // flag wether last error has been logged already LastHTTPRequestSuccessful bool - ProgramStart int64 // unix time when this peer started, aka program_start - ParentID string // ID of parent Peer - Flags uint32 // optional flags, like LMD, Icinga2, etc... - Source []string // reference to all connection strings - ErrorCount int // count times this backend has failed - ErrorLogged bool // flag wether last error has been logged already - // internals - lock *deadlock.RWMutex // must be used for Peer.* access - data *DataStoreSet // the cached remote data tables - waitGroup *sync.WaitGroup // wait group used to wait on shutdowns - shutdownChannel chan bool // channel used to wait to finish shutdown - stopChannel chan bool // channel to stop this peer - Config *Connection // reference to the peer configuration from the config file - lmd *Daemon // reference to main lmd instance - last struct { - Request *Request // reference to last query (used in error reports) - Response []byte // reference to last response - } - cache struct { - HTTPClient *http.Client // cached http client for http backends - connectionPool chan net.Conn // tcp connection get stored here for reuse - maxParallelConnections chan bool // limit max parallel connections - } + ForceFull bool + Idling bool + PeerState PeerStatus } // PeerStatus contains the different states a peer can have. @@ -176,24 +176,24 @@ const ( // HTTPResult contains the livestatus result as long with some meta data. type HTTPResult struct { - Rc int `json:"rc"` Version string `json:"version"` Branch string `json:"branch"` + Message string `json:"message"` Output json.RawMessage `json:"output"` Raw []byte `json:"raw"` + Rc int `json:"rc"` Code int `json:"code"` - Message string `json:"message"` } // PeerError is a custom error to distinguish between connection and response errors. type PeerError struct { - msg string - kind PeerErrorType + srcErr error req *Request + msg string res [][]interface{} resBytes []byte code int - srcErr error + kind PeerErrorType } // Error returns the error message as string. @@ -218,8 +218,8 @@ func (e *PeerError) Type() PeerErrorType { return e.kind } // PeerCommandError is a custom error when remote site returns something after sending a command. type PeerCommandError struct { err error - code int peer *Peer + code int } // Error returns the error message as string. @@ -1399,9 +1399,7 @@ func (p *Peer) validateResponseHeader(resBytes []byte, req *Request, code int, e // return anything. // It returns the connection object and any error encountered. func (p *Peer) GetConnection(req *Request) (conn net.Conn, connType ConnectionType, err error) { - numSources := len(p.Source) - - for num := 0; num < numSources; num++ { + for num := range len(p.Source) { var peerAddr string peerAddr, connType = extractConnType(p.statusGetLocked(PeerAddr).(string)) if connType == ConnTypeHTTP { @@ -1642,7 +1640,7 @@ func (p *Peer) checkStatusFlags(ctx context.Context, store *DataStoreSet) (err e } func (p *Peer) checkAvailableTables(ctx context.Context) (err error) { - columnFlags := []struct { + columnFlags := []struct { //nolint:govet // no need to align this struct, use only once Table TableName Column string Flag OptionalFlags @@ -1667,8 +1665,7 @@ func (p *Peer) checkAvailableTables(ctx context.Context) (err error) { availableTables := p.GetSupportedColumns(ctx) - for i := range columnFlags { - optFlag := columnFlags[i] + for _, optFlag := range columnFlags { if _, ok := availableTables[optFlag.Table]; !ok { continue } diff --git a/pkg/lmd/rawresultset.go b/pkg/lmd/rawresultset.go index c62d449..9696b13 100644 --- a/pkg/lmd/rawresultset.go +++ b/pkg/lmd/rawresultset.go @@ -9,11 +9,11 @@ import ( // RawResultSet contains references to the result rows or stats objects. type RawResultSet struct { noCopy noCopy - Total int // total number of results for this set - RowsScanned int // total number of scanned rows for this set DataResult []*DataRow // references to the data rows required for the result StatsResult ResultSetStats // intermediate result of stats query Sort []*SortField // columns required for sorting + Total int // total number of results for this set + RowsScanned int // total number of scanned rows for this set } // PostProcessing does all the post processing required for a request like sorting diff --git a/pkg/lmd/request.go b/pkg/lmd/request.go index fc55126..ee90d96 100644 --- a/pkg/lmd/request.go +++ b/pkg/lmd/request.go @@ -24,35 +24,35 @@ import ( // Request defines a livestatus request object. type Request struct { noCopy noCopy - id string + StatsResult *ResultSetStats lmd *Daemon - Table TableName + BackendsMap map[string]string + BackendErrors map[string]string + Limit *int + id string + AuthUser string Command string - Columns []string // parsed columns field - RequestColumns []*Column // calculated/expanded columns list - Filter []*Filter + WaitTrigger string FilterStr string - NumFilter int + WaitObject string Stats []*Filter StatsGrouped []*Filter // optimized stats groups - StatsResult *ResultSetStats - Limit *int - Offset int + Filter []*Filter Sort []*SortField - ResponseFixed16 bool - OutputFormat OutputFormat + WaitCondition []*Filter + RequestColumns []*Column // calculated/expanded columns list Backends []string - BackendsMap map[string]string - BackendErrors map[string]string + Columns []string // parsed columns field + Offset int + WaitTimeout int // milliseconds + NumFilter int + Table TableName ColumnsHeaders bool SendStatsData bool - WaitTimeout int // milliseconds - WaitTrigger string - WaitCondition []*Filter - WaitObject string + OutputFormat OutputFormat + ResponseFixed16 bool WaitConditionNegate bool KeepAlive bool - AuthUser string } // SortDirection can be either Asc or Desc. @@ -124,12 +124,12 @@ func (o *OutputFormat) String() string { // SortField defines a single sort entry. type SortField struct { noCopy noCopy + Column *Column Name string - Direction SortDirection + Args string Index int + Direction SortDirection Group bool - Args string - Column *Column } // GroupOperator is the operator used to combine multiple filter or stats header. @@ -157,12 +157,12 @@ func (op *GroupOperator) String() string { // ResultMetaData contains meta from the response data. type ResultMetaData struct { + Request *Request // the request itself + Columns []string // list of requested columns Total int64 // total number of result rows RowsScanned int64 // total number of scanned rows for this result - Columns []string // list of requested columns Duration time.Duration // response time in seconds Size int // result size in bytes - Request *Request // the request itself } var ( @@ -690,9 +690,8 @@ func (req *Request) mergeDistributedResponse(collectedDatasets chan ResultSet, c key := "" if hasColumns > 0 { keys := []string{} - for x := 0; x < hasColumns; x++ { - k := interface2stringNoDedup(row[x]) - keys = append(keys, k) + for x := range hasColumns { + keys = append(keys, interface2stringNoDedup(row[x])) } key = strings.Join(keys, ListSepChar1) } diff --git a/pkg/lmd/response.go b/pkg/lmd/response.go index e99f6a1..ff00415 100644 --- a/pkg/lmd/response.go +++ b/pkg/lmd/response.go @@ -27,16 +27,16 @@ const ( // Response contains the livestatus response data as long with some meta data. type Response struct { noCopy noCopy + Error error // error object if the query was not successful Lock *deadlock.RWMutex // must be used for Result and Failed access Request *Request // the initial request + RawResults *RawResultSet // collected results from peers + Failed map[string]string // map of failed backends by key Result ResultSet // final processed result table + SelectedPeers []*Peer // peers used for this response Code int // 200 if the query was successful - Error error // error object if the query was not successful - RawResults *RawResultSet // collected results from peers ResultTotal int RowsScanned int // total number of data rows scanned for this result - Failed map[string]string - SelectedPeers []*Peer } // PeerResponse is the sub result from a peer before merged into the end result. @@ -609,7 +609,7 @@ func (res *Response) WriteDataResponseRowLocked(json *jsoniter.Stream) { // WriteColumnsResponse writes the columns header. func (res *Response) WriteColumnsResponse(json *jsoniter.Stream) { cols := make([]string, len(res.Request.RequestColumns)+len(res.Request.Stats)) - for k := 0; k < len(res.Request.RequestColumns); k++ { + for k := range len(res.Request.RequestColumns) { if k < len(res.Request.Columns) { cols[k] = res.Request.Columns[k] } else { diff --git a/pkg/lmd/resultset.go b/pkg/lmd/resultset.go index c823001..c7e076b 100644 --- a/pkg/lmd/resultset.go +++ b/pkg/lmd/resultset.go @@ -157,7 +157,7 @@ func (res *ResultSetSorted) Swap(i, j int) { // ResultPrepared is a list of result rows prepared to insert faster. type ResultPrepared struct { - ResultRow []interface{} DataRow *DataRow + ResultRow []interface{} FullUpdate bool } diff --git a/pkg/lmd/table.go b/pkg/lmd/table.go index ec9a13f..8a4573a 100644 --- a/pkg/lmd/table.go +++ b/pkg/lmd/table.go @@ -149,18 +149,18 @@ func (t *TableName) String() string { // Table defines available columns and table options. type Table struct { noCopy noCopy - Name TableName - Columns ColumnList + DataSizes map[DataType]int // contains size used for the datastore + Lock *deadlock.RWMutex // must be used for DataSizes access ColumnsIndex map[string]*Column // access columns by name - PassthroughOnly bool // flag wether table will be cached or simply passed through to remote sites - WorksUnlocked bool // flag wether locking the peer.DataLock can be skipped to answer the query + Virtual VirtualStoreResolveFunc PrimaryKey []string RefTables []TableRef // referenced tables - Virtual VirtualStoreResolveFunc - DefaultSort []string // columns used to sort if nothing is specified - PeerLockMode PeerLockMode // should the peer be locked once for the complete result or on each access - Lock *deadlock.RWMutex // must be used for DataSizes access - DataSizes map[DataType]int // contains size used for the datastore + DefaultSort []string // columns used to sort if nothing is specified + Columns ColumnList + PeerLockMode PeerLockMode // should the peer be locked once for the complete result or on each access + Name TableName + WorksUnlocked bool // flag wether locking the peer.DataLock can be skipped to answer the query + PassthroughOnly bool // flag wether table will be cached or simply passed through to remote sites } // GetColumn returns a column for given name or nil if not found. diff --git a/pkg/lmd/write_counter.go b/pkg/lmd/write_counter.go index 9d24b11..c48ebaf 100644 --- a/pkg/lmd/write_counter.go +++ b/pkg/lmd/write_counter.go @@ -3,8 +3,8 @@ package lmd import "io" type WriteCounter struct { - Count int64 Writer io.Writer + Count int64 } func NewWriteCounter(w io.Writer) *WriteCounter {