Something went wrong on our end
-
Christian Pointner authoredChristian Pointner authored
logs.go 3.14 KiB
//
// tank
//
// Import and Playlist Daemon for autoradio project
//
//
// Copyright (C) 2017-2019 Christian Pointner <equinox@helsinki.at>
//
// This file is part of tank.
//
// tank is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// tank is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with tank. If not, see <http://www.gnu.org/licenses/>.
//
package store
import (
"bytes"
"compress/gzip"
"encoding/json"
"io"
"time"
)
func (l *Log) Append(stream, line string) {
l.m.Lock()
defer l.m.Unlock()
l.lines = append(l.lines, LogLine{stream, time.Now(), line})
}
func (l *Log) MarshalJSON() ([]byte, error) {
l.m.RLock()
defer l.m.RUnlock()
return json.Marshal(l.lines)
}
func (l *Log) encode() ([]byte, error) {
l.m.RLock()
defer l.m.RUnlock()
var buf bytes.Buffer
comp := gzip.NewWriter(&buf)
enc := json.NewEncoder(comp)
if err := enc.Encode(l.lines); err != nil {
return nil, err
}
if err := comp.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (l *Log) decode(data []byte) error {
l.m.RLock()
defer l.m.RUnlock()
l.lines = nil
buf := bytes.NewBuffer(data)
decomp, err := gzip.NewReader(buf)
if err != nil {
return err
}
dec := json.NewDecoder(decomp)
return dec.Decode(&l.lines)
}
func (l *Log) NewReader(stream string) *LogReader {
return &LogReader{l, -1, stream}
}
// LogReader is not a perfect io.Reader:
// - lines longer than len(p) will be truncated !!!
// - it will only return one line on each invocation even if len(p) would allow us to
// return more than one line
type LogReader struct {
log *Log
pos int
stream string
}
func (r *LogReader) Read(p []byte) (n int, err error) {
r.log.m.RLock()
defer r.log.m.RUnlock()
for {
r.pos++
if r.pos >= len(r.log.lines) {
return 0, io.EOF
}
if r.stream == "" || r.log.lines[r.pos].Stream == r.stream {
return copy(p, []byte(r.log.lines[r.pos].Line)), nil
}
}
}
func (st *Store) AddImportLog(show string, id uint64, importStep string, log *Log) (err error) {
encodedLog, err := log.encode()
if err != nil {
return err
}
return st.db.Create(&ImportLog{File: File{ID: id, ShowName: show}, ImportStep: importStep, Encoded: encodedLog}).Error
}
func (st *Store) GetImportLogs(show string, id uint64) (logs ImportLogs, err error) {
cnt := 0
if err = st.db.Model(&File{ID: id}).Where("show_name = ?", show).Count(&cnt).Error; err != nil {
return
}
if cnt == 0 {
return nil, ErrNotFound
}
var results []ImportLog
if err = st.db.Where("file_id = ?", id).Find(&results).Error; err != nil {
return
}
logs = make(map[string]*Log)
for _, result := range results {
l := &Log{}
if err = l.decode(result.Encoded); err != nil {
return
}
logs[result.ImportStep] = l
}
return
}