Skip to content
This repository has been archived by the owner on Nov 2, 2018. It is now read-only.

Commit

Permalink
Single download by uid endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisSchinnerl committed Jul 13, 2018
1 parent 9f8d535 commit b92f28f
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 4 deletions.
6 changes: 6 additions & 0 deletions modules/renter.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type DownloadInfo struct {
StartTime time.Time `json:"starttime"` // The time when the download was started.
StartTimeUnix int64 `json:"starttimeunix"` // The time when the download was started in unix format.
TotalDataTransferred uint64 `json:"totaldatatransferred"` // Total amount of data transferred, including negotiation, etc.
UID string `json:"uid"` // unique identifier that can be used to retrieve a specific download info.
}

// FileUploadParams contains the information used by the Renter to upload a
Expand Down Expand Up @@ -335,6 +336,11 @@ type Renter interface {
// began.
CurrentPeriod() types.BlockHeight

// DownloadByUID retrieves the download with the specified uid. It returns a
// DownloadInfo object and true if the object was found. Otherwise it returns
// false.
DownloadByUID(uid string) (DownloadInfo, bool)

// PeriodSpending returns the amount spent on contracts in the current
// billing period.
PeriodSpending() ContractorSpending
Expand Down
54 changes: 51 additions & 3 deletions modules/renter/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ package renter
// heap.

import (
"encoding/hex"
"fmt"
"os"
"path/filepath"
Expand All @@ -134,6 +135,7 @@ import (
"github.com/NebulousLabs/Sia/modules"
"github.com/NebulousLabs/Sia/persist"
"github.com/NebulousLabs/Sia/types"
"github.com/NebulousLabs/fastrand"

"github.com/NebulousLabs/errors"
)
Expand Down Expand Up @@ -168,6 +170,7 @@ type (
staticPriority uint64 // Downloads with higher priority will complete first.

// Utilities.
uid string
log *persist.Logger // Same log as the renter.
memoryManager *memoryManager // Same memoryManager used across the renter.
mu sync.Mutex // Unique to the download object.
Expand Down Expand Up @@ -374,6 +377,8 @@ func (r *Renter) managedNewDownload(params downloadParams) (*download, error) {

log: r.log,
memoryManager: r.memoryManager,

uid: hex.EncodeToString(fastrand.Bytes(8)),
}

// Determine which chunks to download.
Expand Down Expand Up @@ -476,14 +481,56 @@ func (r *Renter) managedNewDownload(params downloadParams) (*download, error) {
return d, nil
}

// DownloadByUID retrieves the download with the specified uid. It returns a
// DownloadInfo object and true if the object was found. Otherwise it returns
// false.
func (r *Renter) DownloadByUID(uid string) (modules.DownloadInfo, bool) {
r.downloadHistoryMu.Lock()
defer r.downloadHistoryMu.Unlock()

for i := range r.downloadHistory {
if r.downloadHistory[i].uid != uid {
continue
}
// Order from most recent to least recent.
d := r.downloadHistory[i]
d.mu.Lock() // Lock required for d.endTime only.
download := modules.DownloadInfo{
Destination: d.destinationString,
DestinationType: d.staticDestinationType,
Length: d.staticLength,
Offset: d.staticOffset,
SiaPath: d.staticSiaPath,

Completed: d.staticComplete(),
EndTime: d.endTime,
Received: atomic.LoadUint64(&d.atomicDataReceived),
StartTime: d.staticStartTime,
StartTimeUnix: d.staticStartTime.UnixNano(),
TotalDataTransferred: atomic.LoadUint64(&d.atomicTotalDataTransferred),
UID: d.uid,
}
// Release download lock before calling d.Err(), which will acquire the
// lock. The error needs to be checked separately because we need to
// know if it's 'nil' before grabbing the error string.
d.mu.Unlock()
if d.Err() != nil {
download.Error = d.Err().Error()
} else {
download.Error = ""
}
return download, true
}
return modules.DownloadInfo{}, false
}

// DownloadHistory returns the list of downloads that have been performed. Will
// include downloads that have not yet completed. Downloads will be roughly,
// but not precisely, sorted according to start time.
//
// TODO: Currently the DownloadHistory only contains downloads from this
// session, does not contain downloads that were executed for the purposes of
// repairing, and has no way to clear the download history if it gets long or
// unwieldy. It's not entirely certain which of the missing features are
// session and does not contain downloads that were executed for the purposes of
// repairing. It's not entirely certain which of the missing features are
// actually desirable, please consult core team + app dev community before
// deciding what to implement.
func (r *Renter) DownloadHistory() []modules.DownloadInfo {
Expand All @@ -508,6 +555,7 @@ func (r *Renter) DownloadHistory() []modules.DownloadInfo {
StartTime: d.staticStartTime,
StartTimeUnix: d.staticStartTime.UnixNano(),
TotalDataTransferred: atomic.LoadUint64(&d.atomicTotalDataTransferred),
UID: d.uid,
}
// Release download lock before calling d.Err(), which will acquire the
// lock. The error needs to be checked separately because we need to
Expand Down
7 changes: 7 additions & 0 deletions node/api/client/renter.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ func (c *Client) RenterClearDownloadsRangePost(after, before time.Time) (err err
return
}

// RenterDownloadByUID requests the /renter/downloads endpoint to get the
// history of a single download with the specified UID.
func (c *Client) RenterDownloadByUID(uid string) (di api.DownloadInfo, err error) {
err = c.get(fmt.Sprintf("/renter/downloads?uid=%s", uid), &di)
return
}

// RenterDownloadsGet requests the /renter/downloads resource
func (c *Client) RenterDownloadsGet() (rdq api.RenterDownloadQueue, err error) {
err = c.get("/renter/downloads", &rdq)
Expand Down
33 changes: 32 additions & 1 deletion node/api/renter.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ type (
StartTime time.Time `json:"starttime"` // The time when the download was started.
StartTimeUnix int64 `json:"starttimeunix"` // The time when the download was started in unix format.
TotalDataTransferred uint64 `json:"totaldatatransferred"` // The total amount of data transferred, including negotiation, overdrive etc.
UID string `json:"uid"` // unique identifier that can be used to retrieve a specific download info.
}
)

Expand Down Expand Up @@ -439,7 +440,36 @@ func (api *API) renterClearDownloadsHandler(w http.ResponseWriter, req *http.Req
}

// renterDownloadsHandler handles the API call to request the download queue.
func (api *API) renterDownloadsHandler(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
func (api *API) renterDownloadsHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
// If a specific uid was specified we return a single download.
uid := req.FormValue("uid")
if uid != "" {
di, ok := api.renter.DownloadByUID(uid)
if !ok {
WriteError(w, Error{"Couldn't find download for specified UID"}, http.StatusBadRequest)
return
}
WriteJSON(w, DownloadInfo{
Destination: di.Destination,
DestinationType: di.DestinationType,
Filesize: di.Length,
Length: di.Length,
Offset: di.Offset,
SiaPath: di.SiaPath,

Completed: di.Completed,
EndTime: di.EndTime,
Error: di.Error,
Received: di.Received,
StartTime: di.StartTime,
StartTimeUnix: di.StartTimeUnix,
TotalDataTransferred: di.TotalDataTransferred,
UID: di.UID,
})
return
}

// Otherwise we return the whole history.
var downloads []DownloadInfo
for _, di := range api.renter.DownloadHistory() {
downloads = append(downloads, DownloadInfo{
Expand All @@ -457,6 +487,7 @@ func (api *API) renterDownloadsHandler(w http.ResponseWriter, _ *http.Request, _
StartTime: di.StartTime,
StartTimeUnix: di.StartTimeUnix,
TotalDataTransferred: di.TotalDataTransferred,
UID: di.UID,
})
}
WriteJSON(w, RenterDownloadQueue{
Expand Down
11 changes: 11 additions & 0 deletions siatest/renter/renter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ func testClearDownloadHistory(t *testing.T, tg *siatest.TestGroup) {
}
numDownloads = len(rdg.Downloads)

// Make sure that we can also individually grab all the downloads.
for _, di := range rdg.Downloads {
d, err := r.RenterDownloadByUID(di.UID)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(d, di) {
t.Fatal("download infos are not equal")
}
}

// Check removing one download from history
// Remove First Download
timestamp := rdg.Downloads[0].StartTime
Expand Down

0 comments on commit b92f28f

Please sign in to comment.