ipfs-cluster/pintracker/optracker/operationtracker.go

292 lines
7.9 KiB
Go
Raw Normal View History

Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
// Package optracker implements functionality to track the status of pin and
// operations as needed by implementations of the pintracker component.
// It particularly allows to obtain status information for a given Cid,
// to skip re-tracking already ongoing operations, or to cancel ongoing
// operations when opposing ones arrive.
package optracker
import (
"context"
"fmt"
"strings"
"sync"
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
"time"
"github.com/ipfs/ipfs-cluster/api"
cid "github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log"
peer "github.com/libp2p/go-libp2p-core/peer"
"go.opencensus.io/trace"
)
var logger = logging.Logger("optracker")
// OperationTracker tracks and manages all inflight Operations.
type OperationTracker struct {
ctx context.Context // parent context for all ops
pid peer.ID
peerName string
mu sync.RWMutex
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
operations map[string]*Operation
}
func (opt *OperationTracker) String() string {
var b strings.Builder
fmt.Fprintf(&b, "pid: %v\n", opt.pid)
fmt.Fprintf(&b, "name: %s\n", opt.peerName)
fmt.Fprint(&b, "operations:\n")
opt.mu.RLock()
defer opt.mu.RUnlock()
for _, op := range opt.operations {
opstr := op.String()
opstrs := strings.Split(opstr, "\n")
for _, s := range opstrs {
fmt.Fprintf(&b, "\t%s\n", s)
}
}
return b.String()
}
// NewOperationTracker creates a new OperationTracker.
func NewOperationTracker(ctx context.Context, pid peer.ID, peerName string) *OperationTracker {
return &OperationTracker{
ctx: ctx,
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
pid: pid,
peerName: peerName,
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
operations: make(map[string]*Operation),
}
}
// TrackNewOperation will create, track and return a new operation unless
// one already exists to do the same thing, in which case nil is returned.
//
// If an operation exists it is of different type, it is
// cancelled and the new one replaces it in the tracker.
func (opt *OperationTracker) TrackNewOperation(ctx context.Context, pin *api.Pin, typ OperationType, ph Phase) *Operation {
ctx = trace.NewContext(opt.ctx, trace.FromContext(ctx))
ctx, span := trace.StartSpan(ctx, "optracker/TrackNewOperation")
defer span.End()
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
cidStr := pin.Cid.String()
opt.mu.Lock()
defer opt.mu.Unlock()
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
op, ok := opt.operations[cidStr]
if ok { // operation exists
if op.Type() == typ && op.Phase() != PhaseError && op.Phase() != PhaseDone {
return nil // an ongoing operation of the same sign exists
}
op.Cancel() // cancel ongoing operation and replace it
}
op2 := NewOperation(ctx, pin, typ, ph)
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
logger.Debugf("'%s' on cid '%s' has been created with phase '%s'", typ, cidStr, ph)
opt.operations[cidStr] = op2
return op2
}
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
// Clean deletes an operation from the tracker if it is the one we are tracking
// (compares pointers).
func (opt *OperationTracker) Clean(ctx context.Context, op *Operation) {
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
cidStr := op.Cid().String()
opt.mu.Lock()
defer opt.mu.Unlock()
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
op2, ok := opt.operations[cidStr]
if ok && op == op2 { // same pointer
delete(opt.operations, cidStr)
}
}
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
// Status returns the TrackerStatus associated to the last operation known
// with the given Cid. It returns false if we are not tracking any operation
// for the given Cid.
func (opt *OperationTracker) Status(ctx context.Context, c cid.Cid) (api.TrackerStatus, bool) {
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
opt.mu.RLock()
defer opt.mu.RUnlock()
op, ok := opt.operations[c.String()]
if !ok {
return 0, false
}
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
return op.ToTrackerStatus(), true
}
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
// SetError transitions an operation for a Cid into PhaseError if its Status
// is PhaseDone. Any other phases are considered in-flight and not touched.
// For things already in error, the error message is updated.
// Remote pins are ignored too.
func (opt *OperationTracker) SetError(ctx context.Context, c cid.Cid, err error) {
opt.mu.Lock()
defer opt.mu.Unlock()
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
op, ok := opt.operations[c.String()]
if !ok {
return
}
if ty := op.Type(); ty == OperationRemote {
return
}
if ph := op.Phase(); ph == PhaseDone || ph == PhaseError {
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
op.SetPhase(PhaseError)
op.SetError(err)
}
}
func (opt *OperationTracker) unsafePinInfo(ctx context.Context, op *Operation) api.PinInfo {
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
if op == nil {
return api.PinInfo{
Cid: cid.Undef,
Peer: opt.pid,
PeerName: opt.peerName,
Status: api.TrackerStatusUnpinned,
TS: time.Now(),
Error: "",
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
}
}
return api.PinInfo{
Cid: op.Cid(),
Peer: opt.pid,
PeerName: opt.peerName,
Status: op.ToTrackerStatus(),
TS: op.Timestamp(),
Error: op.Error(),
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
}
}
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
// Get returns a PinInfo object for Cid.
func (opt *OperationTracker) Get(ctx context.Context, c cid.Cid) *api.PinInfo {
ctx, span := trace.StartSpan(ctx, "optracker/GetAll")
defer span.End()
opt.mu.RLock()
defer opt.mu.RUnlock()
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
op := opt.operations[c.String()]
pInfo := opt.unsafePinInfo(ctx, op)
if pInfo.Cid == cid.Undef {
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
pInfo.Cid = c
}
return &pInfo
}
// GetExists returns a PinInfo object for a Cid only if there exists
// an associated Operation.
func (opt *OperationTracker) GetExists(ctx context.Context, c cid.Cid) (*api.PinInfo, bool) {
ctx, span := trace.StartSpan(ctx, "optracker/GetExists")
defer span.End()
opt.mu.RLock()
defer opt.mu.RUnlock()
op, ok := opt.operations[c.String()]
if !ok {
return nil, false
}
pInfo := opt.unsafePinInfo(ctx, op)
return &pInfo, true
}
// GetAll returns PinInfo objects for all known operations.
func (opt *OperationTracker) GetAll(ctx context.Context) []*api.PinInfo {
ctx, span := trace.StartSpan(ctx, "optracker/GetAll")
defer span.End()
var pinfos []*api.PinInfo
opt.mu.RLock()
defer opt.mu.RUnlock()
for _, op := range opt.operations {
pinfo := opt.unsafePinInfo(ctx, op)
pinfos = append(pinfos, &pinfo)
}
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
return pinfos
}
// CleanAllDone deletes any operation from the tracker that is in PhaseDone.
func (opt *OperationTracker) CleanAllDone(ctx context.Context) {
opt.mu.Lock()
defer opt.mu.Unlock()
for _, op := range opt.operations {
if op.Phase() == PhaseDone {
delete(opt.operations, op.Cid().String())
}
}
}
// OpContext gets the context of an operation, if any.
func (opt *OperationTracker) OpContext(ctx context.Context, c cid.Cid) context.Context {
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
opt.mu.RLock()
defer opt.mu.RUnlock()
op, ok := opt.operations[c.String()]
if !ok {
return nil
}
Fix: maptracker race issues This commit attempts to fix race issues in the maptracker since the introduction of the OperationTracker. There were two main problems: * Duplicity tracking the state both in the state map and the opTracker * Non atomiciy of operations with different threads being able to affect other threads operations. A test performing random Track/Untracks on the same Cid quickly showed that items would sometimes stay as pin_queued or pin_unqueued. That happened because operations could be cancelled under the hood by a different request, while leaving the map status untouched. It was not simply to deal with this issues without a refactoring. First, the state map has been removed, and the operation tracker now provides status information for any Cid. This implies that the tracker keeps all operations and operations have a `PhaseDone`. There's also a new `OperationRemote` type. Secondly, operations are only created in the tracker and can only be removed by their creators (they can be overwritten by other operations though). Operations cannot be accessed directly and modifications are limited to setting Error for PhaseDone operations. After created, *Operations are queued in the pinWorker queues which handle any status updates. This means, that, even when an operation has been removed from the tracker, status updates will not interfere with any other newer operations. In the maptracker, only the Unpin worker Cleans operations once processed. A sucessful unpin is the only way that a delete() happens in the tracker map. Otherwise, operations stay there until a newer operation for the Cid arrives and 1) cancels the existing one 2) takes its place. The tracker refuses to create a new operation if a similar "ongoing" operation of the same type exists. The final change is that Recover and RecoverAll() are not async and play by the same rules as Track() and Untrack(), queueing the items to be recovered. Note: for stateless pintracker, the tracker will need to Clean() operation of type OperationPin as well, and complement the Status reported by the tracker with those coming from IPFS. License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
2018-05-25 16:32:10 +00:00
return op.Context()
}
// Filter returns a slice of api.PinInfos that had associated
// Operations that matched the provided filter. Note, only supports
// filters of type OperationType or Phase, any other type
// will result in a nil slice being returned.
func (opt *OperationTracker) Filter(ctx context.Context, filters ...interface{}) []*api.PinInfo {
var pinfos []*api.PinInfo
opt.mu.RLock()
defer opt.mu.RUnlock()
ops := filterOpsMap(ctx, opt.operations, filters)
for _, op := range ops {
pinfo := opt.unsafePinInfo(ctx, op)
pinfos = append(pinfos, &pinfo)
}
return pinfos
}
// filterOps returns a slice that only contains operations
// with the matching filter. Note, only supports
// filters of type OperationType or Phase, any other type
// will result in a nil slice being returned.
func (opt *OperationTracker) filterOps(ctx context.Context, filters ...interface{}) []*Operation {
var fltops []*Operation
opt.mu.RLock()
defer opt.mu.RUnlock()
for _, op := range filterOpsMap(ctx, opt.operations, filters) {
fltops = append(fltops, op)
}
return fltops
}
func filterOpsMap(ctx context.Context, ops map[string]*Operation, filters []interface{}) map[string]*Operation {
fltops := make(map[string]*Operation)
if len(filters) < 1 {
return nil
}
if len(filters) == 1 {
filter(ctx, ops, fltops, filters[0])
return fltops
}
mainFilter, filters := filters[0], filters[1:]
filter(ctx, ops, fltops, mainFilter)
return filterOpsMap(ctx, fltops, filters)
}
func filter(ctx context.Context, in, out map[string]*Operation, filter interface{}) {
for _, op := range in {
switch filter.(type) {
case OperationType:
if op.Type() == filter {
out[op.Cid().String()] = op
}
case Phase:
if op.Phase() == filter {
out[op.Cid().String()] = op
}
}
}
}