예제 #1
0
        internal void Reset()
        {
            lock (_ownersLock)
            {
                _owners.Clear();
            }

            lock (_jobLock) {
                _currentJob = null;
                _currentId  = 0;
            }
        }
예제 #2
0
        private void GotLock(uint storeId)
        {
            lock (_jobLock)
            {
                if (_currentJobCompleted)
                {
                    // TODO - release lock?
                }

                if (_currentJob == null || storeId != _currentJob.StoreId)
                {
                    return;
                }

                // Ensure only run once
                if (_currentJob.StartedAt != null)
                {
                    return;
                }

                // If transfer has timed out, cancel it and release lock
                if (_currentJob.ExpiresAt.HasValue && _currentJob.ExpiresAt.Value < DateTime.Now)
                {
                    _currentJob = null;
                    ReleaseLock(storeId);
                    return;
                }

                ICommand cmd = _currentJob.Start(_currentId);
                if (cmd == null)
                {
                    // Release lock
                    if (_currentJob.StoreId != 0xffff) // If not macro
                    {
                        ReleaseLock(_currentJob.StoreId);
                    }

                    _currentJob = null;
                    DequeueAndRun();
                    return;
                }

                _connection.QueueCommand(cmd);
            }
        }
예제 #3
0
        private void GotLock(uint storeId)
        {
            lock (_jobLock)
            {
                if (_currentJob == null || storeId != _currentJob.StoreId)
                {
                    // Don't need it
                    ReleaseLock(storeId);
                    // TODO - will we get stuck if we then never get our lock?
                    return;
                }

                // Ensure only run once
                if (_currentJob.StartedAt != null)
                {
                    return;
                }

                // If transfer has timed out, cancel it and release lock
                if (_currentJob.ExpiresAt.HasValue && _currentJob.ExpiresAt.Value < DateTime.Now)
                {
                    _currentJob = null;
                    ReleaseLock(storeId);
                    return;
                }

                _currentStartCommand = _currentJob.Start(_currentId);
                if (_currentStartCommand == null)
                {
                    // Release lock
                    ReleaseLock(_currentJob.StoreId);

                    _currentJob = null;
                    DequeueAndRun();
                    return;
                }

                _connection.QueueCommand(_currentStartCommand);
            }
        }
예제 #4
0
        private void LostLock(uint storeId)
        {
            lock (_jobLock)
            {
                if (_currentJob != null && storeId == _currentJob.StoreId)
                {
                    if (_currentJobCompleted)
                    {
                        _currentJob = null;
                    }
                    else
                    {
                        // TODO - cancel current job instead of just running next

                        DequeueAndRun();
                        return;
                    }
                }

                DequeueAndRun();
            }
        }
예제 #5
0
        private void DequeueAndRun()
        {
            lock (_jobLock)
            {
                if (_currentJob != null)
                {
                    return;
                }

                if (!_queue.TryDequeue(out _currentJob))
                {
                    return;
                }

                // If job has timed out, skip it and try again
                if (_currentJob.ExpiresAt.HasValue && _currentJob.ExpiresAt.Value < DateTime.Now)
                {
                    _currentJob = null;
                    DequeueAndRun();
                    return;
                }

                _currentId           = _nextTransferId++;
                _currentJobCompleted = false;

                if (_currentJob.StoreId == 0xffff) // Macro pool doesnt use a lock
                {
                    GotLock(_currentJob.StoreId);
                    return;
                }

                // Try and get lock
                _connection.QueueCommand(new LockStateSetCommand {
                    Index = _currentJob.StoreId, Locked = true
                });
            }
        }
예제 #6
0
 public void QueueJob(DataTransferJob job)
 {
     _queue.Enqueue(job);
 }
예제 #7
0
        public bool HandleCommand(ICommand cmd)
        {
            if (cmd is LockStateChangedCommand chCmd)
            {
                lock (_ownersLock)
                {
                    if (!chCmd.Locked)
                    {
                        _owners[chCmd.Index] = LockOwner.None;
                    }
                    else if (!_owners.ContainsKey(chCmd.Index) || _owners[chCmd.Index] == LockOwner.None)
                    {
                        _owners[chCmd.Index] = LockOwner.Other;
                    }
                }

                return(true);
            }

            if (cmd is LockObtainedCommand obCmd)
            {
                lock (_ownersLock)
                {
                    _owners[obCmd.Index] = LockOwner.This;

                    GotLock(obCmd.Index);
                }

                return(true);
            }

            lock (_jobLock)
            {
                if (_currentJob == null)
                {
                    // TODO - send error?
                    return(false);
                }

                // The atem sends this 'error' while we are not allowed/able to download the asset. we should keep retrying the same start until it succeeds
                // Note: perhaps this means that someone else has the lock, but we have the lock which will become valid once their transfer completes?
                if (cmd is DataTransferErrorCommand errCmd && _currentId == errCmd.TransferId)
                {
                    // This can happen sometimes, and we should retry until it works
                    if (errCmd.ErrorCode == DataTransferError.TryAgain && _currentStartCommand != null)
                    {
                        _connection.QueueCommand(_currentStartCommand);
                        return(true);
                    }

                    // The asset was not found, or some unknown error meaning we should fail and move on
                    if (_currentJob != null)
                    {
                        if (errCmd.ErrorCode != DataTransferError.NotFound)
                        {
                            // We don't know the error, so abort the transfer
                            _connection.QueueCommand(new DataTransferAbortCommand
                            {
                                TransferId = _currentId
                            });
                        }

                        ReleaseLock(_currentJob.StoreId);
                        _currentJob.Fail();

                        _currentStartCommand = null;
                        _currentJob          = null;
                    }

                    // Try and get next job started
                    DequeueAndRun();
                    return(true);
                }

                if (cmd is DataTransferCompleteCommand completeCmd && _currentId != completeCmd.TransferId)
                {
                    // TODO - should we try and start our job?
                    return(false);
                }

                if (!AcceptedCommands.Contains(cmd.GetType()) || !_currentJob.StartedAt.HasValue)
                {
                    return(false);
                }

                var res = _currentJob.OnMessage(cmd, _connection);
                switch (res)
                {
                case DataTransferStatus.OK:
                    break;     // Job is still working away

                case DataTransferStatus.Success:

                    ReleaseLock(_currentJob.StoreId);

                    _currentStartCommand = null;
                    _currentJob          = null;

                    DequeueAndRun();

                    break;

                case DataTransferStatus.Unknown:
                    // Command was not handled, this is probably ok
                    // TODO - we should track the time of the last handled command so we can check for stuck transfers
                    return(false);
                }

                return(true);
            }
        }
예제 #8
0
        public bool HandleCommand(ICommand cmd)
        {
            if (cmd is LockStateChangedCommand chCmd)
            {
                lock (_ownersLock)
                {
                    if (!chCmd.Locked)
                    {
                        _owners[chCmd.Index] = LockOwner.None;
                    }
                    else if (!_owners.ContainsKey(chCmd.Index) || _owners[chCmd.Index] == LockOwner.None)
                    {
                        _owners[chCmd.Index] = LockOwner.Other;
                    }

                    if (!chCmd.Locked)
                    {
                        LostLock(chCmd.Index);
                    }
                }

                return(true);
            }

            if (cmd is LockObtainedCommand obCmd)
            {
                lock (_ownersLock)
                {
                    _owners[obCmd.Index] = LockOwner.This;

                    GotLock(obCmd.Index);
                }

                return(true);
            }

            lock (_jobLock)
            {
                if (_currentJob == null)
                {
                    // TODO - send error?
                    return(false);
                }

                if (!AcceptedCommands.Contains(cmd.GetType()) || !_currentJob.StartedAt.HasValue)
                {
                    return(false);
                }

                var res = _currentJob.OnMessage(cmd, _connection);
                switch (res)
                {
                case DataTransferStatus.OK:
                    break;     // Job is still working away

                case DataTransferStatus.Success:
                    _currentJobCompleted = true;

                    if (HoldsLock(_currentJob.StoreId))
                    {
                        ReleaseLock(_currentJob.StoreId);
                    }
                    else
                    {
                        _currentJob = null;
                    }
                    break;

                case DataTransferStatus.Error:
                    // TODO - send error
                    _currentJobCompleted = true;

                    if (HoldsLock(_currentJob.StoreId))
                    {
                        ReleaseLock(_currentJob.StoreId);
                    }
                    else
                    {
                        _currentJob = null;
                    }
                    break;
                }

                return(true);
            }
        }