#include "FileZilla.h"
#include "commandqueue.h"
#include "Mainfrm.h"
#include "state.h"
#include "recursive_operation.h"
#include "loginmanager.h"
#include "queue.h"
DEFINE_EVENT_TYPE(fzEVT_GRANTEXCLUSIVEENGINEACCESS)
CCommandQueue::CCommandQueue(CFileZillaEngine *pEngine, CMainFrame* pMainFrame)
{
m_pEngine = pEngine;
m_pMainFrame = pMainFrame;
m_exclusiveEngineRequest = false;
m_exclusiveEngineLock = false;
m_requestId = 0;
}
CCommandQueue::~CCommandQueue()
{
for (std::list<CCommand *>::iterator iter = m_CommandList.begin(); iter != m_CommandList.end(); iter++)
delete *iter;
}
bool CCommandQueue::Idle() const
{
return m_CommandList.empty() && !m_exclusiveEngineLock;
}
void CCommandQueue::ProcessCommand(CCommand *pCommand)
{
m_CommandList.push_back(pCommand);
if (m_CommandList.size() == 1)
ProcessNextCommand();
}
void CCommandQueue::ProcessNextCommand()
{
if (m_exclusiveEngineLock)
return;
if (m_pEngine->IsBusy())
return;
while (!m_CommandList.empty())
{
CCommand *pCommand = m_CommandList.front();
int res = m_pEngine->Command(*pCommand);
if (pCommand->GetId() == cmd_connect)
{
if (res == FZ_REPLY_WOULDBLOCK || res == FZ_REPLY_OK)
{
const CConnectCommand* pConnectCommand = (const CConnectCommand *)pCommand;
const CServer& server = pConnectCommand->GetServer();
m_pMainFrame->GetState()->SetServer(&server);
}
}
else if (pCommand->GetId() == cmd_disconnect)
{
m_pMainFrame->GetState()->SetServer(0);
}
if (res == FZ_REPLY_WOULDBLOCK)
break;
else if (res == FZ_REPLY_OK)
{
delete pCommand;
m_CommandList.pop_front();
continue;
}
else if (res == FZ_REPLY_ALREADYCONNECTED)
{
m_pMainFrame->GetState()->SetServer(0);
res = m_pEngine->Command(CDisconnectCommand());
if (res == FZ_REPLY_WOULDBLOCK)
{
m_CommandList.push_front(new CDisconnectCommand);
break;
}
else if (res != FZ_REPLY_OK)
{
wxBell();
delete pCommand;
m_CommandList.pop_front();
continue;
}
}
else
{
if ((res & FZ_REPLY_NOTCONNECTED) == FZ_REPLY_NOTCONNECTED)
m_pMainFrame->GetState()->SetServer(0);
wxBell();
// Let the remote list view know if a LIST command failed,
// so that it may issue the next command in recursive operations.
if (pCommand->GetId() == cmd_list)
m_pMainFrame->GetState()->GetRecursiveOperationHandler()->ListingFailed();
m_CommandList.pop_front();
delete pCommand;
}
}
if (m_CommandList.empty() && m_exclusiveEngineRequest)
{
GrantExclusiveEngineRequest();
}
}
bool CCommandQueue::Cancel()
{
if (m_exclusiveEngineLock)
return false;
if (m_CommandList.empty())
return true;
std::list<CCommand *>::iterator iter = m_CommandList.begin();
CCommand *pCommand = *(iter++);
for (; iter != m_CommandList.end(); iter++)
delete *iter;
m_CommandList.clear();
m_CommandList.push_back(pCommand);
if (!m_pEngine)
{
delete pCommand;
m_CommandList.clear();
return true;
}
int res = m_pEngine->Command(CCancelCommand());
if (res == FZ_REPLY_WOULDBLOCK)
return false;
else
return true;
}
void CCommandQueue::Finish(COperationNotification *pNotification)
{
if (pNotification->nReplyCode & FZ_REPLY_DISCONNECTED)
{
if (pNotification->commandId == cmd_none && !m_CommandList.empty())
{
// Pending event, has no relevance during command execution
delete pNotification;
return;
}
if (pNotification->nReplyCode & FZ_REPLY_PASSWORDFAILED)
CLoginManager::Get().CachedPasswordFailed(*m_pMainFrame->GetState()->GetServer());
m_pMainFrame->GetState()->SetServer(0);
}
if (m_exclusiveEngineLock)
{
m_pMainFrame->GetQueue()->ProcessNotification(pNotification);
return;
}
if (m_CommandList.empty())
{
delete pNotification;
return;
}
CCommand* pCommand = m_CommandList.front();
// Let the remote list view know if a LIST command failed,
// so that it may issue the next command in recursive operations.
if (pCommand->GetId() == cmd_list && pNotification->nReplyCode != FZ_REPLY_OK)
m_pMainFrame->GetState()->GetRecursiveOperationHandler()->ListingFailed();
delete m_CommandList.front();
m_CommandList.pop_front();
delete pNotification;
ProcessNextCommand();
}
void CCommandQueue::RequestExclusiveEngine(bool requestExclusive)
{
wxASSERT(!m_exclusiveEngineLock || !requestExclusive);
if (!m_exclusiveEngineRequest && requestExclusive)
{
m_requestId++;
if (m_requestId < 0)
m_requestId = 0;
if (m_CommandList.empty())
{
GrantExclusiveEngineRequest();
return;
}
}
if (!requestExclusive)
m_exclusiveEngineLock = false;
m_exclusiveEngineRequest = requestExclusive;
}
void CCommandQueue::GrantExclusiveEngineRequest()
{
wxASSERT(!m_exclusiveEngineLock);
m_exclusiveEngineLock = true;
m_exclusiveEngineRequest = false;
wxCommandEvent evt(fzEVT_GRANTEXCLUSIVEENGINEACCESS);
evt.SetId(m_requestId);
m_pMainFrame->GetQueue()->AddPendingEvent(evt);
}
CFileZillaEngine* CCommandQueue::GetEngineExclusive(int requestId)
{
if (!m_exclusiveEngineLock)
return 0;
if (requestId != m_requestId)
return 0;
return m_pEngine;
}
void CCommandQueue::ReleaseEngine()
{
m_exclusiveEngineLock = false;
ProcessNextCommand();
}
syntax highlighted by Code2HTML, v. 0.9.1