Skip to content
Snippets Groups Projects
Commit 74ff3539 authored by Jono Wenger's avatar Jono Wenger
Browse files

Make sentRoundTracker that tracks rounds that file parts were recently sent on

parent 3c51e6c0
No related branches found
No related tags found
2 merge requests!117Release,!105XX-3617 / faster file transfer
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
package fileTransfer
import (
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/netTime"
"sync"
"time"
)
// sentRoundTracker keeps track of rounds that file parts were sent on and when
// those rounds occurred. Rounds past the given age can be deleted manually.
type sentRoundTracker struct {
rounds map[id.Round]time.Time
age time.Duration
mux sync.RWMutex
}
// newSentRoundTracker returns an empty sentRoundTracker.
func newSentRoundTracker(interval time.Duration) *sentRoundTracker {
return &sentRoundTracker{
rounds: make(map[id.Round]time.Time),
age: interval,
}
}
// removeOldRounds removes any rounds that are older than the max round age.
func (srt *sentRoundTracker) removeOldRounds() {
srt.mux.Lock()
defer srt.mux.Unlock()
deleteBefore := netTime.Now().Add(-srt.age)
for rid, timeStamp := range srt.rounds {
if timeStamp.Before(deleteBefore) {
delete(srt.rounds, rid)
}
}
}
// Has indicates if the round ID is in the tracker.
func (srt *sentRoundTracker) Has(rid id.Round) bool {
srt.mux.RLock()
defer srt.mux.RUnlock()
_, exists := srt.rounds[rid]
return exists
}
// Insert adds the round to the tracker with the current time.
func (srt *sentRoundTracker) Insert(rid id.Round) {
timeNow := netTime.Now()
srt.mux.Lock()
defer srt.mux.Unlock()
jww.DEBUG.Printf("[FT]\tInsert round %d into tracker at time %s\n", rid, timeNow.Format("03:04:05.9999999 PM"))
srt.rounds[rid] = timeNow
}
// Remove deletes a round ID from the tracker.
func (srt *sentRoundTracker) Remove(rid id.Round) {
srt.mux.Lock()
defer srt.mux.Unlock()
delete(srt.rounds, rid)
}
// Len returns the number of round IDs in the tracker.
func (srt *sentRoundTracker) Len() int {
srt.mux.RLock()
defer srt.mux.RUnlock()
return len(srt.rounds)
}
// GetRoundIDs returns a list of all round IDs in the tracker.
func (srt *sentRoundTracker) GetRoundIDs() []id.Round {
srt.mux.RLock()
defer srt.mux.RUnlock()
roundIDs := make([]id.Round, 0, len(srt.rounds))
for rid := range srt.rounds {
roundIDs = append(roundIDs, rid)
}
return roundIDs
}
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
package fileTransfer
import (
"gitlab.com/xx_network/primitives/id"
"reflect"
"testing"
"time"
)
// Tests that newSentRoundTracker returns the expected new sentRoundTracker.
func Test_newSentRoundTracker(t *testing.T) {
interval := 10 * time.Millisecond
expected := &sentRoundTracker{
rounds: make(map[id.Round]time.Time),
age: interval,
}
srt := newSentRoundTracker(interval)
if !reflect.DeepEqual(expected, srt) {
t.Errorf("New sentRoundTracker does not match expected."+
"\nexpected: %+v\nreceived: %+v", expected, srt)
}
}
// Tests that sentRoundTracker.removeOldRounds removes only old rounds and not
// newer rounds.
func Test_sentRoundTracker_removeOldRounds(t *testing.T) {
srt := newSentRoundTracker(50 * time.Millisecond)
// Add odd round to tracker
for rid := id.Round(0); rid < 100; rid++ {
if rid%2 != 0 {
srt.Insert(rid)
}
}
time.Sleep(50 * time.Millisecond)
// Add even round to tracker
for rid := id.Round(0); rid < 100; rid++ {
if rid%2 == 0 {
srt.Insert(rid)
}
}
// Remove all old rounds (should be all odd rounds)
srt.removeOldRounds()
// Check that only even rounds exist
for rid := id.Round(0); rid < 100; rid++ {
if srt.Has(rid) {
if rid%2 != 0 {
t.Errorf("Round %d exists.", rid)
}
} else if rid%2 == 0 {
t.Errorf("Round %d does not exist.", rid)
}
}
}
// Tests that sentRoundTracker.Has returns true for all the even rounds and
// false for all odd rounds.
func Test_sentRoundTracker_Has(t *testing.T) {
srt := newSentRoundTracker(0)
// Insert even rounds into the tracker
for rid := id.Round(0); rid < 100; rid++ {
if rid%2 == 0 {
srt.Insert(rid)
}
}
// Check that only even rounds exist
for rid := id.Round(0); rid < 100; rid++ {
if srt.Has(rid) {
if rid%2 != 0 {
t.Errorf("Round %d exists.", rid)
}
} else if rid%2 == 0 {
t.Errorf("Round %d does not exist.", rid)
}
}
}
// Tests that sentRoundTracker.Insert adds all the expected rounds.
func Test_sentRoundTracker_Insert(t *testing.T) {
srt := newSentRoundTracker(0)
// Insert even rounds into the tracker
for rid := id.Round(0); rid < 100; rid++ {
if rid%2 == 0 {
srt.Insert(rid)
}
}
// Check that only even rounds were added
for rid := id.Round(0); rid < 100; rid++ {
_, exists := srt.rounds[rid]
if exists {
if rid%2 != 0 {
t.Errorf("Round %d exists.", rid)
}
} else if rid%2 == 0 {
t.Errorf("Round %d does not exist.", rid)
}
}
}
// Tests that sentRoundTracker.Remove removes all even rounds.
func Test_sentRoundTracker_Remove(t *testing.T) {
srt := newSentRoundTracker(0)
// Add all round to tracker
for rid := id.Round(0); rid < 100; rid++ {
srt.Insert(rid)
}
// Remove even rounds from the tracker
for rid := id.Round(0); rid < 100; rid++ {
if rid%2 == 0 {
srt.Remove(rid)
}
}
// Check that only even rounds were removed
for rid := id.Round(0); rid < 100; rid++ {
_, exists := srt.rounds[rid]
if exists {
if rid%2 == 0 {
t.Errorf("Round %d does not exist.", rid)
}
} else if rid%2 != 0 {
t.Errorf("Round %d exists.", rid)
}
}
}
// Tests that sentRoundTracker.Len returns the expected length when the tracker
// is empty, filled, and then modified.
func Test_sentRoundTracker_Len(t *testing.T) {
srt := newSentRoundTracker(0)
if srt.Len() != 0 {
t.Errorf("Length of tracker incorrect.\nexpected: %d\nreceived: %d",
0, srt.Len())
}
// Add all round to tracker
for rid := id.Round(0); rid < 100; rid++ {
srt.Insert(rid)
}
if srt.Len() != 100 {
t.Errorf("Length of tracker incorrect.\nexpected: %d\nreceived: %d",
100, srt.Len())
}
// Remove even rounds from the tracker
for rid := id.Round(0); rid < 100; rid++ {
if rid%2 == 0 {
srt.Remove(rid)
}
}
if srt.Len() != 50 {
t.Errorf("Length of tracker incorrect.\nexpected: %d\nreceived: %d",
50, srt.Len())
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment