487 lines
16 KiB
Go
487 lines
16 KiB
Go
|
|
package notify
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"strconv"
|
||
|
|
"sync"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
itransfer "b612.me/notify/internal/transfer"
|
||
|
|
)
|
||
|
|
|
||
|
|
const (
|
||
|
|
transferMetadataIDKey = "_notify.transfer_id"
|
||
|
|
transferMetadataScopeKey = "_notify.transfer_scope"
|
||
|
|
transferMetadataRuntimeScopeKey = "_notify.transfer_runtime_scope"
|
||
|
|
transferMetadataTransportGenerationKey = "_notify.transfer_transport_generation"
|
||
|
|
transferMetadataSendChunkSizeKey = "_notify.transfer_send_chunk_size"
|
||
|
|
transferMetadataSendParallelismKey = "_notify.transfer_send_parallelism"
|
||
|
|
transferMetadataSendMaxInflightKey = "_notify.transfer_send_max_inflight_bytes"
|
||
|
|
)
|
||
|
|
|
||
|
|
type transferRuntime struct {
|
||
|
|
manager *itransfer.Manager
|
||
|
|
mu sync.RWMutex
|
||
|
|
store TransferResumeStore
|
||
|
|
}
|
||
|
|
|
||
|
|
func newTransferRuntime() *transferRuntime {
|
||
|
|
return &transferRuntime{
|
||
|
|
manager: itransfer.NewManager(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) snapshots() []itransfer.Snapshot {
|
||
|
|
if r == nil || r.manager == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
return r.manager.Snapshots()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) snapshot(direction fileTransferDirection, scope string, transferID string) (itransfer.Snapshot, bool) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return itransfer.Snapshot{}, false
|
||
|
|
}
|
||
|
|
return r.manager.Snapshot(r.key(direction, scope, transferID))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) ensureTransferDescriptor(direction fileTransferDirection, runtimeScope string, publicScope string, transportGeneration uint64, desc itransfer.Descriptor) {
|
||
|
|
if r == nil || r.manager == nil || desc.ID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
publicID := desc.ID
|
||
|
|
key := r.key(direction, runtimeScope, publicID)
|
||
|
|
if _, ok := r.manager.Snapshot(key); ok {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
desc.ID = key
|
||
|
|
desc.Metadata = transferRuntimeMetadataWithScope(runtimeScope, publicScope, transportGeneration, desc.Metadata, publicID)
|
||
|
|
switch direction {
|
||
|
|
case fileTransferDirectionReceive:
|
||
|
|
snapshot, _ := r.manager.StartIncoming(desc)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
default:
|
||
|
|
snapshot, _ := r.manager.StartOutgoing(desc)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) activate(direction fileTransferDirection, scope string, transferID string) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.Activate(r.key(direction, scope, transferID))
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) beginCommit(direction fileTransferDirection, scope string, transferID string) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.BeginCommit(r.key(direction, scope, transferID))
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) beginVerify(direction fileTransferDirection, scope string, transferID string) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.BeginVerify(r.key(direction, scope, transferID))
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) complete(direction fileTransferDirection, scope string, transferID string) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.Complete(r.key(direction, scope, transferID))
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) abort(direction fileTransferDirection, scope string, transferID string, err error) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.Abort(r.key(direction, scope, transferID), err)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) fail(direction fileTransferDirection, scope string, transferID string, err error) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.Fail(r.key(direction, scope, transferID), err)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) resume(direction fileTransferDirection, scope string, transferID string, confirmedBytes int64) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.Resume(r.key(direction, scope, transferID), confirmedBytes)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordSend(direction fileTransferDirection, scope string, transferID string, sentBytes int64) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.RecordSend(r.key(direction, scope, transferID), sentBytes)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) setAckedBytes(direction fileTransferDirection, scope string, transferID string, ackedBytes int64) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.SetAckedBytes(r.key(direction, scope, transferID), ackedBytes)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordReceive(direction fileTransferDirection, scope string, transferID string, recvBytes int64) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.RecordReceive(r.key(direction, scope, transferID), recvBytes)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordRetry(direction fileTransferDirection, scope string, transferID string) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.RecordRetry(r.key(direction, scope, transferID))
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordTimeout(direction fileTransferDirection, scope string, transferID string) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.RecordTimeout(r.key(direction, scope, transferID))
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordStage(direction fileTransferDirection, scope string, transferID string, stage string) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" || stage == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.SetStage(r.key(direction, scope, transferID), stage)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordFailureStage(direction fileTransferDirection, scope string, transferID string, stage string) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" || stage == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.SetFailureStage(r.key(direction, scope, transferID), stage)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordTelemetry(direction fileTransferDirection, scope string, transferID string, delta itransfer.TelemetryDelta) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.RecordTelemetry(r.key(direction, scope, transferID), delta)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordSourceRead(direction fileTransferDirection, scope string, transferID string, dur time.Duration) {
|
||
|
|
r.recordTelemetry(direction, scope, transferID, itransfer.TelemetryDelta{
|
||
|
|
SourceReadDuration: dur,
|
||
|
|
SourceReadCount: 1,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordStreamWrite(direction fileTransferDirection, scope string, transferID string, dur time.Duration) {
|
||
|
|
r.recordTelemetry(direction, scope, transferID, itransfer.TelemetryDelta{
|
||
|
|
StreamWriteDuration: dur,
|
||
|
|
StreamWriteCount: 1,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordSinkWrite(direction fileTransferDirection, scope string, transferID string, dur time.Duration) {
|
||
|
|
r.recordTelemetry(direction, scope, transferID, itransfer.TelemetryDelta{
|
||
|
|
SinkWriteDuration: dur,
|
||
|
|
SinkWriteCount: 1,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordSyncDuration(direction fileTransferDirection, scope string, transferID string, dur time.Duration) {
|
||
|
|
r.recordTelemetry(direction, scope, transferID, itransfer.TelemetryDelta{
|
||
|
|
SyncDuration: dur,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordVerifyDuration(direction fileTransferDirection, scope string, transferID string, dur time.Duration) {
|
||
|
|
r.recordTelemetry(direction, scope, transferID, itransfer.TelemetryDelta{
|
||
|
|
VerifyDuration: dur,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordCommitDuration(direction fileTransferDirection, scope string, transferID string, dur time.Duration) {
|
||
|
|
r.recordTelemetry(direction, scope, transferID, itransfer.TelemetryDelta{
|
||
|
|
CommitDuration: dur,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordCommitWaitDuration(direction fileTransferDirection, scope string, transferID string, dur time.Duration) {
|
||
|
|
r.recordTelemetry(direction, scope, transferID, itransfer.TelemetryDelta{
|
||
|
|
CommitWaitDuration: dur,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recordSendOptions(direction fileTransferDirection, scope string, transferID string, chunkSize int, parallelism int, maxInflightBytes int64) {
|
||
|
|
if r == nil || r.manager == nil || transferID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
metadata := make(itransfer.Metadata, 3)
|
||
|
|
if chunkSize > 0 {
|
||
|
|
metadata[transferMetadataSendChunkSizeKey] = strconv.Itoa(chunkSize)
|
||
|
|
}
|
||
|
|
if parallelism > 0 {
|
||
|
|
metadata[transferMetadataSendParallelismKey] = strconv.Itoa(parallelism)
|
||
|
|
}
|
||
|
|
if maxInflightBytes > 0 {
|
||
|
|
metadata[transferMetadataSendMaxInflightKey] = strconv.FormatInt(maxInflightBytes, 10)
|
||
|
|
}
|
||
|
|
if len(metadata) == 0 {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
snapshot, _ := r.manager.MergeMetadata(r.key(direction, scope, transferID), metadata)
|
||
|
|
r.persistSnapshot(snapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) key(direction fileTransferDirection, scope string, transferID string) string {
|
||
|
|
return fileTransferMonitorKey(direction, normalizeFileScope(scope), transferID)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) setResumeStore(store TransferResumeStore) {
|
||
|
|
if r == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
r.mu.Lock()
|
||
|
|
r.store = store
|
||
|
|
r.mu.Unlock()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) resumeStoreSnapshot() TransferResumeStore {
|
||
|
|
if r == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
r.mu.RLock()
|
||
|
|
defer r.mu.RUnlock()
|
||
|
|
return r.store
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) recover(ctx context.Context) error {
|
||
|
|
store := r.resumeStoreSnapshot()
|
||
|
|
if store == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
if ctx == nil {
|
||
|
|
ctx = context.Background()
|
||
|
|
}
|
||
|
|
snapshots, err := store.LoadTransferSnapshots(ctx)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
for _, snapshot := range snapshots {
|
||
|
|
if transferSnapshotTerminal(snapshot.State) {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
_, _ = r.manager.Restore(restoreInternalTransferSnapshot(snapshot))
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) resumableSnapshot(direction fileTransferDirection, publicScope string, transferID string) (TransferSnapshot, bool) {
|
||
|
|
if r == nil || transferID == "" {
|
||
|
|
return TransferSnapshot{}, false
|
||
|
|
}
|
||
|
|
wantScope := normalizeFileScope(publicScope)
|
||
|
|
var matched TransferSnapshot
|
||
|
|
found := false
|
||
|
|
for _, snapshot := range transferSnapshotsFromRuntime(r) {
|
||
|
|
if snapshot.ID != transferID || snapshot.Direction != convertTransferDirectionPublic(direction) {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if normalizeFileScope(snapshot.Scope) != wantScope {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if transferSnapshotTerminal(snapshot.State) {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if !found || snapshot.UpdatedAt.After(matched.UpdatedAt) {
|
||
|
|
matched = snapshot
|
||
|
|
found = true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return matched, found
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *transferRuntime) persistSnapshot(snapshot itransfer.Snapshot) {
|
||
|
|
store := r.resumeStoreSnapshot()
|
||
|
|
if store == nil || snapshot.ID == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
publicSnapshot := convertTransferSnapshot(snapshot)
|
||
|
|
ctx := context.Background()
|
||
|
|
if transferSnapshotTerminal(publicSnapshot.State) {
|
||
|
|
_ = store.DeleteTransferSnapshot(ctx, publicSnapshot)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
_ = store.SaveTransferSnapshot(ctx, publicSnapshot)
|
||
|
|
}
|
||
|
|
|
||
|
|
func restoreInternalTransferSnapshot(snapshot TransferSnapshot) itransfer.Snapshot {
|
||
|
|
runtimeScope := normalizeFileScope(snapshot.RuntimeScope)
|
||
|
|
publicScope := normalizeFileScope(snapshot.Scope)
|
||
|
|
if runtimeScope == defaultFileScope && publicScope != defaultFileScope {
|
||
|
|
runtimeScope = publicScope
|
||
|
|
}
|
||
|
|
metadata := transferRuntimeMetadataWithScope(runtimeScope, publicScope, snapshot.TransportGeneration, itransfer.Metadata(cloneTransferMetadata(snapshot.Metadata)), snapshot.ID)
|
||
|
|
metadata = transferRuntimeMetadataWithSendConfig(metadata, snapshot.ChunkSize, snapshot.Parallelism, snapshot.MaxInflightBytes)
|
||
|
|
return itransfer.Snapshot{
|
||
|
|
ID: fileTransferMonitorKey(convertTransferDirectionFile(snapshot.Direction), runtimeScope, snapshot.ID),
|
||
|
|
Direction: convertTransferDirectionInternal(snapshot.Direction),
|
||
|
|
Channel: transferChannelToKernel(snapshot.Channel),
|
||
|
|
State: convertTransferStateInternal(snapshot.State),
|
||
|
|
Stage: snapshot.Stage,
|
||
|
|
LastFailureStage: snapshot.LastFailureStage,
|
||
|
|
Size: snapshot.Size,
|
||
|
|
Checksum: snapshot.Checksum,
|
||
|
|
Metadata: metadata,
|
||
|
|
SentBytes: snapshot.SentBytes,
|
||
|
|
AckedBytes: snapshot.AckedBytes,
|
||
|
|
ReceivedBytes: snapshot.ReceivedBytes,
|
||
|
|
InflightBytes: snapshot.InflightBytes,
|
||
|
|
RetryCount: snapshot.RetryCount,
|
||
|
|
TimeoutCount: snapshot.TimeoutCount,
|
||
|
|
LastError: snapshot.LastError,
|
||
|
|
SourceReadDuration: snapshot.SourceReadDuration,
|
||
|
|
StreamWriteDuration: snapshot.StreamWriteDuration,
|
||
|
|
SinkWriteDuration: snapshot.SinkWriteDuration,
|
||
|
|
SyncDuration: snapshot.SyncDuration,
|
||
|
|
VerifyDuration: snapshot.VerifyDuration,
|
||
|
|
CommitDuration: snapshot.CommitDuration,
|
||
|
|
CommitWaitDuration: snapshot.CommitWaitDuration,
|
||
|
|
SourceReadCount: snapshot.SourceReadCount,
|
||
|
|
StreamWriteCount: snapshot.StreamWriteCount,
|
||
|
|
SinkWriteCount: snapshot.SinkWriteCount,
|
||
|
|
StartedAt: snapshot.StartedAt.UnixNano(),
|
||
|
|
UpdatedAt: snapshot.UpdatedAt.UnixNano(),
|
||
|
|
CompletedAt: snapshot.CompletedAt.UnixNano(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func convertTransferDirectionInternal(direction TransferDirection) itransfer.Direction {
|
||
|
|
if direction == TransferDirectionReceive {
|
||
|
|
return itransfer.DirectionReceive
|
||
|
|
}
|
||
|
|
return itransfer.DirectionSend
|
||
|
|
}
|
||
|
|
|
||
|
|
func convertTransferDirectionFile(direction TransferDirection) fileTransferDirection {
|
||
|
|
if direction == TransferDirectionReceive {
|
||
|
|
return fileTransferDirectionReceive
|
||
|
|
}
|
||
|
|
return fileTransferDirectionSend
|
||
|
|
}
|
||
|
|
|
||
|
|
func convertTransferDirectionPublic(direction fileTransferDirection) TransferDirection {
|
||
|
|
if direction == fileTransferDirectionReceive {
|
||
|
|
return TransferDirectionReceive
|
||
|
|
}
|
||
|
|
return TransferDirectionSend
|
||
|
|
}
|
||
|
|
|
||
|
|
func convertTransferStateInternal(state TransferState) itransfer.State {
|
||
|
|
switch state {
|
||
|
|
case TransferStateNegotiating:
|
||
|
|
return itransfer.StateNegotiating
|
||
|
|
case TransferStatePrepared:
|
||
|
|
return itransfer.StatePrepared
|
||
|
|
case TransferStateActive:
|
||
|
|
return itransfer.StateActive
|
||
|
|
case TransferStatePaused:
|
||
|
|
return itransfer.StatePaused
|
||
|
|
case TransferStateCommitting:
|
||
|
|
return itransfer.StateCommitting
|
||
|
|
case TransferStateVerifying:
|
||
|
|
return itransfer.StateVerifying
|
||
|
|
case TransferStateDone:
|
||
|
|
return itransfer.StateDone
|
||
|
|
case TransferStateAborted:
|
||
|
|
return itransfer.StateAborted
|
||
|
|
case TransferStateFailed:
|
||
|
|
return itransfer.StateFailed
|
||
|
|
default:
|
||
|
|
return itransfer.StateInit
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func transferSnapshotTerminal(state TransferState) bool {
|
||
|
|
switch state {
|
||
|
|
case TransferStateDone, TransferStateAborted, TransferStateFailed:
|
||
|
|
return true
|
||
|
|
default:
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func transferRuntimeMetadataWithScope(runtimeScope string, publicScope string, transportGeneration uint64, metadata itransfer.Metadata, transferID string) itransfer.Metadata {
|
||
|
|
cloned := cloneTransferRuntimeMetadata(metadata)
|
||
|
|
if cloned == nil {
|
||
|
|
cloned = make(itransfer.Metadata)
|
||
|
|
}
|
||
|
|
runtimeScope = normalizeFileScope(runtimeScope)
|
||
|
|
publicScope = normalizeFileScope(publicScope)
|
||
|
|
if publicScope == defaultFileScope && runtimeScope != defaultFileScope {
|
||
|
|
publicScope = runtimeScope
|
||
|
|
}
|
||
|
|
cloned[transferMetadataIDKey] = transferID
|
||
|
|
cloned[transferMetadataScopeKey] = publicScope
|
||
|
|
cloned[transferMetadataRuntimeScopeKey] = runtimeScope
|
||
|
|
if transportGeneration > 0 {
|
||
|
|
cloned[transferMetadataTransportGenerationKey] = strconv.FormatUint(transportGeneration, 10)
|
||
|
|
} else {
|
||
|
|
delete(cloned, transferMetadataTransportGenerationKey)
|
||
|
|
}
|
||
|
|
return cloned
|
||
|
|
}
|
||
|
|
|
||
|
|
func transferRuntimeMetadataWithSendConfig(metadata itransfer.Metadata, chunkSize int, parallelism int, maxInflightBytes int64) itransfer.Metadata {
|
||
|
|
cloned := cloneTransferRuntimeMetadata(metadata)
|
||
|
|
if cloned == nil {
|
||
|
|
cloned = make(itransfer.Metadata)
|
||
|
|
}
|
||
|
|
if chunkSize > 0 {
|
||
|
|
cloned[transferMetadataSendChunkSizeKey] = strconv.Itoa(chunkSize)
|
||
|
|
} else {
|
||
|
|
delete(cloned, transferMetadataSendChunkSizeKey)
|
||
|
|
}
|
||
|
|
if parallelism > 0 {
|
||
|
|
cloned[transferMetadataSendParallelismKey] = strconv.Itoa(parallelism)
|
||
|
|
} else {
|
||
|
|
delete(cloned, transferMetadataSendParallelismKey)
|
||
|
|
}
|
||
|
|
if maxInflightBytes > 0 {
|
||
|
|
cloned[transferMetadataSendMaxInflightKey] = strconv.FormatInt(maxInflightBytes, 10)
|
||
|
|
} else {
|
||
|
|
delete(cloned, transferMetadataSendMaxInflightKey)
|
||
|
|
}
|
||
|
|
return cloned
|
||
|
|
}
|
||
|
|
|
||
|
|
func cloneTransferRuntimeMetadata(src itransfer.Metadata) itransfer.Metadata {
|
||
|
|
if len(src) == 0 {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
dst := make(itransfer.Metadata, len(src))
|
||
|
|
for key, value := range src {
|
||
|
|
dst[key] = value
|
||
|
|
}
|
||
|
|
return dst
|
||
|
|
}
|