コード例 #1
0
ファイル: oxrmeg2.c プロジェクト: grtlinux/TAIN_IB2
/*----------------------------------------------------------------------------*/
int MainService(char* strInfo)
/*----------------------------------------------------------------------------*/
{
	BOOL flag = TRUE;

    SigSetSignal();
    
    if (flag) CheckAlive();
    
	if (!flag) LOG(_FL_, 0, 0, "SOCKET INFO [%s]", strInfo);

	if (flag)
	{
		if (flag)
		{
			/* 사용할 FQ를 선택한다. */
                        /* 처리여부 : SEND(O) ,RECV(X), SEND/RECV(O) */
			if (!flag) FQ2Init(SEND_FQ, sServiceid);
                        /* 처리여부 : SEND(X) ,RECV(O), SEND/RECV(O) */
			if (flag) FQ2Init(RECV_FQ, sServiceid);
		}

		if (flag)
		{
			/* 소켓정보를 파싱하여 정리한다. */
			MSockParsingSockInfo(strInfo);
		}

		while (TRUE)
		{
			/* 프로세스 동작체크 */
			if (flag) CheckAlive();
				
			/* server / accept / connect 소켓을 구성하고 소켓을 생성한다. */
			/* MegaBox / MegaPac을 사용. connect후 negociation 처리 함수 */
			if (flag) MSockConnectSocketX25();

			/* accept / connect 소켓을 체크한다. TimeOut, Poll 체크 */
			if (flag) MSockCheckHandler(CheckProc);

			/* 소켓의 send 처리를 다루는 handler */
			if (flag) MSockSendHandler(SendProc);

			/* 소켓의 recv 처리를 다루는 handler */
			if (flag) MSockRecvHandler(RecvProc);

			if (!flag) sleep(5);
			if (flag) usleep(100 * 1000);
		}
	}

	if (flag) LOG(_FL_, 0, 0, "\x1b[41m-----%S ProcessExit -----\x1b[0m", sServiceid);

	return 0;
}
コード例 #2
0
ファイル: ofscom2.c プロジェクト: grtlinux/TAIN_IB2
/*----------------------------------------------------------------------------*/
int MainService(char* strInfo)
/*----------------------------------------------------------------------------*/
{
	BOOL flag = TRUE;

    SigSetSignal();
    
    if (flag) CheckAlive();
    
	if (!flag) LOG(_FL_, 0, 0, "SOCKET INFO [%s]", strInfo);

	if (flag)
	{
		if (flag)
		{
			/* 사용할 FQ를 선택한다. */
			if (flag)  FQ2Init(SEND_FQ, sServiceid);
			if (!flag) FQ2Init(RECV_FQ, sServiceid);
		}

		if (flag)
		{
			/* 소켓정보를 파싱하여 정리한다. */
			MSockParsingSockInfo(strInfo);
		}

		while (TRUE)
		{
			/* 프로세스 동작체크 */
			if (flag) CheckAlive();
				
			/* server / accept / connect 소켓을 구성하고 소켓을 생성한다. */
			if (flag) MSockMakeSockInfo();

			/* accept / connect 소켓을 체크한다. TimeOut, Poll 체크 */
			if (flag) MSockCheckHandler(CheckProc);

			/* 소켓의 send 처리를 다루는 handler */
			if (flag) MSockSendHandler(SendProc);

			/* 소켓의 recv 처리를 다루는 handler */
			if (flag) MSockRecvHandler(RecvProc);

			if (!flag) sleep(5);
			if (flag) usleep(20 * 1000); /* 0.02초 */
				
		}
	}

	if (flag) LOG(_FL_, 0, 0, "\x1b[41m-----%S ProcessExit -----\x1b[0m", sServiceid);

	return 0;
}
コード例 #3
0
ファイル: pgDatabase.cpp プロジェクト: KrisShannon/pgadmin3
bool pgDatabase::ExecuteVoid(const wxString &sql, bool reportError)
{
	bool rc = 0;
	if (connection())
	{
		rc = connection()->ExecuteVoid(sql, reportError);
		if (!rc)
			CheckAlive();
	}
	return rc;
}
コード例 #4
0
ファイル: pgDatabase.cpp プロジェクト: KrisShannon/pgadmin3
wxString pgDatabase::ExecuteScalar(const wxString &sql)
{
	wxString str;
	if (connection())
	{
		str = connection()->ExecuteScalar(sql);
		if (str.IsEmpty() && connection()->GetLastResultStatus() != PGRES_TUPLES_OK)
			CheckAlive();
	}
	return str;
}
コード例 #5
0
ファイル: pgDatabase.cpp プロジェクト: KrisShannon/pgadmin3
pgSet *pgDatabase::ExecuteSet(const wxString &sql)
{
	pgSet *set = 0;
	if (connection())
	{
		set = connection()->ExecuteSet(sql);
		if (!set)
			CheckAlive();
	}
	return set;
}
コード例 #6
0
/*
*
* @author Michael McQuarrie
* @param _fDeltaTick
* @return void
*/
void
CFlagParticleEmitter::Process(float32 _fDeltaTick)
{
    m_vec3Origin = m_pFlag->GetPosition();

    if (m_dwVertexBufferSize > m_vecParticles.size())
    {
        m_fSpawnTimer += _fDeltaTick;
        if (m_fSpawnTimer > m_fEmitRate)
        {
            m_fSpawnTimer = 0.0f;
            //Adding particles to the emitter
            AddParticle();
        }
    }
    //Check if particles are still alive
    for(std::vector<TParticle>::iterator iter = m_vecParticles.begin();
            iter != m_vecParticles.end(); ++iter)
    {
        if(iter->bAlive)
        {
            //Adding the velocity to move the particles
            iter->vec3Position += iter->vec3Velocity * _fDeltaTick * 5.0f;

            iter->colour.a = 1.0f - iter->fLifeTime;

            //Adding to the life counter
            iter->fLifeTime += _fDeltaTick;
            if(iter->fAge <= iter->fLifeTime)
            {
                m_fSpawnTimer += _fDeltaTick;
                if (m_fSpawnTimer >= m_fEmitRate)
                {
                    m_fSpawnTimer = 0.0f;
                    iter->fLifeTime = 0.0f;
                    Resetparticle(&(*iter));
                }
            }
        }
    }

    CTotalCubeDomination::GetInstance().GetRenderer()->AddToAllViewports(this, RENDERTYPE_3DCOORDS | RENDERTYPE_ALPHABLEND);

    //Lastly Remove the dead particles
    CheckAlive();
}
コード例 #7
0
ファイル: events.cpp プロジェクト: search5/pgadmin3
void frmMain::OnNew(wxCommandEvent &ev)
{
	pgaFactory *factory = pgaFactory::GetFactory(ev.GetId() - MNU_NEW);

	if (factory == &serverFactory)
	{
		if (currentObject && currentObject->IsCreatedBy(serverFactory))
		{
			pgServer *server = (pgServer *)currentObject;
			if (!server->GetConnected())
				ReconnectServer(server);
		}
		return;
	}

	if (currentObject)
	{
		if (!dlgProperty::CreateObjectDialog(this, currentObject, factory))
			CheckAlive();
	}
}
コード例 #8
0
ファイル: events.cpp プロジェクト: search5/pgadmin3
void frmMain::setDisplay(pgObject *data, ctlListView *props, ctlSQLBox *sqlbox)
{
	pgServer *server = 0;


	bool showTree = false;

	pgaFactory *factory = data->GetFactory();
	if (factory)
	{
		if (factory == &serverFactory)
		{
			server = (pgServer *)data;

			data->ShowTree(this, browser, props, sqlbox);
			showTree = false;
		}
		else
			showTree = true;
	}
	else
		showTree = false;

	if (showTree)
		data->ShowTree(this, browser, props, sqlbox);

	if (sqlbox)
	{
		sqlbox->SetReadOnly(false);
		sqlbox->SetText(data->GetSql(browser));
		sqlbox->SetReadOnly(true);
	}

	pgConn *conn = data->GetConnection();
	if (conn && (conn->GetStatus() == PGCONN_BROKEN || conn->GetStatus() == PGCONN_BAD))
	{
		CheckAlive();
		return;
	}

	unsigned int i;
	wxMenuItem *menuItem;
	i = newMenu->GetMenuItemCount();
	while (i--)
	{
		menuItem = newMenu->GetMenuItems().Item(i)->GetData();
		if (menuItem)
			delete newMenu->Remove(menuItem);
	}

	i = newContextMenu->GetMenuItemCount();
	while (i--)
	{
		menuItem = newContextMenu->GetMenuItems().Item(i)->GetData();
		if (menuItem)
			delete newContextMenu->Remove(menuItem);
	}

	editMenu->Enable(newMenuFactory->GetId(), false);

	wxMenu *indivMenu = data->GetNewMenu();
	if (indivMenu)
	{
		if (indivMenu->GetMenuItemCount())
		{
			editMenu->Enable(newMenuFactory->GetId(), true);

			for (i = 0 ; i < indivMenu->GetMenuItemCount() ; i++)
			{
				menuItem = indivMenu->GetMenuItems().Item(i)->GetData();
#if wxCHECK_VERSION(2, 9, 0)
				wxString lab = menuItem->GetItemLabelText();
#else
				wxString lab = menuItem->GetLabel(); // deprecated
#endif

				newMenu->Append(menuItem->GetId(), lab, menuItem->GetHelp());
				newContextMenu->Append(menuItem->GetId(), lab, menuItem->GetHelp());
			}
		}
		delete indivMenu;
	}

	menuFactories->CheckMenu(data, menuBar, toolBar);

	menuFactories->EnableSubmenu(menuBar, MNU_CONFIGSUBMENU);
	menuFactories->EnableSubmenu(menuBar, MNU_SLONY_SUBMENU);
}
コード例 #9
0
ファイル: events.cpp プロジェクト: search5/pgadmin3
void frmMain::OnCheckAlive(wxCommandEvent &event)
{
	CheckAlive();
}
コード例 #10
0
ファイル: frmMain.cpp プロジェクト: mhagander/pgadmin3
void frmMain::Refresh(pgObject *data)
{
    StartMsg(data->GetTranslatedMessage(REFRESHINGDETAILS));
    browser->Freeze();

    wxTreeItemId currentItem=data->GetId();

    // Scan the child nodes and make a list of those that are expanded
    // This is not an exact science as node names may change etc.
    wxArrayString expandedNodes;
    GetExpandedChildNodes(currentItem, expandedNodes);

    browser->DeleteChildren(currentItem);

    // refresh information about the object
    data->SetDirty();
    
    pgObject *newData = data->Refresh(browser, currentItem);

    bool done = !data->GetConnection() || data->GetConnection()->GetStatus() == PGCONN_OK;
    
    if (newData != data)
    {
        wxLogInfo(wxT("Deleting %s %s for refresh"), data->GetTypeName().c_str(), data->GetQuotedFullIdentifier().c_str());

        if (data == currentObject)
            currentObject = newData;

        if (newData)
        {
            wxLogInfo(wxT("Replacing with new node %s %s for refresh"), newData->GetTypeName().c_str(), newData->GetQuotedFullIdentifier().c_str());

            newData->SetId(currentItem);    // not done automatically
            browser->SetItemData(currentItem, newData);

            // Update the node text if this is an object, as it may have been renamed
            if (!newData->IsCollection())
                browser->SetItemText(currentItem, newData->GetDisplayName());

            delete data;
        }
        else
        {
            wxLogInfo(wxT("No object to replace: vanished after refresh."));
            
            // If the connection is dead, just return here
            if (data->GetConnection()->GetStatus() != PGCONN_OK)
            {
                CheckAlive();
                browser->Thaw();
                return;
            }
    
            wxTreeItemId delItem=currentItem;
            currentItem=browser->GetItemParent(currentItem);
            browser->SelectItem(currentItem);
            browser->Delete(delItem);
        }
    }

    if (currentItem)
    {
        execSelChange(currentItem, currentItem == browser->GetSelection());

        // Attempt to expand any child nodes that were previously expanded
        ExpandChildNodes(currentItem, expandedNodes);
    }

    browser->Thaw();
    EndMsg(done);
}
コード例 #11
0
ファイル: iocpserver.cpp プロジェクト: doug-dicks/code-1
//---------------------------------------------------------------------------------------------------------------------------
//StartServer()
//start  listen
//---------------------------------------------------------------------------------------------------------------------------
int  CIocpServer::StartServer(const char *local_ip,const char *local_port)
{
	if(!m_Inited)
	{
		fprintf(stderr, "Run Init() first !\n");
		return -1;
	}

	SOCKET_OBJ      *sockobj=NULL;
	HANDLE           hrc;
	int              endpointcount=0,
					 rc,
					 i;
	HANDLE			 event_accept; 

	struct addrinfo *res=NULL,
		*ptr=NULL;


#ifdef LOG_LEVEL2
	printf("LOG_LEVEL2");
#else 
//
#ifdef LOG_LEVEL1
	printf("LOG_LEVEL1");
#else
	printf("LOG_NONE");
#endif
//
#endif

	printf("\n\n连接线程:%d: 监听线程:%d; 平均连接数:%d ; ",
		m_CLThreads,m_Threads,AVERAGE_CONNECTIONS);
	printf("IOCP版本: %s;\n",IOCP_VERSION);

#ifdef ENABLE_KEEPALIVE
	printf("心跳检测:开启; ");
#else
	printf("心跳检测:关闭; ");
#endif
	printf("心跳超时:%d; 关闭延时:%d\n",KEEPALIVE_TIME,CLOSE_DELAY);


	res = ResolveAddress(local_ip, local_port, AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (res == NULL)
	{
		fprintf(stderr, "ResolveAddress failed to return any addresses!\n");
		return -1;
	}

	ptr = res;
	if (ptr)
	{
		sockobj = GetSocketObj(INVALID_SOCKET);
		// create the socket
		sockobj->s = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
		if (sockobj->s == INVALID_SOCKET)
		{
			fprintf(stderr,"socket failed: %d\n", WSAGetLastError());
			return -1;
		}

		// Associate the socket and its SOCKET_OBJ to the completion port
		hrc = CreateIoCompletionPort((HANDLE)sockobj->s, CompletionPort, (ULONG_PTR)sockobj, 0);
		if (hrc == NULL)
		{
			fprintf(stderr, "CreateIoCompletionPort failed: %d\n", GetLastError());
			return -1;
		}

		// bind the socket to a local address and port
		rc = bind(sockobj->s, ptr->ai_addr, (int)ptr->ai_addrlen);
		if (rc == SOCKET_ERROR)
		{
			fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
			return -1;
		}

		BUFFER_OBJ *acceptobj=NULL;
		GUID        guidAcceptEx = WSAID_ACCEPTEX;
		GUID	    guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
		DWORD       bytes;

		// Need to load the Winsock extension functions from each provider
		//    -- e.g. AF_INET and AF_INET6. 
		rc = WSAIoctl(
			sockobj->s,
			SIO_GET_EXTENSION_FUNCTION_POINTER,
			&guidAcceptEx,
			sizeof(guidAcceptEx),
			&lpfnAcceptEx,
			sizeof(lpfnAcceptEx),
			&bytes,
			NULL,
			NULL
			);
		if (rc == SOCKET_ERROR)
		{
			fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d\n",
				WSAGetLastError());
			return -1;
		}

		rc = WSAIoctl(
			sockobj->s,
			SIO_GET_EXTENSION_FUNCTION_POINTER,
			&guidGetAcceptExSockaddrs,
			sizeof(guidGetAcceptExSockaddrs),
			&lpfnGetAcceptExSockaddrs,
			sizeof(lpfnGetAcceptExSockaddrs),
			&bytes,
			NULL,
			NULL
			);
		if (rc == SOCKET_ERROR)
		{
			fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER faled: %d\n",
				WSAGetLastError());
			return -1;
		}

		// For TCP sockets, we need to "listen" on them
		rc = _(sockobj->s, 32);
		if (rc == SOCKET_ERROR)
		{
			fprintf(stderr, "listen failed: %d\n", WSAGetLastError());
			return -1;
		}
		
		event_accept =  CreateEvent(NULL, TRUE, FALSE, NULL);
		if(event_accept == NULL)
		{
			fprintf(stderr,"event_accept CreateEvent failed: %d\n",GetLastError());
			return -1;
		}

		rc = WSAEventSelect(sockobj->s,event_accept,FD_ACCEPT);
		if (rc == SOCKET_ERROR)
		{
			fprintf(stderr, "WSAEventSelect failed: %d\n", WSAGetLastError());
			return -1;
		}

        
		// Post the AcceptEx(s)
		for(i=0; i < DEFAULT_ACCEPTEX_COUNT ;i++)
		{
			acceptobj = GetBufferObj();
			sockobj->recvobj = acceptobj;
			if(PostAccept(sockobj, acceptobj) != 0)
			{
				FreeBufferObj(acceptobj);
				fprintf(stderr, "PostAccept failed: %d\n", WSAGetLastError());
				return -1;
			}
		}


		endpointcount++;
		ptr = ptr->ai_next;
	}
	// free the addrinfo structure for the 'bind' address
	freeaddrinfo(res);

	DWORD sleeptime = CLOSE_DELAY / 2;				 //每次sleep的时间

#ifdef LOG_STATUS
	long		sock=0;
	long		buf=0;
#endif

	if(sleeptime < 50) //限制在50ms以外
		sleeptime = 50;

	DWORD time_ontimer=GetTickCount();
	DWORD time_close = time_ontimer;
	DWORD time_alive = time_ontimer;
	DWORD newtime;
	BUFFER_OBJ *acceptobj;

	printf("\n>>> 服务器地址: %s: 端口号: %s <<<\n\n",
		local_ip, local_port);

	while (1)
	{
		rc = WaitForSingleObject(event_accept,sleeptime);
		if(rc == WAIT_FAILED)
		{
			fprintf(stderr,"WaitForSingleObject Failed:%d\n",GetLastError());
			break;
		} 
		else if(rc != WAIT_TIMEOUT) //GOT FD_ACCEPT
		{
		//	acceptobj = GetBufferObj();
		//	PostAccept(sockobj,acceptobj);
			if(m_accept_count < DEFAULT_ACCEPTEX_COUNT /2)
			{
				for(int i=0;i<DEFAULT_ACCEPTEX_COUNT/2;i++)
				{
					acceptobj = GetBufferObj();
					PostAccept(sockobj,acceptobj);
				}
			}
			ResetEvent(event_accept);
		}

		newtime = GetTickCount();

		if(newtime - time_ontimer > 3000) // 3秒
		{ 
			OnTimer();  //call virtual timer();
			time_ontimer = newtime;			
#ifdef LOG_STATUS		//显示服务器状态
			if(sock != gTotalSock || buf != gTotalBuf)
			{
				Log_Server.Write("服务器状态 : sock : %d ; buf : %d ; IoCount : %d ;",gTotalSock,gTotalBuf,gIoCount);

				sock = gTotalSock;
				buf = gTotalBuf;
			}
#endif

		}

		//Check Close
		if(newtime - time_close > sleeptime)
		{
			time_close = newtime;
			CheckClose();
		}

		if(newtime - time_alive > KEEPALIVE_TIME / 3)
		{
			CheckAlive();
			time_alive = newtime;
		}

	}

	WSACleanup();

	return 0;
}
コード例 #12
0
ファイル: urlBlastDlg.cpp プロジェクト: ceeaspb/webpagetest
/*-----------------------------------------------------------------------------
  Background thread for managing the state of the agent
-----------------------------------------------------------------------------*/
void CurlBlastDlg::ThreadProc(void)
{
    LoadSettings();

    // configure the desktop resolution
    WaitForSingleObject(testingMutex, INFINITE);
    SetupScreen();
    ReleaseMutex(testingMutex);

    // wait for the statup delay
    SetStatus(_T("Starting up..."));
    DWORD ms = startupDelay;
    while( ms > 0 && WaitForSingleObject(hMustExit,0) == WAIT_TIMEOUT) {
        Sleep(500);
        ms -= 500;
    }

    // launch the watchdog
    TCHAR path[MAX_PATH];
    GetModuleFileName(NULL, path, MAX_PATH);
    lstrcpy(PathFindFileName(path), _T("wptwatchdog.exe"));
    CString watchdog;
    watchdog.Format(_T("\"%s\" %d"), path, GetCurrentProcessId());
    HANDLE process = NULL;
    LaunchProcess(watchdog, &process);
    if (process)
        CloseHandle(process);

    if (WaitForSingleObject(hMustExit,0) == WAIT_TIMEOUT) {
        DoStartup();
    }

    // handle the periodic cleanup until it is time to exit
    Alive();
    DWORD msCleanup = 500;
    DWORD msTemp = 20000;
    while(WaitForSingleObject(hMustExit,0) == WAIT_TIMEOUT) {
        if (!msCleanup) {
            CloseDialogs();
            KillProcs();
            msCleanup = 500;
        } else
            msCleanup -= 500;

        if (!msTemp) {
            if (WaitForSingleObject(testingMutex, 0) != WAIT_TIMEOUT) {
                ClearTemp();
                msTemp = 20000;
                ReleaseMutex(testingMutex);
            }
        } else
            msTemp -= 500;

        CheckAlive();
        Sleep(500);
    }

    // signal and wait for all of the workers to finish
    KillWorker();

    // shut down the url manager
    urlManager.Stop();
}
コード例 #13
0
/*
* Process
* @author Rigardt de Vries
* @param _fDeltaTick			the game timer
* @return void
*/
void
CFlameParticleEmitter::Process(float32 _fDeltaTick)
{
	if (m_dwVertexBufferSize > m_vecParticles.size())
	{
		m_fSpawnTimer += _fDeltaTick;
		if (m_fSpawnTimer > m_fEmitRate)
		{
			m_fSpawnTimer = 0.0f;
			//Adding particles to the emitter
			AddParticle();
		}
	}

	//Check if particles are still emmiting
	for(std::vector<TParticle>::iterator iter = m_vecParticles.begin(); 
		iter != m_vecParticles.end(); ++iter)
	{
		if (m_pFlameplate->GetActive() == true)
		{
			if (iter->bAlive == false)
			{
				m_fSpawnTimer += _fDeltaTick;
				if (m_fSpawnTimer > m_fEmitRate)
				{
					m_fSpawnTimer = 0.0f;
					
					iter->bAlive = true;
				}
				
			}
		}
		if(iter->bAlive)
		{
			//Adding the velocity to move the particles
            iter->vec3Position += iter->vec3Velocity * _fDeltaTick * 8.0f;

			if (iter->fLifeTime < 0.3f)
			{
				D3DXColorLerp(&iter->colour, &KCOLYELLOW, &KCOLRED, iter->fLifeTime * 3.333333f);
			}
			else
			{
				D3DXColorLerp(&iter->colour, &KCOLRED, &KCOLGREY, (iter->fLifeTime - 0.3f) * 3.333333f);
			}

			//Adding to the life counter
			iter->fLifeTime += _fDeltaTick;
			if(iter->fAge <= iter->fLifeTime)
			{
				if (m_pFlameplate->GetActive() == true)
				{
					Resetparticle(&(*iter));
				}
				else
				{
					iter->bAlive = false;
				}
			}
		}
	}
	
    CTotalCubeDomination::GetInstance().GetRenderer()->AddToAllViewports(this, RENDERTYPE_3DCOORDS | RENDERTYPE_ALPHABLEND);

	//Lastly Remove the dead particles
	CheckAlive();
}
コード例 #14
0
ファイル: frmMain.cpp プロジェクト: kleopatra999/pgadmin3
void frmMain::Refresh(pgObject *data)
{
	bool done = false;
	pgObject *obj = NULL;

	StartMsg(data->GetTranslatedMessage(REFRESHINGDETAILS));
	browser->Freeze();

	wxTreeItemId currentItem = data->GetId();
	if (currentItem)
		obj = browser->GetObject(currentItem);

	if (obj && obj->CheckOpenDialogs(browser, currentItem))
	{
		wxString msg = _("There are properties dialogues open for one or more objects that would be refreshed. Please close the properties dialogues and try again.");
		wxMessageBox(msg, _("Cannot refresh browser"), wxICON_WARNING | wxOK);
	}
	else
	{
		if (data->GetMetaType() == PGM_SCHEMA && !data->IsCollection() && data->GetConnection()->BackendMinimumVersion(9, 3))
		{
			// Event triggers backend functions are at schema level.
			// Hence, we can consider that Event Triggers at schema level and partly at database.
			// So, if any schema is refreshed, we need to the event trigger collection as well.
			// It's a special case, which effects the schema operations on the event triggers as well.
			// To solve this, we are navigating to the parent node (database node), and then locating event trigger collections.
			// Once we've found the event triggers collection, we refresh it.
			//
			wxTreeItemId dbItem = browser->GetItemParent(browser->GetItemParent(browser->GetSelection()));
			pgCollection *eventTrgCol = browser->FindCollection(eventTriggerFactory, dbItem);

			if(eventTrgCol)
			Refresh(eventTrgCol);
		}

		// Scan the child nodes and make a list of those that are expanded
		// This is not an exact science as node names may change etc.
		wxArrayString expandedNodes;
		GetExpandedChildNodes(currentItem, expandedNodes);

		browser->DeleteChildren(currentItem);

		// refresh information about the object
		data->SetDirty();

		pgObject *newData = data->Refresh(browser, currentItem);
		done = !data->GetConnection() || data->GetConnection()->GetStatus() == PGCONN_OK;

		if (newData != data)
		{
			wxLogInfo(wxT("Deleting %s %s for refresh"), data->GetTypeName().c_str(), data->GetQuotedFullIdentifier().c_str());

			if (data == currentObject)
				currentObject = newData;

			if (newData)
			{
				wxLogInfo(wxT("Replacing with new node %s %s for refresh"), newData->GetTypeName().c_str(), newData->GetQuotedFullIdentifier().c_str());

				newData->SetId(currentItem);    // not done automatically
				browser->SetItemData(currentItem, newData);

				// Update the node text if this is an object, as it may have been renamed
				if (!newData->IsCollection())
					browser->SetItemText(currentItem, newData->GetDisplayName());

				delete data;
				data = NULL;
			}
			else
			{
				wxLogInfo(wxT("No object to replace: vanished after refresh."));

				// If the connection is dead, just return here
				if (data->GetConnection()->GetStatus() != PGCONN_OK)
				{
					CheckAlive();
					browser->Thaw();
					return;
				}

				wxTreeItemId delItem = currentItem;
				currentItem = browser->GetItemParent(currentItem);
				browser->SelectItem(currentItem);
				browser->Delete(delItem);
			}
		}

		if (currentItem)
		{
			// Select the current node
			execSelChange(currentItem, currentItem == browser->GetSelection());

			// Attempt to expand any child nodes that were previously expanded
			ExpandChildNodes(currentItem, expandedNodes);
		}
	}

	browser->Thaw();
	EndMsg(done);
}