#include "StdAfx.h"
#include "P4Connection.h"
#include "P4BridgeClient.h"
#include "P4BridgeServer.h"
#include "ConnectionManager.h"
#define DELETE_OBJECT(obj) if( obj != NULL ) { delete obj; obj = NULL; }
//#ifdef _DEBUG_MEMORY
//IdleConnection::IdleConnection(P4Connection* pcon, _int64 releaseTime)
// : DoublyLinkedListItem(NULL), p4base(tIdleConnection)
//{
// pCon = pcon;
// ReleaseTime = releaseTime;
//}
//#endif
//IdleConnection::~IdleConnection(void)
//{
// DELETE_OBJECT(pCon);
//}
#ifdef _DEBUG_MEMORY
ConnectionManager::ConnectionManager(P4BridgeServer* pserver)
: DoublyLinkedList(&(pserver->Locker)), p4base(tConnectionManager)
#else
ConnectionManager::ConnectionManager(P4BridgeServer* pserver)
: DoublyLinkedList(&(pserver->Locker))
#endif
{
Initialized = 0;
pServer = pserver;
client = NULL;
user = NULL;
port = NULL;
password = NULL;
programName = NULL;
programVer = NULL;
cwd = NULL;
charset = (CharSetApi::CharSet) 0;
file_charset = (CharSetApi::CharSet) 0;
IdleConnections = new DoublyLinkedList(&(pserver->Locker));
}
ConnectionManager::~ConnectionManager(void)
{
if (disposed != 0)
{
return;
}
LOCK(&pServer->Locker);
disposed = 1;
DiscardConnections();
// The P4Connection list will be deleted by the destructor for DoublyLinkedList
//P4Connection* connection = (P4Connection*)First();
//while (connection)
//{
// P4Connection* nextConnection = (P4Connection*)connection->Next();
// delete connection;
// connection = nextConnection;
//}
Initialized = 0;
DELETE_OBJECT(client);
DELETE_OBJECT(user);
DELETE_OBJECT(port);
DELETE_OBJECT(password);
DELETE_OBJECT(programName);
DELETE_OBJECT(programVer);
DELETE_OBJECT(cwd);
}
const StrPtr* ConnectionManager::GetCharset( )
{
const StrPtr* ret = &(GetConnection(0)->GetCharset( ));
ReleaseConnection(0,0);
return ret;
}
int ConnectionManager::Disconnect( void )
{
LOCK(&pServer->Locker);
Initialized = 0;
P4Connection* connection = (P4Connection*)First();
while (connection)
{
if (connection->Id >=1)
{
// this connection is running a command and so it cannot
// be closed, set initialized to false, so it will reinitialize
// for the next command
//connection->clientNeedsInit = 1;
//Initialized = 0;
return 0;
}
connection = (P4Connection*)connection->Next();;
}
// not running any commands, so discard all connections
DiscardConnections();
return 1;
}
void ConnectionManager::DiscardConnections()
{
// discard idle connections
DELETE_OBJECT(IdleConnections);
//while (idle)
//{
// IdleConnection* pCur = idle;
// idle = (IdleConnection*)pCur->Prev();
// pCur->pCon->Disconnect();
// delete pCur;
//}
P4Connection* connection = (P4Connection*)Last();
while (connection)
{
P4Connection* pCur = connection;
connection = (P4Connection*)pCur->Prev();
pCur->Disconnect();
delete pCur;
}
this->pFirstItem = NULL;
this->pLastItem = NULL;
}
P4Connection* ConnectionManager::GetConnection(int cmdId)
{
LOCK(&pServer->Locker);
P4Connection* con = (P4Connection*)Find(cmdId);
if (con)
{
return con;
}
if (!IdleConnections)
{
IdleConnections = new DoublyLinkedList(&(pServer->Locker));
}
P4Connection* idle = (P4Connection*)IdleConnections->First();
if (idle)
{
//LOG_DEBUG1(4 ,"Using existing Connection for command: %X", cmdId);
//LOG_DEBUG1(4 ,"Now have %d connections in ConnectionManager", itemCount);
con = idle;
con->Id = cmdId;
IdleConnections->Remove(idle,0);
Add(con);
return con;
}
return NewConnection(cmdId);
}
void ConnectionManager::ReleaseConnection(int cmdId, unsigned _int64 releaseTime)
{
LOCK(&pServer->Locker);
P4Connection* con = (P4Connection*)Find(cmdId);
ReleaseConnection(con, releaseTime);
}
void ConnectionManager::ReleaseConnection(P4Connection* con, unsigned _int64 releaseTime)
{
if (con)
{
con->ui->clear_results();
Remove(con, 0);
con->Id = -1;
con->ReleaseTime = releaseTime;
IdleConnections->Add(con);
}
}
int ConnectionManager::FreeConnections( unsigned _int64 currentTime )
{
LOCK(&pServer->Locker);
if (!IdleConnections)
{
return 0;
}
P4Connection* con = (P4Connection*)IdleConnections->First();
while (con)
{
if (con->ReleaseTime > currentTime)
{
break;
}
con->Disconnect();
IdleConnections->Remove(con);
con = (P4Connection*)IdleConnections->First();
}
return IdleConnections->Count();
}
P4Connection* ConnectionManager::NewConnection(int cmdId)
{
//LOG_DEBUG1(4 ,"Creating a new Connection for command: %X", cmdId);
//LOG_DEBUG1(4 ,"Now have %d connections in ConnectionManager", itemCount);
LOCK(&pServer->Locker);
P4Connection* con = new P4Connection(this, pServer, cmdId);
con->ui = new P4BridgeClient(pServer, con);
if (client) con->SetClient( client);
if (user) con->SetUser(user);
if (port) con->SetPort(port);
if (password) con->SetPassword(password);
if (programName) con->SetProg(programName);
if (programVer) con->SetVersion(programVer);
if (cwd) con->SetCwd(cwd);
con->SetProtocol( "specstring", "" );
con->SetProtocol( "enableStreams", "" );
con->SetProtocol( "wingui", "999" );
// Set the character set for the untagged client
con->SetCharset(charset, file_charset);
return con;
}
//P4Connection* ConnectionManager::DefaultConnection()
//{
// P4Connection* value = (P4Connection*) Find(0);
// if (value)
// {
// return value;
// }
// return NewConnection(0);
//}
void ConnectionManager::SetCharset( CharSetApi::CharSet c, CharSetApi::CharSet filec )
{
charset = c;
file_charset = filec;
P4Connection* curCon = (P4Connection*)pFirstItem;
while (curCon)
{
curCon->SetCharset(c, filec);
curCon = (P4Connection*) curCon->Next();
}
if (!IdleConnections)
{
return;
}
P4Connection* curCon2 = (P4Connection*)IdleConnections->First();
while (curCon2)
{
curCon2->SetCharset(c, filec);
curCon2 = (P4Connection*) curCon2->Next();
}
}
void ConnectionManager::SetCwd( const char* newCwd )
{
DELETE_OBJECT(cwd);
cwd = CopyStr(newCwd);
if (!pFirstItem)
{
//DefaultConnection();
return;
}
P4Connection* curCon = (P4Connection*)pFirstItem;
while (curCon)
{
curCon->SetCwd(newCwd);
curCon = (P4Connection*) curCon->Next();
}
if (!IdleConnections)
{
return;
}
P4Connection* curCon2 = (P4Connection*)IdleConnections->First();
while (curCon2)
{
curCon2->SetCwd(newCwd);
curCon2 = (P4Connection*) curCon2->Next();
}
}
void ConnectionManager::SetClient( const char* newVal )
{
DELETE_OBJECT(client);
if (newVal) client = CopyStr(newVal);
}
void ConnectionManager::SetUser( const char* newVal )
{
DELETE_OBJECT(user);
if (newVal) user = CopyStr(newVal);
}
void ConnectionManager::SetPort( const char* newVal )
{
DELETE_OBJECT(port);
if (newVal) port = CopyStr(newVal);
}
void ConnectionManager::SetPassword( const char* newVal )
{
DELETE_OBJECT(password);
if (newVal) password = CopyStr(newVal);
}
void ConnectionManager::SetProgramName( const char* newVal )
{
DELETE_OBJECT(programName);
if (newVal) programName = CopyStr(newVal);
}
void ConnectionManager::SetProgramVer( const char* newVal )
{
DELETE_OBJECT(programVer);
if (newVal) programVer = CopyStr(newVal);
}