summaryrefslogtreecommitdiff
path: root/lgc/lgc.go
diff options
context:
space:
mode:
Diffstat (limited to 'lgc/lgc.go')
-rw-r--r--lgc/lgc.go108
1 files changed, 72 insertions, 36 deletions
diff --git a/lgc/lgc.go b/lgc/lgc.go
index a32bb36..fb51ec1 100644
--- a/lgc/lgc.go
+++ b/lgc/lgc.go
@@ -34,22 +34,28 @@ import (
type LoadGeneratingConnection interface {
Start(context.Context, debug.DebugLevel) bool
- Transferred() uint64
+ TransferredInInterval() (uint64, time.Duration)
Client() *http.Client
IsValid() bool
ClientId() uint64
+ Stats() *stats.TraceStats
}
+// TODO: All 64-bit fields that are accessed atomically must
+// appear at the top of this struct.
type LoadGeneratingConnectionDownload struct {
- Path string
- downloaded uint64
- client *http.Client
- debug debug.DebugLevel
- valid bool
- KeyLogger io.Writer
- clientId uint64
- tracer *httptrace.ClientTrace
- stats stats.TraceStats
+ downloaded uint64
+ lastIntervalEnd int64
+ Path string
+ downloadStartTime time.Time
+ lastDownloaded uint64
+ client *http.Client
+ debug debug.DebugLevel
+ valid bool
+ KeyLogger io.Writer
+ clientId uint64
+ tracer *httptrace.ClientTrace
+ stats stats.TraceStats
}
func (lgd *LoadGeneratingConnectionDownload) SetDnsStartTimeInfo(
@@ -126,6 +132,10 @@ func (lgd *LoadGeneratingConnectionDownload) SetGotConnTimeInfo(
now time.Time,
gotConnInfo httptrace.GotConnInfo,
) {
+ if gotConnInfo.Reused {
+ fmt.Printf("Unexpectedly reusing a connection!\n")
+ panic(!gotConnInfo.Reused)
+ }
lgd.stats.GetConnectionDoneTime = now
lgd.stats.ConnInfo = gotConnInfo
if debug.IsDebug(lgd.debug) {
@@ -200,12 +210,15 @@ func (lgd *LoadGeneratingConnectionDownload) ClientId() uint64 {
return lgd.clientId
}
-func (lgd *LoadGeneratingConnectionDownload) Transferred() uint64 {
- transferred := atomic.LoadUint64(&lgd.downloaded)
+func (lgd *LoadGeneratingConnectionDownload) TransferredInInterval() (uint64, time.Duration) {
+ transferred := atomic.SwapUint64(&lgd.downloaded, 0)
+ newIntervalEnd := (time.Now().Sub(lgd.downloadStartTime)).Nanoseconds()
+ previousIntervalEnd := atomic.SwapInt64(&lgd.lastIntervalEnd, newIntervalEnd)
+ intervalLength := time.Duration(newIntervalEnd - previousIntervalEnd)
if debug.IsDebug(lgd.debug) {
- fmt.Printf("download: Transferred: %v\n", transferred)
+ fmt.Printf("download: Transferred: %v bytes in %v.\n", transferred, intervalLength)
}
- return transferred
+ return transferred, intervalLength
}
func (lgd *LoadGeneratingConnectionDownload) Client() *http.Client {
@@ -268,57 +281,72 @@ func (lgd *LoadGeneratingConnectionDownload) Start(
go lgd.doDownload(ctx)
return true
}
-func (lbd *LoadGeneratingConnectionDownload) IsValid() bool {
- return lbd.valid
+func (lgd *LoadGeneratingConnectionDownload) IsValid() bool {
+ return lgd.valid
+}
+
+func (lgd *LoadGeneratingConnectionDownload) Stats() *stats.TraceStats {
+ return &lgd.stats
}
-func (lbd *LoadGeneratingConnectionDownload) doDownload(ctx context.Context) {
+func (lgd *LoadGeneratingConnectionDownload) doDownload(ctx context.Context) {
var request *http.Request = nil
var get *http.Response = nil
var err error = nil
if request, err = http.NewRequestWithContext(
- httptrace.WithClientTrace(ctx, lbd.tracer),
+ httptrace.WithClientTrace(ctx, lgd.tracer),
"GET",
- lbd.Path,
+ lgd.Path,
nil,
); err != nil {
- lbd.valid = false
+ lgd.valid = false
return
}
- if get, err = lbd.client.Do(request); err != nil {
- lbd.valid = false
+ lgd.downloadStartTime = time.Now()
+ lgd.lastIntervalEnd = 0
+
+ if get, err = lgd.client.Do(request); err != nil {
+ lgd.valid = false
return
}
- cr := &countingReader{n: &lbd.downloaded, ctx: ctx, readable: get.Body}
+ cr := &countingReader{n: &lgd.downloaded, ctx: ctx, readable: get.Body}
_, _ = io.Copy(ioutil.Discard, cr)
get.Body.Close()
- if debug.IsDebug(lbd.debug) {
+ if debug.IsDebug(lgd.debug) {
fmt.Printf("Ending a load-generating download.\n")
}
}
+// TODO: All 64-bit fields that are accessed atomically must
+// appear at the top of this struct.
type LoadGeneratingConnectionUpload struct {
- Path string
- uploaded uint64
- client *http.Client
- debug debug.DebugLevel
- valid bool
- KeyLogger io.Writer
- clientId uint64
+ uploaded uint64
+ lastIntervalEnd int64
+ Path string
+ uploadStartTime time.Time
+ lastUploaded uint64
+ client *http.Client
+ debug debug.DebugLevel
+ valid bool
+ KeyLogger io.Writer
+ clientId uint64
}
func (lgu *LoadGeneratingConnectionUpload) ClientId() uint64 {
return lgu.clientId
}
-func (lgu *LoadGeneratingConnectionUpload) Transferred() uint64 {
- transferred := atomic.LoadUint64(&lgu.uploaded)
- if debug.IsDebug(lgu.debug) {
- fmt.Printf("upload: Transferred: %v\n", transferred)
+func (lgd *LoadGeneratingConnectionUpload) TransferredInInterval() (uint64, time.Duration) {
+ transferred := atomic.SwapUint64(&lgd.uploaded, 0)
+ newIntervalEnd := (time.Now().Sub(lgd.uploadStartTime)).Nanoseconds()
+ previousIntervalEnd := atomic.SwapInt64(&lgd.lastIntervalEnd, newIntervalEnd)
+ intervalLength := time.Duration(newIntervalEnd - previousIntervalEnd)
+ if debug.IsDebug(lgd.debug) {
+ fmt.Printf("upload: Transferred: %v bytes in %v.\n", transferred, intervalLength)
}
- return transferred
+ return transferred, intervalLength
}
func (lgu *LoadGeneratingConnectionUpload) Client() *http.Client {
@@ -351,6 +379,9 @@ func (lgu *LoadGeneratingConnectionUpload) doUpload(ctx context.Context) bool {
var resp *http.Response = nil
var err error
+ lgu.uploadStartTime = time.Now()
+ lgu.lastIntervalEnd = 0
+
if resp, err = lgu.client.Post(lgu.Path, "application/octet-stream", s); err != nil {
lgu.valid = false
return false
@@ -394,3 +425,8 @@ func (lgu *LoadGeneratingConnectionUpload) Start(
go lgu.doUpload(ctx)
return true
}
+
+func (lgu *LoadGeneratingConnectionUpload) Stats() *stats.TraceStats {
+ // Get all your stats from the download side of the LGC.
+ return nil
+}