2023-01-11 01:31:38 +03:00
|
|
|
/*
|
|
|
|
DESCRIPTION
|
|
|
|
files.go provides the functionality required for saving and loading
|
|
|
|
broadcastManager state. This includes marshalling/unmarshalling overrides.
|
|
|
|
|
|
|
|
AUTHORS
|
|
|
|
Saxon A. Nelson-Milton <saxon@ausocean.org>
|
|
|
|
|
|
|
|
LICENSE
|
|
|
|
Copyright (C) 2022-2023 the Australian Ocean Lab (AusOcean)
|
|
|
|
|
|
|
|
It is free software: you can redistribute it and/or modify them
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
option) any later version.
|
|
|
|
|
|
|
|
It 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 revid in gpl.txt. If not, see http://www.gnu.org/licenses.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"bitbucket.org/ausocean/av/cmd/vidforward/global"
|
|
|
|
)
|
|
|
|
|
|
|
|
// inTest is used to indicate if we are within a test; some functionality is not
|
|
|
|
// employed in this case.
|
|
|
|
var inTest bool
|
|
|
|
|
|
|
|
// The file name for the broadcast manager state save.
|
|
|
|
const fileName = "state.json"
|
|
|
|
|
|
|
|
// BroadcastBasic is a crude version of the Broadcast used to simplify
|
|
|
|
// marshal/unmarshal overriding.
|
|
|
|
type BroadcastBasic struct {
|
|
|
|
MAC
|
2023-03-05 01:09:39 +03:00
|
|
|
URLs []string
|
2023-01-11 01:31:38 +03:00
|
|
|
Status string
|
|
|
|
}
|
|
|
|
|
|
|
|
// ManagerBasic is a crude version of the BroadcastManager struct use to simplify
|
|
|
|
// marshal/unmarshal overriding.
|
|
|
|
type ManagerBasic struct {
|
2023-06-15 00:09:31 +03:00
|
|
|
Broadcasts map[MAC]*Broadcast
|
2023-01-11 01:31:38 +03:00
|
|
|
SlateExitSignals []MAC
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalJSON calls the default marshalling behaviour for the BroadcastBasic
|
|
|
|
// struct using the information from b.
|
|
|
|
func (b Broadcast) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(BroadcastBasic{
|
|
|
|
MAC: b.mac,
|
2023-03-05 01:09:39 +03:00
|
|
|
URLs: b.urls,
|
2023-01-11 01:31:38 +03:00
|
|
|
Status: b.status,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON unmarshals into a value of the BroadcastBasic struct and then
|
|
|
|
// populates a Broadcast value.
|
|
|
|
func (b *Broadcast) UnmarshalJSON(data []byte) error {
|
|
|
|
var bm BroadcastBasic
|
|
|
|
err := json.Unmarshal(data, &bm)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not unmarshal JSON: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
b.mac = bm.MAC
|
2023-03-05 01:09:39 +03:00
|
|
|
b.urls = bm.URLs
|
2023-01-11 01:31:38 +03:00
|
|
|
b.status = bm.Status
|
|
|
|
|
2023-03-05 01:09:39 +03:00
|
|
|
b.rv, err = newRevid(global.GetLogger(), b.urls)
|
2023-01-11 01:31:38 +03:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not populate RV field: %w", err)
|
|
|
|
}
|
|
|
|
|
2023-03-12 01:09:21 +03:00
|
|
|
err = b.rv.Start()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not start revid pipeline: %w", err)
|
|
|
|
}
|
|
|
|
|
2023-01-11 01:31:38 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalJSON calls the default marshaller for a ManagerBasic value using data
|
|
|
|
// from a broadcastManager value.
|
|
|
|
func (m *broadcastManager) MarshalJSON() ([]byte, error) {
|
|
|
|
var signals []MAC
|
|
|
|
for k := range m.slateExitSignals {
|
|
|
|
signals = append(signals, k)
|
|
|
|
}
|
|
|
|
return json.Marshal(ManagerBasic{
|
|
|
|
Broadcasts: m.broadcasts,
|
|
|
|
SlateExitSignals: signals,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON populates a ManagerBasic value from the provided data and then
|
|
|
|
// populates the receiver broadcastManager to a usable state based on this data.
|
|
|
|
func (m *broadcastManager) UnmarshalJSON(data []byte) error {
|
|
|
|
var mb ManagerBasic
|
|
|
|
err := json.Unmarshal(data, &mb)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not unmarshal JSON: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.broadcasts = mb.Broadcasts
|
|
|
|
m.slateExitSignals = make(map[MAC]chan struct{})
|
|
|
|
m.log = global.GetLogger()
|
|
|
|
|
|
|
|
notifier, err := newWatchdogNotifier(m.log, terminationCallback(m))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not create watchdog notifier: %w", err)
|
|
|
|
}
|
|
|
|
m.dogNotifier = notifier
|
|
|
|
|
|
|
|
for _, mac := range mb.SlateExitSignals {
|
|
|
|
sigCh := make(chan struct{})
|
|
|
|
m.slateExitSignals[mac] = sigCh
|
|
|
|
rv := m.getPipeline(mac)
|
|
|
|
if rv == nil {
|
|
|
|
panic("no pipeline for MAC")
|
|
|
|
}
|
|
|
|
if !inTest {
|
|
|
|
err := writeSlateAndCheckErrors(rv, sigCh, m.log)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("couldn't write slate for MAC %v: %w", mac, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// save utilises marshalling functionality to save the broadcastManager state
|
|
|
|
// to a file.
|
|
|
|
func (m *broadcastManager) save() error {
|
|
|
|
f, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not open file: %w", err)
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
bytes, err := json.Marshal(m)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not marshal broadcast manager: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = f.Write(bytes)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not write bytes to file: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// load populates a broadcastManager value based on the previously saved state.
|
|
|
|
func (m *broadcastManager) load() error {
|
|
|
|
bytes, err := os.ReadFile(fileName)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not read state file: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = json.Unmarshal(bytes, &m)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not unmarshal state data: %w", err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|