overdue
This commit is contained in:
214
.rclone_repo/fs/bwtimetable.go
Executable file
214
.rclone_repo/fs/bwtimetable.go
Executable file
@@ -0,0 +1,214 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// BwTimeSlot represents a bandwidth configuration at a point in time.
|
||||
type BwTimeSlot struct {
|
||||
DayOfTheWeek int
|
||||
HHMM int
|
||||
Bandwidth SizeSuffix
|
||||
}
|
||||
|
||||
// BwTimetable contains all configured time slots.
|
||||
type BwTimetable []BwTimeSlot
|
||||
|
||||
// String returns a printable representation of BwTimetable.
|
||||
func (x BwTimetable) String() string {
|
||||
ret := []string{}
|
||||
for _, ts := range x {
|
||||
ret = append(ret, fmt.Sprintf("%s-%04.4d,%s", time.Weekday(ts.DayOfTheWeek), ts.HHMM, ts.Bandwidth.String()))
|
||||
}
|
||||
return strings.Join(ret, " ")
|
||||
}
|
||||
|
||||
// Basic hour format checking
|
||||
func validateHour(HHMM string) error {
|
||||
if len(HHMM) != 5 {
|
||||
return errors.Errorf("invalid time specification (hh:mm): %q", HHMM)
|
||||
}
|
||||
hh, err := strconv.Atoi(HHMM[0:2])
|
||||
if err != nil {
|
||||
return errors.Errorf("invalid hour in time specification %q: %v", HHMM, err)
|
||||
}
|
||||
if hh < 0 || hh > 23 {
|
||||
return errors.Errorf("invalid hour (must be between 00 and 23): %q", hh)
|
||||
}
|
||||
mm, err := strconv.Atoi(HHMM[3:])
|
||||
if err != nil {
|
||||
return errors.Errorf("invalid minute in time specification: %q: %v", HHMM, err)
|
||||
}
|
||||
if mm < 0 || mm > 59 {
|
||||
return errors.Errorf("invalid minute (must be between 00 and 59): %q", hh)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Basic weekday format checking
|
||||
func parseWeekday(dayOfWeek string) (int, error) {
|
||||
dayOfWeek = strings.ToLower(dayOfWeek)
|
||||
if dayOfWeek == "sun" || dayOfWeek == "sunday" {
|
||||
return 0, nil
|
||||
}
|
||||
if dayOfWeek == "mon" || dayOfWeek == "monday" {
|
||||
return 1, nil
|
||||
}
|
||||
if dayOfWeek == "tue" || dayOfWeek == "tuesday" {
|
||||
return 2, nil
|
||||
}
|
||||
if dayOfWeek == "wed" || dayOfWeek == "wednesday" {
|
||||
return 3, nil
|
||||
}
|
||||
if dayOfWeek == "thu" || dayOfWeek == "thursday" {
|
||||
return 4, nil
|
||||
}
|
||||
if dayOfWeek == "fri" || dayOfWeek == "friday" {
|
||||
return 5, nil
|
||||
}
|
||||
if dayOfWeek == "sat" || dayOfWeek == "saturday" {
|
||||
return 6, nil
|
||||
}
|
||||
return 0, errors.Errorf("invalid weekday: %q", dayOfWeek)
|
||||
}
|
||||
|
||||
// Set the bandwidth timetable.
|
||||
func (x *BwTimetable) Set(s string) error {
|
||||
// The timetable is formatted as:
|
||||
// "dayOfWeek-hh:mm,bandwidth dayOfWeek-hh:mm,banwidth..." ex: "Mon-10:00,10G Mon-11:30,1G Tue-18:00,off"
|
||||
// If only a single bandwidth identifier is provided, we assume constant bandwidth.
|
||||
|
||||
if len(s) == 0 {
|
||||
return errors.New("empty string")
|
||||
}
|
||||
// Single value without time specification.
|
||||
if !strings.Contains(s, " ") && !strings.Contains(s, ",") {
|
||||
ts := BwTimeSlot{}
|
||||
if err := ts.Bandwidth.Set(s); err != nil {
|
||||
return err
|
||||
}
|
||||
ts.DayOfTheWeek = 0
|
||||
ts.HHMM = 0
|
||||
*x = BwTimetable{ts}
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, tok := range strings.Split(s, " ") {
|
||||
tv := strings.Split(tok, ",")
|
||||
|
||||
// Format must be dayOfWeek-HH:MM,BW
|
||||
if len(tv) != 2 {
|
||||
return errors.Errorf("invalid time/bandwidth specification: %q", tok)
|
||||
}
|
||||
|
||||
weekday := 0
|
||||
HHMM := ""
|
||||
if !strings.Contains(tv[0], "-") {
|
||||
HHMM = tv[0]
|
||||
if err := validateHour(HHMM); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < 7; i++ {
|
||||
hh, _ := strconv.Atoi(HHMM[0:2])
|
||||
mm, _ := strconv.Atoi(HHMM[3:])
|
||||
ts := BwTimeSlot{
|
||||
DayOfTheWeek: i,
|
||||
HHMM: (hh * 100) + mm,
|
||||
}
|
||||
if err := ts.Bandwidth.Set(tv[1]); err != nil {
|
||||
return err
|
||||
}
|
||||
*x = append(*x, ts)
|
||||
}
|
||||
} else {
|
||||
timespec := strings.Split(tv[0], "-")
|
||||
if len(timespec) != 2 {
|
||||
return errors.Errorf("invalid time specification: %q", tv[0])
|
||||
}
|
||||
var err error
|
||||
weekday, err = parseWeekday(timespec[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
HHMM = timespec[1]
|
||||
if err := validateHour(HHMM); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hh, _ := strconv.Atoi(HHMM[0:2])
|
||||
mm, _ := strconv.Atoi(HHMM[3:])
|
||||
ts := BwTimeSlot{
|
||||
DayOfTheWeek: weekday,
|
||||
HHMM: (hh * 100) + mm,
|
||||
}
|
||||
// Bandwidth limit for this time slot.
|
||||
if err := ts.Bandwidth.Set(tv[1]); err != nil {
|
||||
return err
|
||||
}
|
||||
*x = append(*x, ts)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Difference in minutes between lateDayOfWeekHHMM and earlyDayOfWeekHHMM
|
||||
func timeDiff(lateDayOfWeekHHMM int, earlyDayOfWeekHHMM int) int {
|
||||
|
||||
lateTimeMinutes := (lateDayOfWeekHHMM / 10000) * 24 * 60
|
||||
lateTimeMinutes += ((lateDayOfWeekHHMM / 100) % 100) * 60
|
||||
lateTimeMinutes += lateDayOfWeekHHMM % 100
|
||||
|
||||
earlyTimeMinutes := (earlyDayOfWeekHHMM / 10000) * 24 * 60
|
||||
earlyTimeMinutes += ((earlyDayOfWeekHHMM / 100) % 100) * 60
|
||||
earlyTimeMinutes += earlyDayOfWeekHHMM % 100
|
||||
|
||||
return lateTimeMinutes - earlyTimeMinutes
|
||||
}
|
||||
|
||||
// LimitAt returns a BwTimeSlot for the time requested.
|
||||
func (x BwTimetable) LimitAt(tt time.Time) BwTimeSlot {
|
||||
// If the timetable is empty, we return an unlimited BwTimeSlot starting at Sunday midnight.
|
||||
if len(x) == 0 {
|
||||
return BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: -1}
|
||||
}
|
||||
|
||||
dayOfWeekHHMM := int(tt.Weekday())*10000 + tt.Hour()*100 + tt.Minute()
|
||||
|
||||
// By default, we return the last element in the timetable. This
|
||||
// satisfies two conditions: 1) If there's only one element it
|
||||
// will always be selected, and 2) The last element of the table
|
||||
// will "wrap around" until overridden by an earlier time slot.
|
||||
// there's only one time slot in the timetable.
|
||||
ret := x[len(x)-1]
|
||||
mindif := 0
|
||||
first := true
|
||||
|
||||
// Look for most recent time slot.
|
||||
for _, ts := range x {
|
||||
// Ignore the past
|
||||
if dayOfWeekHHMM < (ts.DayOfTheWeek*10000)+ts.HHMM {
|
||||
continue
|
||||
}
|
||||
dif := timeDiff(dayOfWeekHHMM, (ts.DayOfTheWeek*10000)+ts.HHMM)
|
||||
if first {
|
||||
mindif = dif
|
||||
first = false
|
||||
}
|
||||
if dif <= mindif {
|
||||
mindif = dif
|
||||
ret = ts
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Type of the value
|
||||
func (x BwTimetable) Type() string {
|
||||
return "BwTimetable"
|
||||
}
|
||||
Reference in New Issue
Block a user