mirror of
https://github.com/hamburghammer/gsave.git
synced 2024-12-22 18:37:39 +01:00
771ce66ce2
This is to prevent further data races.
129 lines
3.5 KiB
Go
129 lines
3.5 KiB
Go
package db
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// NewInMemoryDB a constructor to build a new inMemoryDB.
|
|
func NewInMemoryDB() *InMemoryDB {
|
|
return &InMemoryDB{storage: make(map[string]Host), m: sync.Mutex{}}
|
|
}
|
|
|
|
// InMemoryDB a in memory DB implementing the db.HostDB interface.
|
|
type InMemoryDB struct {
|
|
storage map[string]Host
|
|
m sync.Mutex
|
|
}
|
|
|
|
// WithCustomStorage allows to put a custom map as DB storage.
|
|
// Returns a new InMemoryDB.
|
|
func (db *InMemoryDB) WithCustomStorage(storage map[string]Host) *InMemoryDB {
|
|
db.m.Lock()
|
|
defer db.m.Unlock()
|
|
|
|
return &InMemoryDB{storage: storage, m: sync.Mutex{}}
|
|
}
|
|
|
|
// GetHosts returns a paginated result of all hosts.
|
|
// It returns an error if no host was found or all entries are beeing skiped.
|
|
func (db *InMemoryDB) GetHosts(pagination Pagination) ([]HostInfo, error) {
|
|
db.m.Lock()
|
|
defer db.m.Unlock()
|
|
|
|
hosts := make([]HostInfo, 0)
|
|
for _, value := range db.storage {
|
|
hosts = append(hosts, value.HostInfo)
|
|
}
|
|
|
|
if len(hosts) == 0 {
|
|
return []HostInfo{}, ErrHostsNotFound
|
|
}
|
|
|
|
records := len(hosts)
|
|
if records < pagination.Skip {
|
|
return []HostInfo{}, ErrAllEntriesSkipped
|
|
} else if records < (pagination.Skip + pagination.Limit) {
|
|
hosts = hosts[pagination.Skip:]
|
|
foundHosts := make([]HostInfo, len(hosts))
|
|
copy(foundHosts, hosts)
|
|
return foundHosts, nil
|
|
}
|
|
|
|
hosts = hosts[pagination.Skip:(pagination.Skip + pagination.Limit)]
|
|
foundHosts := make([]HostInfo, len(hosts))
|
|
copy(foundHosts, hosts)
|
|
return foundHosts, nil
|
|
}
|
|
|
|
// GetHost returns a host with the matching hostname.
|
|
// If no host could be found it will return an error.
|
|
func (db *InMemoryDB) GetHost(hostname string) (HostInfo, error) {
|
|
db.m.Lock()
|
|
defer db.m.Unlock()
|
|
|
|
host, found := db.storage[hostname]
|
|
if !found {
|
|
return HostInfo{}, ErrHostNotFound
|
|
}
|
|
|
|
return host.HostInfo, nil
|
|
}
|
|
|
|
// GetStatsByHostname gets all Stats in a paginated form from a specific host.
|
|
// It returns errors if no host is found or if all entries are beeing skiped.
|
|
func (db *InMemoryDB) GetStatsByHostname(hostname string, pagination Pagination) ([]Stats, error) {
|
|
db.m.Lock()
|
|
defer db.m.Unlock()
|
|
|
|
host, found := db.storage[hostname]
|
|
if !found {
|
|
return []Stats{}, ErrHostNotFound
|
|
}
|
|
|
|
records := len(host.Stats)
|
|
if records < pagination.Skip {
|
|
return []Stats{}, ErrAllEntriesSkipped
|
|
} else if records < (pagination.Skip + pagination.Limit) {
|
|
stats := host.Stats[pagination.Skip:]
|
|
foundStats := make([]Stats, len(stats))
|
|
copy(foundStats, stats)
|
|
return foundStats, nil
|
|
}
|
|
|
|
stats := host.Stats[pagination.Skip:(pagination.Skip + pagination.Limit)]
|
|
foundStats := make([]Stats, len(stats))
|
|
copy(foundStats, stats)
|
|
return foundStats, nil
|
|
}
|
|
|
|
// InsertStats into the DB.
|
|
// To do so it takes the hostname of the Hostname field and creates a new host inside the DB and/or adds the stat to it.
|
|
// The HostInfos are also beeing updated.
|
|
// This implementation won't return an error but its declared to implement the db.HostDB interface.
|
|
func (db *InMemoryDB) InsertStats(hostname string, stats Stats) error {
|
|
db.m.Lock()
|
|
defer db.m.Unlock()
|
|
|
|
host, found := db.storage[hostname]
|
|
if !found {
|
|
hostInfo := HostInfo{Hostname: hostname, DataPoints: 1, LastInsert: time.Now()}
|
|
db.storage[hostname] = Host{HostInfo: hostInfo, Stats: []Stats{stats}}
|
|
return nil
|
|
}
|
|
|
|
host.Stats = db.insertAtBeginning(host.Stats, stats)
|
|
host.HostInfo.DataPoints++
|
|
host.HostInfo.LastInsert = time.Now()
|
|
|
|
db.storage[hostname] = host
|
|
return nil
|
|
}
|
|
|
|
func (db *InMemoryDB) insertAtBeginning(stats []Stats, stat Stats) []Stats {
|
|
stats = append(stats, Stats{})
|
|
copy(stats[1:], stats)
|
|
stats[0] = stat
|
|
|
|
return stats
|
|
}
|