23
28
#include "frm/frmMain.h"
24
29
#include "utils/pgfeatures.h"
25
30
#include "schema/pgServer.h"
29
BEGIN_EVENT_TABLE(frmStatus, pgDialog)
30
EVT_BUTTON(wxID_REFRESH, frmStatus::OnRefresh)
31
EVT_BUTTON(wxID_CLOSE, frmStatus::OnCloseBtn)
32
EVT_BUTTON(wxID_CANCEL, frmStatus::OnCancelBtn)
33
EVT_BUTTON(wxID_STOP, frmStatus::OnTerminateBtn)
34
EVT_BUTTON(XRCID("btnCommit"), frmStatus::OnCommit)
35
EVT_BUTTON(XRCID("btnRollback"), frmStatus::OnRollback)
36
EVT_CLOSE( frmStatus::OnClose)
37
EVT_COMMAND_SCROLL(XRCID("slRate"), frmStatus::OnRateChange)
38
EVT_NOTEBOOK_PAGE_CHANGING(XRCID("nbStatus"), frmStatus::OnNotebookPageChanged)
39
EVT_TIMER(TIMER_ID, frmStatus::OnRefreshTimer)
40
EVT_LIST_ITEM_SELECTED(XRCID("lstStatus"), frmStatus::OnSelStatusItem)
41
EVT_LIST_ITEM_DESELECTED(XRCID("lstStatus"), frmStatus::OnSelStatusItem)
42
EVT_LIST_ITEM_SELECTED(XRCID("lstLocks"), frmStatus::OnSelLockItem)
43
EVT_LIST_ITEM_DESELECTED(XRCID("lstLocks"), frmStatus::OnSelLockItem)
44
EVT_LIST_ITEM_SELECTED(XRCID("lstXacts"), frmStatus::OnSelXactItem)
45
EVT_LIST_ITEM_DESELECTED(XRCID("lstXacts"), frmStatus::OnSelXactItem)
46
EVT_COMBOBOX(XRCID("cbLogfiles"), frmStatus::OnLoadLogfile)
47
EVT_BUTTON(XRCID("btnRotateLog"), frmStatus::OnRotateLogfile)
31
#include "ctl/ctlMenuToolbar.h"
32
#include "utils/csvfiles.h"
35
#include "images/clip_copy.xpm"
36
#include "images/readdata.xpm"
37
#include "images/query_cancel.xpm"
38
#include "images/terminate_backend.xpm"
39
#include "images/delete.xpm"
40
#include "images/storedata.xpm"
43
BEGIN_EVENT_TABLE(frmStatus, pgFrame)
44
EVT_MENU(MNU_EXIT, frmStatus::OnExit)
46
EVT_MENU(MNU_COPY, frmStatus::OnCopy)
48
EVT_MENU(MNU_HELP, frmStatus::OnHelp)
49
EVT_MENU(MNU_STATUSPAGE, frmStatus::OnToggleStatusPane)
50
EVT_MENU(MNU_LOCKPAGE, frmStatus::OnToggleLockPane)
51
EVT_MENU(MNU_XACTPAGE, frmStatus::OnToggleXactPane)
52
EVT_MENU(MNU_LOGPAGE, frmStatus::OnToggleLogPane)
53
EVT_MENU(MNU_TOOLBAR, frmStatus::OnToggleToolBar)
54
EVT_MENU(MNU_DEFAULTVIEW, frmStatus::OnDefaultView)
56
EVT_AUI_PANE_CLOSE( frmStatus::OnPaneClose)
58
EVT_COMBOBOX(CTL_RATECBO, frmStatus::OnRateChange)
59
EVT_MENU(MNU_REFRESH, frmStatus::OnRefresh)
60
EVT_MENU(MNU_CANCEL, frmStatus::OnCancelBtn)
61
EVT_MENU(MNU_TERMINATE, frmStatus::OnTerminateBtn)
62
EVT_MENU(MNU_COMMIT, frmStatus::OnCommit)
63
EVT_MENU(MNU_ROLLBACK, frmStatus::OnRollback)
64
EVT_COMBOBOX(CTL_LOGCBO, frmStatus::OnLoadLogfile)
65
EVT_BUTTON(CTL_ROTATEBTN, frmStatus::OnRotateLogfile)
67
EVT_TIMER(TIMER_REFRESHUI_ID, frmStatus::OnRefreshUITimer)
69
EVT_TIMER(TIMER_STATUS_ID, frmStatus::OnRefreshStatusTimer)
70
EVT_LIST_ITEM_SELECTED(CTL_STATUSLIST, frmStatus::OnSelStatusItem)
71
EVT_LIST_ITEM_DESELECTED(CTL_STATUSLIST, frmStatus::OnSelStatusItem)
73
EVT_TIMER(TIMER_LOCKS_ID, frmStatus::OnRefreshLocksTimer)
74
EVT_LIST_ITEM_SELECTED(CTL_LOCKLIST, frmStatus::OnSelLockItem)
75
EVT_LIST_ITEM_DESELECTED(CTL_LOCKLIST, frmStatus::OnSelLockItem)
77
EVT_TIMER(TIMER_XACT_ID, frmStatus::OnRefreshXactTimer)
78
EVT_LIST_ITEM_SELECTED(CTL_XACTLIST, frmStatus::OnSelXactItem)
79
EVT_LIST_ITEM_DESELECTED(CTL_XACTLIST, frmStatus::OnSelXactItem)
81
EVT_TIMER(TIMER_LOG_ID, frmStatus::OnRefreshLogTimer)
82
EVT_LIST_ITEM_SELECTED(CTL_LOGLIST, frmStatus::OnSelLogItem)
83
EVT_LIST_ITEM_DESELECTED(CTL_LOGLIST, frmStatus::OnSelLogItem)
85
EVT_CLOSE( frmStatus::OnClose)
51
#define statusList CTRL_LISTVIEW("lstStatus")
52
#define lockList CTRL_LISTVIEW("lstLocks")
53
#define xactList CTRL_LISTVIEW("lstXacts")
54
#define logList CTRL_LISTVIEW("lstLog")
55
#define slRate CTRL_SLIDER("slRate")
56
#define stRate CTRL_STATIC("stRate")
57
#define nbStatus CTRL_NOTEBOOK("nbStatus")
58
#define cbLogfiles CTRL_COMBOBOX("cbLogfiles")
59
#define btnRotateLog CTRL_BUTTON("btnRotateLog")
62
void frmStatus::OnCloseBtn(wxCommandEvent &event)
67
void frmStatus::OnClose(wxCloseEvent &event)
73
void ChangeButtonId(wxButton *btn, int id, const wxChar *txt)
80
frmStatus::frmStatus(frmMain *form, const wxString& _title, pgConn *conn)
86
wxWindowBase::SetFont(settings->GetSystemFont());
87
LoadResource(0, wxT("frmStatus"));
89
RestorePosition(-1, -1, 400, 240, 200, 150);
89
int frmStatus::cboToRate()
93
if (cbRate->GetValue() == _("Don't refresh"))
95
if (cbRate->GetValue() == _("1 second"))
97
if (cbRate->GetValue() == _("5 seconds"))
99
if (cbRate->GetValue() == _("10 seconds"))
101
if (cbRate->GetValue() == _("30 seconds"))
103
if (cbRate->GetValue() == _("1 minute"))
105
if (cbRate->GetValue() == _("5 minutes"))
107
if (cbRate->GetValue() == _("10 minutes"))
109
if (cbRate->GetValue() == _("30 minutes"))
111
if (cbRate->GetValue() == _("1 hour"))
118
wxString frmStatus::rateToCboString(int rate)
123
rateStr = _("Don't refresh");
125
rateStr = _("1 second");
127
rateStr = _("5 seconds");
129
rateStr = _("10 seconds");
131
rateStr = _("30 seconds");
133
rateStr = _("1 minute");
135
rateStr = _("5 minutes");
137
rateStr = _("10 minutes");
139
rateStr = _("30 minutes");
141
rateStr = _("1 hour");
147
frmStatus::frmStatus(frmMain *form, const wxString& _title, pgConn *conn) : pgFrame(NULL, _title)
149
dlgName = wxT("frmStatus");
161
logHasTimestamp = false;
162
logFormatKnown = false;
164
// Notify wxAUI which frame to use
165
manager.SetManagedWindow(this);
166
manager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_TRANSPARENT_DRAG | wxAUI_MGR_ALLOW_ACTIVE_PANE);
168
// Set different window's attributes
91
170
appearanceFactory->SetIcons(this);
96
logHasTimestamp = false;
97
logFormatKnown = false;
98
btnCancelSt = CTRL_BUTTON("btnCancelSt");
99
btnCancelLk = CTRL_BUTTON("btnCancelLk");
100
btnTerminateSt = CTRL_BUTTON("btnTerminateSt");
101
btnTerminateLk = CTRL_BUTTON("btnTerminateLk");
102
btnCommit = CTRL_BUTTON("btnCommit");
103
btnRollback = CTRL_BUTTON("btnRollback");
104
ChangeButtonId(btnCancelSt, wxID_CANCEL, _("Cancel"));
105
ChangeButtonId(btnCancelLk, wxID_CANCEL, _("Cancel"));
106
ChangeButtonId(btnTerminateSt, wxID_STOP, _("Terminate"));
107
ChangeButtonId(btnTerminateLk, wxID_STOP, _("Terminate"));
110
backend_pid=conn->GetBackendPID();
171
RestorePosition(-1, -1, 700, 500, 700, 500);
172
SetMinSize(wxSize(700,500));
173
wxWindowBase::SetFont(settings->GetSystemFont());
176
menuBar = new wxMenuBar();
178
fileMenu = new wxMenu();
179
fileMenu->Append(MNU_EXIT, _("E&xit\tAlt-F4"), _("Exit query window"));
181
menuBar->Append(fileMenu, _("&File"));
183
editMenu = new wxMenu();
184
editMenu->Append(MNU_COPY, _("&Copy\tCtrl-C"), _("Copy selected text to clipboard"), wxITEM_NORMAL);
186
menuBar->Append(editMenu, _("&Edit"));
188
viewMenu = new wxMenu();
189
viewMenu->Append(MNU_STATUSPAGE, _("&Activity\tCtrl-Alt-A"), _("Show or hide the activity tab."), wxITEM_CHECK);
190
viewMenu->Append(MNU_LOCKPAGE, _("&Locks\tCtrl-Alt-L"), _("Show or hide the locks tab."), wxITEM_CHECK);
191
viewMenu->Append(MNU_XACTPAGE, _("&Transactions\tCtrl-Alt-T"), _("Show or hide the transactions tab."), wxITEM_CHECK);
192
viewMenu->Append(MNU_LOGPAGE, _("Log&file\tCtrl-Alt-F"), _("Show or hide the logfile tab."), wxITEM_CHECK);
193
viewMenu->AppendSeparator();
194
viewMenu->Append(MNU_TOOLBAR, _("Tool&bar\tCtrl-Alt-B"), _("Show or hide the toolbar."), wxITEM_CHECK);
195
viewMenu->AppendSeparator();
196
viewMenu->Append(MNU_DEFAULTVIEW, _("&Default view\tCtrl-Alt-V"), _("Restore the default view."));
198
menuBar->Append(viewMenu, _("&View"));
200
wxMenu *helpMenu=new wxMenu();
201
helpMenu->Append(MNU_CONTENTS, _("&Help"), _("Open the helpfile."));
203
menuBar->Append(helpMenu, _("&Help"));
206
editMenu->Enable(MNU_COPY, false);
212
statusBar = CreateStatusBar(1);
213
SetStatusBarPane(-1);
216
toolBar = new ctlMenuToolbar(this, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_NODIVIDER);
217
toolBar->SetToolBitmapSize(wxSize(16, 16));
218
toolBar->AddTool(MNU_REFRESH, _("Refresh"), wxBitmap(readdata_xpm), _("Refresh"), wxITEM_NORMAL);
219
toolBar->AddSeparator();
220
toolBar->AddTool(MNU_COPY, _("Copy"), wxBitmap(clip_copy_xpm), _("Copy selected text to clipboard"), wxITEM_NORMAL);
221
toolBar->AddSeparator();
222
toolBar->AddTool(MNU_CANCEL, _("Cancel"), wxBitmap(query_cancel_xpm), _("Cancel query"), wxITEM_NORMAL);
223
toolBar->AddTool(MNU_TERMINATE, _("Terminate"), wxBitmap(terminate_backend_xpm), _("Terminate backend"), wxITEM_NORMAL);
224
toolBar->AddTool(MNU_COMMIT, _("Commit"), wxBitmap(storedata_xpm), _("Commit transaction"), wxITEM_NORMAL);
225
toolBar->AddTool(MNU_ROLLBACK, _("Rollback"), wxBitmap(delete_xpm), _("Rollback transaction"), wxITEM_NORMAL);
226
toolBar->AddSeparator();
227
cbLogfiles = new wxComboBox(toolBar, CTL_LOGCBO, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL,
228
wxCB_READONLY|wxCB_DROPDOWN);
229
toolBar->AddControl(cbLogfiles);
230
btnRotateLog = new wxButton(toolBar, CTL_ROTATEBTN, _("Rotate"));
231
toolBar->AddControl(btnRotateLog);
232
toolBar->AddSeparator();
233
cbRate = new ctlComboBoxFix(toolBar, CTL_RATECBO, wxDefaultPosition, wxSize(-1, -1), wxCB_READONLY|wxCB_DROPDOWN);
234
toolBar->AddControl(cbRate);
237
// Append items to cbo
238
cbRate->Append(_("Don't refresh"));
239
cbRate->Append(_("1 second"));
240
cbRate->Append(_("5 seconds"));
241
cbRate->Append(_("10 seconds"));
242
cbRate->Append(_("30 seconds"));
243
cbRate->Append(_("1 minute"));
244
cbRate->Append(_("5 minutes"));
245
cbRate->Append(_("10 minutes"));
246
cbRate->Append(_("30 minutes"));
247
cbRate->Append(_("1 hour"));
249
// Disable toolbar's items
250
toolBar->EnableTool(MNU_CANCEL, false);
251
toolBar->EnableTool(MNU_TERMINATE, false);
252
toolBar->EnableTool(MNU_COMMIT, false);
253
toolBar->EnableTool(MNU_ROLLBACK, false);
254
cbLogfiles->Enable(false);
255
btnRotateLog->Enable(false);
262
manager.AddPane(toolBar, wxAuiPaneInfo().Name(wxT("toolBar")).Caption(_("Tool bar")).ToolbarPane().Top().LeftDockable(false).RightDockable(false));
264
// Now load the layout
265
wxString perspective;
266
settings->Read(wxT("frmStatus/Perspective-") + VerFromRev(FRMSTATUS_PERSPECTIVE_VER), &perspective, FRMSTATUS_DEFAULT_PERSPECTIVE);
267
manager.LoadPerspective(perspective, true);
269
// Reset the captions for the current language
270
manager.GetPane(wxT("toolBar")).Caption(_("Tool bar"));
271
manager.GetPane(wxT("Activity")).Caption(_("Activity"));
272
manager.GetPane(wxT("Locks")).Caption(_("Locks"));
273
manager.GetPane(wxT("Transactions")).Caption(_("Transactions"));
274
manager.GetPane(wxT("Logfile")).Caption(_("Logfile"));
276
// Tell the manager to "commit" all the changes just made
279
// Sync the View menu options
280
viewMenu->Check(MNU_STATUSPAGE, manager.GetPane(wxT("Activity")).IsShown());
281
viewMenu->Check(MNU_LOCKPAGE, manager.GetPane(wxT("Locks")).IsShown());
282
viewMenu->Check(MNU_XACTPAGE, manager.GetPane(wxT("Transactions")).IsShown());
283
viewMenu->Check(MNU_LOGPAGE, manager.GetPane(wxT("Logfile")).IsShown());
284
viewMenu->Check(MNU_TOOLBAR, manager.GetPane(wxT("toolBar")).IsShown());
287
backend_pid = connection->GetBackendPID();
289
// Create the refresh timer (quarter of a second)
290
// This is a horrible hack to get around the lack of a
291
// PANE_ACTIVATED event in wxAUI.
292
refreshUITimer = new wxTimer(this, TIMER_REFRESHUI_ID);
293
refreshUITimer->Start(250);
300
frmStatus::~frmStatus()
302
// Delete the refresh timer
303
delete refreshUITimer;
305
// If the status window wasn't launched in standalone mode...
307
mainForm->RemoveFrame(this);
309
// Save the window's position
310
settings->Write(wxT("frmStatus/Perspective-") + VerFromRev(FRMSTATUS_PERSPECTIVE_VER), manager.SavePerspective());
314
// For each current page, save the slider's position and delete the timer
315
settings->Write(wxT("frmStatus/RefreshStatusRate"), statusRate);
317
settings->Write(wxT("frmStatus/RefreshLockRate"), locksRate);
319
if (viewMenu->IsEnabled(MNU_XACTPAGE))
321
settings->Write(wxT("frmStatus/RefreshXactRate"), xactRate);
328
if (viewMenu->IsEnabled(MNU_LOGPAGE))
330
settings->Write(wxT("frmStatus/RefreshLogRate"), logRate);
339
// If connection is still available, delete it
350
// Send RateChange event to launch each timer
351
wxScrollEvent nullScrollEvent;
352
if (viewMenu->IsChecked(MNU_STATUSPAGE))
354
currentPane = PANE_STATUS;
355
cbRate->SetValue(rateToCboString(statusRate));
356
OnRateChange(nullScrollEvent);
358
if (viewMenu->IsChecked(MNU_LOCKPAGE))
360
currentPane = PANE_LOCKS;
361
cbRate->SetValue(rateToCboString(locksRate));
362
OnRateChange(nullScrollEvent);
364
if (viewMenu->IsEnabled(MNU_XACTPAGE) && viewMenu->IsChecked(MNU_XACTPAGE))
366
currentPane = PANE_XACT;
367
cbRate->SetValue(rateToCboString(xactRate));
368
OnRateChange(nullScrollEvent);
370
if (viewMenu->IsEnabled(MNU_LOGPAGE) && viewMenu->IsChecked(MNU_LOGPAGE))
372
currentPane = PANE_LOG;
373
cbRate->SetValue(rateToCboString(logRate));
374
OnRateChange(nullScrollEvent);
378
wxCommandEvent nullEvent;
379
OnRefresh(nullEvent);
383
void frmStatus::OnClose(wxCloseEvent &event)
389
void frmStatus::OnExit(wxCommandEvent& event)
395
void frmStatus::AddStatusPane()
398
wxPanel *pnlActivity = new wxPanel(this);
401
wxFlexGridSizer *grdActivity = new wxFlexGridSizer(1, 1, 5, 5);
402
grdActivity->AddGrowableCol(0);
403
grdActivity->AddGrowableRow(0);
405
// Add the list control
406
wxListCtrl *lstStatus = new wxListCtrl(pnlActivity, CTL_STATUSLIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxSUNKEN_BORDER);
407
grdActivity->Add(lstStatus, 0, wxGROW, 3);
409
// Add the panel to the notebook
410
manager.AddPane(pnlActivity,
412
Name(wxT("Activity")).Caption(_("Activity")).
413
CaptionVisible(true).CloseButton(true).MaximizeButton(true).
414
Dockable(true).Movable(true));
417
pnlActivity->SetSizer(grdActivity);
418
grdActivity->Fit(pnlActivity);
420
// Add each column to the list control
421
statusList = (ctlListView*)lstStatus;
112
422
statusList->AddColumn(wxT("PID"), 35);
113
423
statusList->AddColumn(_("Database"), 70);
114
424
statusList->AddColumn(_("User"), 70);
115
425
if (connection->BackendMinimumVersion(8, 1))
117
427
statusList->AddColumn(_("Client"), 70);
118
statusList->AddColumn(_("Client start"), 80);
428
statusList->AddColumn(_("Client start"), 80);
121
430
if (connection->BackendMinimumVersion(7, 4))
122
431
statusList->AddColumn(_("Query start"), 50);
124
432
if (connection->BackendMinimumVersion(8, 3))
125
433
statusList->AddColumn(_("TX start"), 50);
434
statusList->AddColumn(_("Blocked by"), 35);
127
435
statusList->AddColumn(_("Query"), 500);
437
// Read statusRate configuration
438
settings->Read(wxT("frmStatus/RefreshStatusRate"), &statusRate, 10);
441
statusTimer = new wxTimer(this, TIMER_STATUS_ID);
445
void frmStatus::AddLockPane()
448
wxPanel *pnlLock = new wxPanel(this);
451
wxFlexGridSizer *grdLock = new wxFlexGridSizer(1, 1, 5, 5);
452
grdLock->AddGrowableCol(0);
453
grdLock->AddGrowableRow(0);
455
// Add the list control
456
wxListCtrl *lstLocks = new wxListCtrl(pnlLock, CTL_LOCKLIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxSUNKEN_BORDER);
457
grdLock->Add(lstLocks, 0, wxGROW, 3);
459
// Add the panel to the notebook
460
manager.AddPane(pnlLock,
462
Name(wxT("Locks")).Caption(_("Locks")).
463
CaptionVisible(true).CloseButton(true).MaximizeButton(true).
464
Dockable(true).Movable(true));
467
pnlLock->SetSizer(grdLock);
468
grdLock->Fit(pnlLock);
470
// Add each column to the list control
471
lockList = (ctlListView*)lstLocks;
129
472
lockList->AddColumn(wxT("PID"), 35);
130
473
lockList->AddColumn(_("Database"), 50);
131
474
lockList->AddColumn(_("Relation"), 50);
137
480
lockList->AddColumn(_("Granted"), 50);
138
481
if (connection->BackendMinimumVersion(7, 4))
139
482
lockList->AddColumn(_("Start"), 50);
141
483
lockList->AddColumn(_("Query"), 500);
143
if (connection->BackendMinimumVersion(8, 1))
145
xactList->AddColumn(wxT("XID"), 50);
146
xactList->AddColumn(_("Global ID"), 200);
147
xactList->AddColumn(_("Time"), 100);
148
xactList->AddColumn(_("Owner"), 50);
149
xactList->AddColumn(_("Database"), 50);
153
nbStatus->DeletePage(xactPage);
158
if (connection->BackendMinimumVersion(8, 0) &&
159
connection->HasFeature(FEATURE_FILEREAD))
161
logFormat = connection->ExecuteScalar(wxT("SHOW log_line_prefix"));
162
if (logFormat == wxT("unset"))
163
logFormat = wxEmptyString;
164
logFmtPos=logFormat.Find('%', true);
167
logFormatKnown = true;
168
else if (!logFmtPos && logFormat.Mid(logFmtPos, 2) == wxT("%t") && logFormat.Length() > 2)
170
logFormatKnown = true;
171
logHasTimestamp = true;
485
// Read locksRate configuration
486
settings->Read(wxT("frmStatus/RefreshLockRate"), &locksRate, 10);
489
locksTimer = new wxTimer(this, TIMER_LOCKS_ID);
493
void frmStatus::AddXactPane()
496
wxPanel *pnlXacts = new wxPanel(this);
499
wxFlexGridSizer *grdXacts = new wxFlexGridSizer(1, 1, 5, 5);
500
grdXacts->AddGrowableCol(0);
501
grdXacts->AddGrowableRow(0);
503
// Add the list control
504
wxListCtrl *lstXacts = new wxListCtrl(pnlXacts, CTL_LOCKLIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxSUNKEN_BORDER);
505
grdXacts->Add(lstXacts, 0, wxGROW, 3);
507
// Add the panel to the notebook
508
manager.AddPane(pnlXacts,
510
Name(wxT("Transactions")).Caption(_("Transactions")).
511
CaptionVisible(true).CloseButton(true).MaximizeButton(true).
512
Dockable(true).Movable(true));
515
pnlXacts->SetSizer(grdXacts);
516
grdXacts->Fit(pnlXacts);
519
xactList = (ctlListView*)lstXacts;
521
// We don't need this report if server release is less than 8.1
522
// GPDB doesn't have external global transactions.
523
// Perhaps we should use this display to show our
524
// global xid to local xid mappings?
525
if (!connection->BackendMinimumVersion(8, 1) || connection->GetIsGreenplum())
527
// manager.GetPane(wxT("Transactions")).Show(false);
528
lstXacts->InsertColumn(lstXacts->GetColumnCount(), _("Message"), wxLIST_FORMAT_LEFT, 800);
529
lstXacts->InsertItem(lstXacts->GetItemCount(), _("Prepared transactions not available on this server."));
530
lstXacts->Enable(false);
537
// Add each column to the list control
538
xactList->AddColumn(wxT("XID"), 50);
539
xactList->AddColumn(_("Global ID"), 200);
540
xactList->AddColumn(_("Time"), 100);
541
xactList->AddColumn(_("Owner"), 50);
542
xactList->AddColumn(_("Database"), 50);
544
// Read xactRate configuration
545
settings->Read(wxT("frmStatus/RefreshXactRate"), &xactRate, 10);
548
xactTimer = new wxTimer(this, TIMER_XACT_ID);
552
void frmStatus::AddLogPane()
555
wxPanel *pnlLog = new wxPanel(this);
558
wxFlexGridSizer *grdLog = new wxFlexGridSizer(1, 1, 5, 5);
559
grdLog->AddGrowableCol(0);
560
grdLog->AddGrowableRow(0);
562
// Add the list control
563
wxListCtrl *lstLog = new wxListCtrl(pnlLog, CTL_LOGLIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxSUNKEN_BORDER);
564
grdLog->Add(lstLog, 0, wxGROW, 3);
566
// Add the panel to the notebook
567
manager.AddPane(pnlLog,
568
wxAuiPaneInfo().Center().
569
Name(wxT("Logfile")).Caption(_("Logfile")).
570
CaptionVisible(true).CloseButton(true).MaximizeButton(true).
571
Dockable(true).Movable(true));
574
pnlLog->SetSizer(grdLog);
578
logList = (ctlListView*)lstLog;
580
// We don't need this report (but we need the pane)
581
// if server release is less than 8.0 or if server has no adminpack
582
if (!(connection->BackendMinimumVersion(8, 0) &&
583
connection->HasFeature(FEATURE_FILEREAD)))
585
if (connection->BackendMinimumVersion(8, 0))
586
frmHint::ShowHint(this, HINT_INSTRUMENTATION);
588
logList->InsertColumn(logList->GetColumnCount(), _("Message"), wxLIST_FORMAT_LEFT, 800);
589
logList->InsertItem(logList->GetItemCount(), _("Logs are not available for this server."));
590
logList->Enable(false);
596
// Add each column to the list control
597
logFormat = connection->ExecuteScalar(wxT("SHOW log_line_prefix"));
598
if (logFormat == wxT("unset"))
599
logFormat = wxEmptyString;
600
logFmtPos=logFormat.Find('%', true);
603
logFormatKnown = true; // log_line_prefix not specified.
604
else if (!logFmtPos && logFormat.Mid(logFmtPos, 2) == wxT("%t") && logFormat.Length() > 2) // Timestamp at end of log_line_prefix?
606
logFormatKnown = true;
607
logHasTimestamp = true;
609
else if (connection->GetIsGreenplum())
611
// Always %m|%u|%d|%p|%I|%X|:- (timestamp w/ millisec) for 3.2.x
612
// Usually CSV formatted for 3.3
613
logFormatKnown = true;
614
logHasTimestamp = true;
618
if (connection->GetIsGreenplum() && connection->BackendMinimumVersion(8,2,13))
620
// Be ready for GPDB CSV format log file
621
logList->AddColumn(_("Timestamp"), 120); // Room for millisecs
622
logList->AddColumn(_("Level"), 35);
623
logList->AddColumn(_("Log entry"), 400);
624
logList->AddColumn(_("Connection"), 45);
625
logList->AddColumn(_("Cmd number"), 48);
626
logList->AddColumn(_("Dbname"), 48);
627
logList->AddColumn(_("Segment"), 45);
629
else // Non-GPDB or non-CSV format log
172
632
logList->AddColumn(_("Timestamp"), 100);
175
634
if (logFormatKnown)
176
635
logList->AddColumn(_("Level"), 35);
178
637
logList->AddColumn(_("Log entry"), 800);
180
if (!connection->HasFeature(FEATURE_ROTATELOG))
181
btnRotateLog->Disable();
185
if (connection->BackendMinimumVersion(8, 0))
186
frmHint::ShowHint(this, HINT_INSTRUMENTATION);
188
nbStatus->DeletePage(logPage);
192
settings->Read(wxT("frmStatus/Refreshrate"), &rate, 1);
193
slRate->SetValue(rate);
199
msg.Printf(_("Stopped"));
202
msg.Printf(_("1 second"));
205
msg.Printf(_("%d seconds"), rate);
208
stRate->SetLabel(msg);
210
timer=new wxTimer(this, TIMER_ID);
212
btnCancelSt->Enable(false);
213
btnTerminateSt->Enable(false);
214
btnCancelLk->Enable(false);
215
btnTerminateLk->Enable(false);
216
if (connection->BackendMinimumVersion(8, 1))
218
btnCommit->Enable(false);
219
btnRollback->Enable(false);
226
frmStatus::~frmStatus()
228
mainForm->RemoveFrame(this);
231
settings->Write(wxT("frmStatus/Refreshrate"), slRate->GetValue());
245
wxCommandEvent nullEvent;
247
long rate = slRate->GetValue();
253
msg.Printf(_("Stopped"));
256
msg.Printf(_("1 second"));
259
msg.Printf(_("%d seconds"), rate);
262
stRate->SetLabel(msg);
265
timer->Start(rate*1000L);
267
OnRefresh(nullEvent);
271
void frmStatus::OnNotebookPageChanged(wxNotebookEvent& event)
274
wxCommandEvent buttonEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_REFRESH);
275
AddPendingEvent(buttonEvent);
277
// Disable the buttons. They'll get re-enabled if a suitable item is selected.
278
btnCancelSt->Enable(false);
279
btnTerminateSt->Enable(false);
280
btnCancelLk->Enable(false);
281
btnTerminateLk->Enable(false);
282
if (connection->BackendMinimumVersion(8, 1))
284
btnCommit->Enable(false);
285
btnRollback->Enable(false);
290
void frmStatus::OnRateChange(wxScrollEvent &event)
640
if (!connection->HasFeature(FEATURE_ROTATELOG))
641
btnRotateLog->Disable();
643
// Re-initialize variables
646
// Read logRate configuration
647
settings->Read(wxT("frmStatus/RefreshLogRate"), &logRate, 10);
650
logTimer = new wxTimer(this, TIMER_LOG_ID);
654
void frmStatus::OnCopy(wxCommandEvent& ev)
675
// This shouldn't happen.
676
// If it does, it's no big deal, we just need to get out.
681
row = list->GetFirstSelected();
685
for (col = 0; col < list->GetColumnCount(); col++)
687
text.Append(list->GetText(row, col) + wxT("\t"));
690
text.Append(wxT("\r\n"));
692
text.Append(wxT("\n"));
694
row = list->GetNextSelected(row);
697
if (text.Length() > 0 && wxTheClipboard->Open())
699
wxTheClipboard->SetData(new wxTextDataObject(text));
700
wxTheClipboard->Close();
705
void frmStatus::OnPaneClose(wxAuiManagerEvent& evt)
707
if (evt.pane->name == wxT("Activity"))
709
viewMenu->Check(MNU_STATUSPAGE, false);
712
if (evt.pane->name == wxT("Locks"))
714
viewMenu->Check(MNU_LOCKPAGE, false);
717
if (evt.pane->name == wxT("Transactions"))
719
viewMenu->Check(MNU_XACTPAGE, false);
723
if (evt.pane->name == wxT("Logfile"))
725
viewMenu->Check(MNU_LOGPAGE, false);
732
void frmStatus::OnToggleStatusPane(wxCommandEvent& event)
734
if (viewMenu->IsChecked(MNU_STATUSPAGE))
736
manager.GetPane(wxT("Activity")).Show(true);
737
cbRate->SetValue(rateToCboString(statusRate));
739
statusTimer->Start(statusRate*1000L);
743
manager.GetPane(wxT("Activity")).Show(false);
747
// Tell the manager to "commit" all the changes just made
752
void frmStatus::OnToggleLockPane(wxCommandEvent& event)
754
if (viewMenu->IsChecked(MNU_LOCKPAGE))
756
manager.GetPane(wxT("Locks")).Show(true);
757
cbRate->SetValue(rateToCboString(locksRate));
759
locksTimer->Start(locksRate*1000L);
763
manager.GetPane(wxT("Locks")).Show(false);
767
// Tell the manager to "commit" all the changes just made
772
void frmStatus::OnToggleXactPane(wxCommandEvent& event)
774
if (viewMenu->IsEnabled(MNU_XACTPAGE) && viewMenu->IsChecked(MNU_XACTPAGE))
776
manager.GetPane(wxT("Transactions")).Show(true);
777
cbRate->SetValue(rateToCboString(xactRate));
778
if (xactRate > 0 && xactTimer)
779
xactTimer->Start(xactRate*1000L);
783
manager.GetPane(wxT("Transactions")).Show(false);
788
// Tell the manager to "commit" all the changes just made
793
void frmStatus::OnToggleLogPane(wxCommandEvent& event)
795
if (viewMenu->IsEnabled(MNU_LOGPAGE) && viewMenu->IsChecked(MNU_LOGPAGE))
797
manager.GetPane(wxT("Logfile")).Show(true);
798
cbRate->SetValue(rateToCboString(logRate));
799
if (logRate > 0 && logTimer)
800
logTimer->Start(logRate*1000L);
804
manager.GetPane(wxT("Logfile")).Show(false);
809
// Tell the manager to "commit" all the changes just made
814
void frmStatus::OnToggleToolBar(wxCommandEvent& event)
816
if (viewMenu->IsChecked(MNU_TOOLBAR))
818
manager.GetPane(wxT("toolBar")).Show(true);
822
manager.GetPane(wxT("toolBar")).Show(false);
825
// Tell the manager to "commit" all the changes just made
830
void frmStatus::OnDefaultView(wxCommandEvent& event)
832
manager.LoadPerspective(FRMSTATUS_DEFAULT_PERSPECTIVE, true);
834
// Reset the captions for the current language
835
manager.GetPane(wxT("toolBar")).Caption(_("Tool bar"));
836
manager.GetPane(wxT("Activity")).Caption(_("Activity"));
837
manager.GetPane(wxT("Locks")).Caption(_("Locks"));
838
manager.GetPane(wxT("Transactions")).Caption(_("Transactions"));
839
manager.GetPane(wxT("Logfile")).Caption(_("Logfile"));
841
// tell the manager to "commit" all the changes just made
844
// Sync the View menu options
845
viewMenu->Check(MNU_TOOLBAR, manager.GetPane(wxT("toolBar")).IsShown());
846
viewMenu->Check(MNU_STATUSPAGE, manager.GetPane(wxT("Activity")).IsShown());
847
viewMenu->Check(MNU_LOCKPAGE, manager.GetPane(wxT("Locks")).IsShown());
848
viewMenu->Check(MNU_XACTPAGE, manager.GetPane(wxT("Transactions")).IsShown());
849
viewMenu->Check(MNU_LOGPAGE, manager.GetPane(wxT("Logfile")).IsShown());
853
void frmStatus::OnHelp(wxCommandEvent& event)
857
page=wxT("sql-commands");
859
if (connection->GetIsEdb())
860
DisplayHelp(page, HELP_ENTERPRISEDB);
862
DisplayHelp(page, HELP_POSTGRESQL);
866
void frmStatus::OnRateChange(wxCommandEvent &event)
894
// This shouldn't happen.
895
// If it does, it's no big deal, we just need to get out.
296
long rate = slRate->GetValue();
302
msg.Printf(_("Stopped"));
305
msg.Printf(_("1 second"));
308
msg.Printf(_("%d seconds"), rate);
311
stRate->SetLabel(msg);
315
904
timer->Start(rate*1000L);
322
void frmStatus::OnRefreshTimer(wxTimerEvent &event)
324
OnRefresh(*(wxCommandEvent*)&event);
328
void frmStatus::OnRefresh(wxCommandEvent &event)
331
// To avoid hammering the lock manager (and the network for that matter),
332
// only query for the required tab.
339
connection->ExecuteVoid(wxT("SET log_statement='none';"));
341
if (nbStatus->GetSelection() == 0)
345
pgSet *dataSet1=connection->ExecuteSet(wxT("SELECT * FROM pg_stat_activity ORDER BY procpid"));
348
statusList->Freeze();
349
statusBar->SetStatusText(_("Refreshing."));
350
while (!dataSet1->Eof())
352
pid=dataSet1->GetLong(wxT("procpid"));
354
if (pid != backend_pid)
358
while (row < statusList->GetItemCount())
360
itempid=StrToLong(statusList->GetItemText(row));
361
if (itempid && itempid < pid)
362
statusList->DeleteItem(row);
367
if (!itempid || itempid > pid)
369
statusList->InsertItem(row, NumToStr(pid), 0);
371
wxString qry=dataSet1->GetVal(wxT("current_query"));
374
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("datname")));
375
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("usename")));
377
if (connection->BackendMinimumVersion(8, 1))
379
wxString client=dataSet1->GetVal(wxT("client_addr")) + wxT(":") + dataSet1->GetVal(wxT("client_port"));
380
if (client == wxT(":-1"))
381
client = _("local pipe");
382
statusList->SetItem(row, colpos++, client);
384
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("backend_start")));
386
if (connection->BackendMinimumVersion(7, 4))
388
if (qry.IsEmpty() || qry == wxT("<IDLE>"))
389
statusList->SetItem(row, colpos++, wxEmptyString);
391
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("query_start")));
394
if (connection->BackendMinimumVersion(8, 3))
395
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("xact_start")));
397
statusList->SetItem(row, colpos, qry.Left(250));
400
dataSet1->MoveNext();
404
while (row < statusList->GetItemCount())
405
statusList->DeleteItem(row);
408
statusBar->SetStatusText(_("Done."));
414
while (row < statusList->GetItemCount())
416
long itempid=StrToLong(statusList->GetItemText(row));
417
if (itempid && itempid > pid)
418
statusList->DeleteItem(row);
423
else if (nbStatus->GetSelection() == 1)
428
if (connection->BackendMinimumVersion(8, 3))
431
wxT("(SELECT datname FROM pg_database WHERE oid = pgl.database) AS dbname, ")
432
wxT("pgl.relation::regclass AS class, ")
433
wxT("pg_get_userbyid(pg_stat_get_backend_userid(svrid)) as user, ")
434
wxT("pgl.virtualxid, pgl.virtualtransaction AS transaction, pg_stat_get_backend_pid(svrid) AS pid, pgl.mode, pgl.granted, ")
435
wxT("pg_stat_get_backend_activity(svrid) AS current_query, ")
436
wxT("pg_stat_get_backend_activity_start(svrid) AS query_start ")
437
wxT("FROM pg_stat_get_backend_idset() svrid, pg_locks pgl ")
438
wxT("WHERE pgl.pid = pg_stat_get_backend_pid(svrid) ")
439
wxT("ORDER BY pid;");
441
else if (connection->BackendMinimumVersion(7, 4))
444
wxT("(SELECT datname FROM pg_database WHERE oid = pgl.database) AS dbname, ")
445
wxT("pgl.relation::regclass AS class, ")
446
wxT("pg_get_userbyid(pg_stat_get_backend_userid(svrid)) as user, ")
447
wxT("pgl.transaction, pg_stat_get_backend_pid(svrid) AS pid, pgl.mode, pgl.granted, ")
448
wxT("pg_stat_get_backend_activity(svrid) AS current_query, ")
449
wxT("pg_stat_get_backend_activity_start(svrid) AS query_start ")
450
wxT("FROM pg_stat_get_backend_idset() svrid, pg_locks pgl ")
451
wxT("WHERE pgl.pid = pg_stat_get_backend_pid(svrid) ")
452
wxT("ORDER BY pid;");
457
wxT("(SELECT datname FROM pg_database WHERE oid = pgl.database) AS dbname, ")
458
wxT("pgl.relation::regclass AS class, ")
459
wxT("pg_get_userbyid(pg_stat_get_backend_userid(svrid)) as user, ")
460
wxT("pgl.transaction, pg_stat_get_backend_pid(svrid) AS pid, pgl.mode, pgl.granted, ")
461
wxT("pg_stat_get_backend_activity(svrid) AS current_query ")
462
wxT("FROM pg_stat_get_backend_idset() svrid, pg_locks pgl ")
463
wxT("WHERE pgl.pid = pg_stat_get_backend_pid(svrid) ")
464
wxT("ORDER BY pid;");
467
pgSet *dataSet2=connection->ExecuteSet(sql);
470
statusBar->SetStatusText(_("Refreshing."));
473
while (!dataSet2->Eof())
475
pid=dataSet2->GetLong(wxT("pid"));
477
if (pid != backend_pid)
481
while (row < lockList->GetItemCount())
483
itempid=StrToLong(lockList->GetItemText(row));
484
if (itempid && itempid < pid)
485
lockList->DeleteItem(row);
490
if (!itempid || itempid > pid)
492
lockList->InsertItem(row, NumToStr(pid), 0);
496
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("dbname")));
497
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("class")));
498
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("user")));
499
if (connection->BackendMinimumVersion(8, 3))
500
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("virtualxid")));
501
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("transaction")));
502
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("mode")));
504
if (dataSet2->GetVal(wxT("granted")) == wxT("t"))
505
lockList->SetItem(row, colpos++, _("Yes"));
507
lockList->SetItem(row, colpos++, _("No"));
509
wxString qry=dataSet2->GetVal(wxT("current_query"));
511
if (connection->BackendMinimumVersion(7, 4))
513
if (qry.IsEmpty() || qry == wxT("<IDLE>"))
514
lockList->SetItem(row, colpos++, wxEmptyString);
516
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("query_start")));
518
lockList->SetItem(row, colpos++, qry.Left(250));
523
dataSet2->MoveNext();
528
while (row < lockList->GetItemCount())
529
lockList->DeleteItem(row);
532
statusBar->SetStatusText(_("Done."));
538
while (row < lockList->GetItemCount())
540
long itempid=StrToLong(lockList->GetItemText(row));
541
if (itempid && itempid > pid)
542
lockList->DeleteItem(row);
547
else if (nbStatus->GetSelection() == xactPage)
551
wxString sql = wxT("SELECT * FROM pg_prepared_xacts");
553
pgSet *dataSet3=connection->ExecuteSet(sql);
556
statusBar->SetStatusText(_("Refreshing."));
559
while (!dataSet3->Eof())
561
long xid=dataSet3->GetLong(wxT("transaction"));
565
while (row < xactList->GetItemCount())
567
itemxid=StrToLong(xactList->GetItemText(row));
568
if (itemxid && itemxid < xid)
569
xactList->DeleteItem(row);
574
if (!itemxid || itemxid > xid)
576
xactList->InsertItem(row, NumToStr(xid), 0);
580
xactList->SetItem(row, colpos++, dataSet3->GetVal(wxT("gid")));
581
xactList->SetItem(row, colpos++, dataSet3->GetVal(wxT("prepared")));
582
xactList->SetItem(row, colpos++, dataSet3->GetVal(wxT("owner")));
583
xactList->SetItem(row, colpos++, dataSet3->GetVal(wxT("database")));
586
dataSet3->MoveNext();
910
void frmStatus::OnRefreshUITimer(wxTimerEvent &event)
914
refreshUITimer->Stop();
916
for (unsigned int i = 0; i < manager.GetAllPanes().GetCount(); i++)
918
wxAuiPaneInfo& pane = manager.GetAllPanes()[i];
920
if (pane.HasFlag(wxAuiPaneInfo::optionActive))
922
if (pane.name == wxT("Activity") && currentPane != PANE_STATUS)
924
OnSelStatusItem(evt);
926
if (pane.name == wxT("Locks") && currentPane != PANE_LOCKS)
930
if (pane.name == wxT("Transactions") && currentPane != PANE_XACT)
934
if (pane.name == wxT("Logfile") && currentPane != PANE_LOG)
941
refreshUITimer->Start(250);
945
void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event)
949
if (! viewMenu->IsChecked(MNU_STATUSPAGE))
960
statusBar->SetStatusText(wxT("Connection broken."));
968
wxCriticalSectionLocker lock(gs_critsect);
970
connection->ExecuteVoid(wxT("SET log_statement='none';SET log_duration='off';"),false);
973
pgSet *dataSet1=connection->ExecuteSet(wxT("SELECT *,(SELECT min(pid) FROM pg_locks l1 WHERE GRANTED AND relation IN (SELECT relation FROM pg_locks l2 WHERE l2.pid=procpid AND NOT granted)) AS blockedby FROM pg_stat_activity ORDER BY procpid"));
976
statusList->Freeze();
977
statusBar->SetStatusText(_("Refreshing status list."));
978
while (!dataSet1->Eof())
980
pid=dataSet1->GetLong(wxT("procpid"));
982
if (pid != backend_pid)
986
while (row < statusList->GetItemCount())
988
itempid=StrToLong(statusList->GetItemText(row));
989
if (itempid && itempid < pid)
990
statusList->DeleteItem(row);
995
if (!itempid || itempid > pid || row >= statusList->GetItemCount())
997
statusList->InsertItem(row, NumToStr(pid), 0);
999
wxString qry=dataSet1->GetVal(wxT("current_query"));
1002
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("datname")));
1003
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("usename")));
1005
if (connection->BackendMinimumVersion(8, 1))
1007
wxString client=dataSet1->GetVal(wxT("client_addr")) + wxT(":") + dataSet1->GetVal(wxT("client_port"));
1008
if (client == wxT(":-1"))
1009
client = _("local pipe");
1010
statusList->SetItem(row, colpos++, client);
1012
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("backend_start")));
1014
if (connection->BackendMinimumVersion(7, 4))
1016
if (qry.IsEmpty() || qry == wxT("<IDLE>"))
1017
statusList->SetItem(row, colpos++, wxEmptyString);
1019
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("query_start")));
1022
if (connection->BackendMinimumVersion(8, 3))
1023
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("xact_start")));
1025
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("blockedby")));
1026
statusList->SetItem(row, colpos, qry.Left(250));
1029
dataSet1->MoveNext();
1033
while (row < statusList->GetItemCount())
1034
statusList->DeleteItem(row);
1037
statusBar->SetStatusText(_("Done."));
1043
while (row < statusList->GetItemCount())
1045
long itempid=StrToLong(statusList->GetItemText(row));
1046
if (itempid && itempid > pid)
1047
statusList->DeleteItem(row);
1054
void frmStatus::OnRefreshLocksTimer(wxTimerEvent &event)
1058
if (! viewMenu->IsChecked(MNU_LOCKPAGE))
1063
statusTimer->Stop();
1069
statusBar->SetStatusText(wxT("Connection broken."));
1077
wxCriticalSectionLocker lock(gs_critsect);
1079
connection->ExecuteVoid(wxT("SET log_statement='none';SET log_duration='off';"),false);
1083
if (connection->BackendMinimumVersion(8, 3))
1085
sql = wxT("SELECT ")
1086
wxT("(SELECT datname FROM pg_database WHERE oid = pgl.database) AS dbname, ")
1087
wxT("pgl.relation::regclass AS class, ")
1088
wxT("pg_get_userbyid(pg_stat_get_backend_userid(svrid)) as user, ")
1089
wxT("pgl.virtualxid, pgl.virtualtransaction AS transaction, pg_stat_get_backend_pid(svrid) AS pid, pgl.mode, pgl.granted, ")
1090
wxT("pg_stat_get_backend_activity(svrid) AS current_query, ")
1091
wxT("pg_stat_get_backend_activity_start(svrid) AS query_start ")
1092
wxT("FROM pg_stat_get_backend_idset() svrid, pg_locks pgl ")
1093
wxT("WHERE pgl.pid = pg_stat_get_backend_pid(svrid) ")
1094
wxT("ORDER BY pid;");
1096
else if (connection->BackendMinimumVersion(7, 4))
1098
sql = wxT("SELECT ")
1099
wxT("(SELECT datname FROM pg_database WHERE oid = pgl.database) AS dbname, ")
1100
wxT("pgl.relation::regclass AS class, ")
1101
wxT("pg_get_userbyid(pg_stat_get_backend_userid(svrid)) as user, ")
1102
wxT("pgl.transaction, pg_stat_get_backend_pid(svrid) AS pid, pgl.mode, pgl.granted, ")
1103
wxT("pg_stat_get_backend_activity(svrid) AS current_query, ")
1104
wxT("pg_stat_get_backend_activity_start(svrid) AS query_start ")
1105
wxT("FROM pg_stat_get_backend_idset() svrid, pg_locks pgl ")
1106
wxT("WHERE pgl.pid = pg_stat_get_backend_pid(svrid) ")
1107
wxT("ORDER BY pid;");
1111
sql = wxT("SELECT ")
1112
wxT("(SELECT datname FROM pg_database WHERE oid = pgl.database) AS dbname, ")
1113
wxT("pgl.relation::regclass AS class, ")
1114
wxT("pg_get_userbyid(pg_stat_get_backend_userid(svrid)) as user, ")
1115
wxT("pgl.transaction, pg_stat_get_backend_pid(svrid) AS pid, pgl.mode, pgl.granted, ")
1116
wxT("pg_stat_get_backend_activity(svrid) AS current_query ")
1117
wxT("FROM pg_stat_get_backend_idset() svrid, pg_locks pgl ")
1118
wxT("WHERE pgl.pid = pg_stat_get_backend_pid(svrid) ")
1119
wxT("ORDER BY pid;");
1122
pgSet *dataSet2=connection->ExecuteSet(sql);
1125
statusBar->SetStatusText(_("Refreshing locks list."));
1128
while (!dataSet2->Eof())
1130
pid=dataSet2->GetLong(wxT("pid"));
1132
if (pid != backend_pid)
1136
while (row < lockList->GetItemCount())
1138
itempid=StrToLong(lockList->GetItemText(row));
1139
if (itempid && itempid < pid)
1140
lockList->DeleteItem(row);
1145
if (!itempid || itempid > pid || lockList->GetItemCount() == 0)
1147
lockList->InsertItem(row, NumToStr(pid), 0);
1151
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("dbname")));
1152
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("class")));
1153
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("user")));
1154
if (connection->BackendMinimumVersion(8, 3))
1155
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("virtualxid")));
1156
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("transaction")));
1157
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("mode")));
1159
if (dataSet2->GetVal(wxT("granted")) == wxT("t"))
1160
lockList->SetItem(row, colpos++, _("Yes"));
1162
lockList->SetItem(row, colpos++, _("No"));
1164
wxString qry=dataSet2->GetVal(wxT("current_query"));
1166
if (connection->BackendMinimumVersion(7, 4))
1168
if (qry.IsEmpty() || qry == wxT("<IDLE>"))
1169
lockList->SetItem(row, colpos++, wxEmptyString);
1171
lockList->SetItem(row, colpos++, dataSet2->GetVal(wxT("query_start")));
1173
lockList->SetItem(row, colpos++, qry.Left(250));
1177
dataSet2->MoveNext();
1182
while (row < lockList->GetItemCount())
1183
lockList->DeleteItem(row);
1186
statusBar->SetStatusText(_("Done."));
1192
while (row < lockList->GetItemCount())
1194
long itempid=StrToLong(lockList->GetItemText(row));
1195
if (itempid && itempid > pid)
1196
lockList->DeleteItem(row);
1203
void frmStatus::OnRefreshXactTimer(wxTimerEvent &event)
1207
if (! viewMenu->IsEnabled(MNU_XACTPAGE) || ! viewMenu->IsChecked(MNU_XACTPAGE) || !xactTimer)
1212
statusTimer->Stop();
1217
statusBar->SetStatusText(wxT("Connection broken."));
1225
wxCriticalSectionLocker lock(gs_critsect);
1227
connection->ExecuteVoid(wxT("SET log_statement='none';SET log_duration='off';"),false);
1230
wxString sql = wxT("SELECT * FROM pg_prepared_xacts");
1232
pgSet *dataSet3=connection->ExecuteSet(sql);
1235
statusBar->SetStatusText(_("Refreshing transactions list."));
1238
while (!dataSet3->Eof())
1240
long xid=dataSet3->GetLong(wxT("transaction"));
590
1244
while (row < xactList->GetItemCount())
591
xactList->DeleteItem(row);
594
statusBar->SetStatusText(_("Done."));
1246
itemxid=StrToLong(xactList->GetItemText(row));
1247
if (itemxid && itemxid < xid)
1248
xactList->DeleteItem(row);
1253
if (!itemxid || itemxid > xid)
1255
xactList->InsertItem(row, NumToStr(xid), 0);
1259
xactList->SetItem(row, colpos++, dataSet3->GetVal(wxT("gid")));
1260
xactList->SetItem(row, colpos++, dataSet3->GetVal(wxT("prepared")));
1261
xactList->SetItem(row, colpos++, dataSet3->GetVal(wxT("owner")));
1262
xactList->SetItem(row, colpos++, dataSet3->GetVal(wxT("database")));
1265
dataSet3->MoveNext();
1269
while (row < xactList->GetItemCount())
1270
xactList->DeleteItem(row);
1273
statusBar->SetStatusText(_("Done."));
1279
while (row < xactList->GetItemCount())
1281
long itempid=StrToLong(lockList->GetItemText(row));
1282
if (itempid && itempid > pid)
1283
xactList->DeleteItem(row);
1290
void frmStatus::OnRefreshLogTimer(wxTimerEvent &event)
1292
if (! viewMenu->IsEnabled(MNU_LOGPAGE) || ! viewMenu->IsChecked(MNU_LOGPAGE) || !logTimer)
1297
statusTimer->Stop();
1302
statusBar->SetStatusText(wxT("Connection broken."));
1310
wxCriticalSectionLocker lock(gs_critsect);
1312
connection->ExecuteVoid(wxT("SET log_statement='none';SET log_duration='off';"),false);
1314
if (connection->GetLastResultError().sql_state == wxT("42501"))
1316
// Don't have superuser privileges, so can't do anything with the log display
1318
cbLogfiles->Disable();
1319
btnRotateLog->Disable();
1320
manager.GetPane(wxT("Logfile")).Show(false);
1327
if (logDirectory.IsEmpty())
1330
logDirectory = connection->ExecuteScalar(wxT("SHOW log_directory"));
1331
if (connection->GetLastResultError().sql_state == wxT("42501"))
1333
// Don't have superuser privileges, so can't do anything with the log display
1335
cbLogfiles->Disable();
1336
btnRotateLog->Disable();
1337
manager.GetPane(wxT("Logfile")).Show(false);
1341
if (fillLogfileCombo())
1343
savedPartialLine.Clear();
1344
cbLogfiles->SetSelection(0);
1351
logDirectory = wxT("-");
1352
if (connection->BackendMinimumVersion(8, 3))
1353
logList->AppendItem(-1, _("logging_collector not enabled or log_filename misconfigured"));
1355
logList->AppendItem(-1, _("redirect_stderr not enabled or log_filename misconfigured"));
1356
cbLogfiles->Disable();
1357
btnRotateLog->Disable();
1361
if (logDirectory == wxT("-"))
1366
// check if the current logfile changed
1367
pgSet *set = connection->ExecuteSet(wxT("SELECT pg_file_length(") + connection->qtDbString(logfileName) + wxT(") AS len"));
1370
newlen = set->GetLong(wxT("len"));
597
1375
checkConnection();
600
while (row < lockList->GetItemCount())
602
long itempid=StrToLong(lockList->GetItemText(row));
603
if (itempid && itempid > pid)
604
lockList->DeleteItem(row);
609
else if (nbStatus->GetSelection() == logPage)
1378
if (newlen > logfileLength)
1380
statusBar->SetStatusText(_("Refreshing log list."));
1381
addLogFile(logfileName, logfileTimestamp, newlen, logfileLength, false);
1382
statusBar->SetStatusText(_("Done."));
1384
// as long as there was new data, the logfile is probably the current
1385
// one so we don't need to check for rotation
1391
wxString newDirectory = connection->ExecuteScalar(wxT("SHOW log_directory"));
1394
if (newDirectory != logDirectory)
1395
cbLogfiles->Clear();
1397
newfiles = fillLogfileCombo();
613
if (logDirectory.IsEmpty())
616
logDirectory = connection->ExecuteScalar(wxT("SHOW log_directory"));
617
if (fillLogfileCombo())
619
cbLogfiles->SetSelection(0);
626
logDirectory = wxT("-");
627
if (connection->BackendMinimumVersion(8, 3))
628
logList->AppendItem(-1, _("redirect_stderr not enabled or log_filename misconfigured"));
630
logList->AppendItem(-1, _("logging_collector not enabled or log_filename misconfigured"));
631
cbLogfiles->Disable();
632
btnRotateLog->Disable();
636
if (logDirectory == wxT("-"))
642
// check if the current logfile changed
643
pgSet *set = connection->ExecuteSet(wxT("SELECT pg_file_length(") + connection->qtDbString(logfileName) + wxT(") AS len"));
646
newlen = set->GetLong(wxT("len"));
654
if (newlen > logfileLength)
656
statusBar->SetStatusText(_("Refreshing."));
657
addLogFile(logfileName, logfileTimestamp, newlen, logfileLength, false);
658
statusBar->SetStatusText(_("Done."));
660
// as long as there was new data, the logfile is probably the current
661
// one so we don't need to check for rotation
667
wxString newDirectory = connection->ExecuteScalar(wxT("SHOW log_directory"));
670
if (newDirectory != logDirectory)
673
newfiles = fillLogfileCombo();
682
int pos = cbLogfiles->GetCount() - newfiles;
683
bool skipFirst = true;
687
addLogLine(_("pgadmin:Logfile rotated."), false);
688
wxDateTime *ts=(wxDateTime*)cbLogfiles->GetClientData(pos++);
1406
int pos = cbLogfiles->GetCount() - newfiles;
1407
bool skipFirst = true;
1411
addLogLine(_("pgadmin:Logfile rotated."), false);
1412
wxDateTime *ts=(wxDateTime*)cbLogfiles->GetClientData(pos++);
692
addLogFile(ts, skipFirst);
1415
addLogFile(ts, skipFirst);
1425
void frmStatus::OnRefresh(wxCommandEvent &event)
1429
OnRefreshStatusTimer(evt);
1430
OnRefreshLocksTimer(evt);
1431
OnRefreshXactTimer(evt);
1432
OnRefreshLogTimer(evt);
703
1436
void frmStatus::checkConnection()
705
1438
if (!connection->IsAlive())
709
statusBar->SetStatusText(_("Connection broken."));
1442
statusTimer->Stop();
1448
statusBar->SetStatusText(_("Connection broken."));
767
1525
read += strlen(raw);
1528
if (wxString(wxString(raw,wxConvLibc),wxConvUTF8).Len() > 0)
1529
str = line + wxString(wxString(raw,wxConvLibc),wxConvUTF8);
1531
str = line + wxTextBuffer::Translate(wxString(raw, set->GetConversion()), wxTextFileType_Unix);
770
wxString str = line + wxTextBuffer::Translate(wxString(raw, set->GetConversion()), wxTextFileType_Unix);
773
bool hasCr = (str.Right(1) == wxT("\n"));
775
wxStringTokenizer tk(str, wxT("\n"));
778
while (tk.HasMoreTokens())
780
str = tk.GetNextToken();
783
// could be truncated
787
if (tk.HasMoreTokens() || hasCr)
1537
wxString msgstr = _("The server log contains entries in multiple encodings and cannot be displayed by pgAdmin.");
1538
wxMessageBox(msgstr);
1544
// This will work for any DB using CSV format logs
1546
if (logHasTimestamp)
1548
// Right now, csv format logs from GPDB and PostgreSQL always start with a timestamp, so we count on that.
1550
// And the only reason we need to do that is to make sure we are in sync.
1552
// Bad things happen if we start in the middle of a
1553
// double-quoted string, as we would never find a correct line terminator!
1555
// In CSV logs, the first field must be a Timestamp, so must start with "2009" or "201" or "202" (at least for the next 20 years).
1556
if (str.length() > 4 && str.Left(4) != wxT("2009") && str.Left(3) != wxT("201") && str.Left(3) != wxT("202"))
1558
wxLogNotice(wxT("Log line does not start with timestamp: %s \n"), str.Mid(0,100).c_str());
1559
// Something isn't right, as we are not at the beginning of a csv log record.
1560
// We should never get here, but if we do, try to handle it in a smart way.
1561
str = str.Mid(str.Find(wxT("\n20"))+1); // Try to re-sync.
1565
CSVLineTokenizer tk(str);
1569
while (tk.HasMoreLines())
1574
str = tk.GetNextLine(partial);
1577
line = str; // Start of a log line, but not complete. Loop back, Read more data.
1581
// Some extra debug checking, assuming csv logs line start with timestamps.
1582
// Not really necessary, but it is good for debugging if something isn't right.
1583
if (logHasTimestamp)
1585
// The first field must be a Timestamp, so must start with "2009" or "201" or "202" (at least for the next 20 years).
1586
// This is just an extra check to make sure we haven't gotten out of sync with the log.
1587
if (str.length() > 5 && str.Left(4) != wxT("2009") && str.Left(3) != wxT("201") && str.Left(3) != wxT("202"))
1589
// BUG: We are out of sync on the log
1590
wxLogNotice(wxT("Log line does not start with timestamp: %s\n"), str.c_str());;
1592
else if (str.length() < 20)
1594
// BUG: We are out of sync on the log, or the log is garbled
1595
wxLogNotice(wxT("Log line too short: %s\n"), str.c_str());
1599
// Looks like we have a good complete CSV log record.
1600
addLogLine(str.Trim(), true, true);
1607
// Non-csv format log file
1609
bool hasCr = (str.Right(1) == wxT("\n"));
1611
wxStringTokenizer tk(str, wxT("\n"));
1615
while (tk.HasMoreTokens())
1617
str = tk.GetNextToken();
1620
// could be truncated
1625
if (tk.HasMoreTokens() || hasCr)
1626
addLogLine(str.Trim());
1635
savedPartialLine.clear();
794
1637
if (!line.IsEmpty())
1639
// We finished reading to the end of the log file, but still have some data left
1642
savedPartialLine = line; // Save partial log line for next read of the data file.
1646
addLogLine(line.Trim());
800
void frmStatus::addLogLine(const wxString &str, bool formatted)
1652
void frmStatus::addLogLine(const wxString &str, bool formatted, bool csv_log_format)
802
1654
int row=logList->GetItemCount();
803
1656
if (!logFormatKnown)
804
1657
logList->AppendItem(-1, str);
807
if (str.Find(':') < 0)
809
logList->InsertItem(row, wxEmptyString, -1);
810
logList->SetItem(row, (logHasTimestamp ? 2 : 1), str);
1658
else if ((!csv_log_format) && str.Find(':') < 0)
1660
// Must be a continuation of a previous line.
1661
logList->InsertItem(row, wxEmptyString, -1);
1662
logList->SetItem(row, 2, str);
1664
else if (!formatted)
1666
// Not from a log, from pgAdmin itself.
1667
logList->InsertItem(row, wxEmptyString, -1);
1668
logList->SetItem(row, 1, str.BeforeFirst(':'));
1669
logList->SetItem(row, 2, str.AfterFirst(':'));
1671
else // formatted log
1675
// Log is in CSV format (GPDB 3.3 and later, or Postgres if only csv log enabled)
1676
// In this case, we are always supposed to have a complete log line in csv format in str when called.
1678
if (logHasTimestamp && (str.Length() < 20 || (logHasTimestamp && (str[0] != wxT('2') || str[1] != wxT('0')))))
1680
// Log line too short or does not start with an expected timestamp...
1681
// Must be a continuation of the previous line or garbage,
1682
// or we are out of sync in our CSV handling.
1683
// We shouldn't ever get here.
1684
logList->InsertItem(row, wxEmptyString, -1);
1685
logList->SetItem(row, 2, str);
1689
CSVTokenizer tk(str);
1691
bool gpdb = connection->GetIsGreenplum();
1693
// Get the fields from the CSV log.
1694
wxString logTime = tk.GetNextToken();
1695
wxString logUser = tk.GetNextToken();
1696
wxString logDatabase = tk.GetNextToken();
1697
wxString logPid = tk.GetNextToken();
1699
wxString logSession;
1700
wxString logCmdcount;
1701
wxString logSegment;
1705
wxString logThread = tk.GetNextToken(); // GPDB specific
1706
wxString logHost = tk.GetNextToken();
1707
wxString logPort = tk.GetNextToken(); // GPDB (Postgres puts port with Host)
1708
wxString logSessiontime = tk.GetNextToken();
1709
wxString logTransaction = tk.GetNextToken();
1710
logSession = tk.GetNextToken();
1711
logCmdcount = tk.GetNextToken();
1712
logSegment = tk.GetNextToken();
1713
wxString logSlice = tk.GetNextToken();
1714
wxString logDistxact = tk.GetNextToken();
1715
wxString logLocalxact = tk.GetNextToken();
1716
wxString logSubxact = tk.GetNextToken();
1720
wxString logHost = tk.GetNextToken(); // Postgres puts port with Hostname
1721
logSession = tk.GetNextToken();
1722
wxString logLineNumber = tk.GetNextToken();
1723
wxString logPsDisplay = tk.GetNextToken();
1724
wxString logSessiontime = tk.GetNextToken();
1725
wxString logVXid = tk.GetNextToken();
1726
wxString logTransaction = tk.GetNextToken();
1729
wxString logSeverity = tk.GetNextToken();
1730
wxString logState = tk.GetNextToken();
1731
wxString logMessage = tk.GetNextToken();
1732
wxString logDetail = tk.GetNextToken();
1733
wxString logHint = tk.GetNextToken();
1734
wxString logQuery = tk.GetNextToken();
1735
wxString logQuerypos = tk.GetNextToken();
1736
wxString logContext = tk.GetNextToken();
1737
wxString logDebug = tk.GetNextToken();
1738
wxString logCursorpos = tk.GetNextToken();
1743
wxString logFunction = tk.GetNextToken(); // GPDB. Postgres puts func, file, and line together
1744
wxString logFile = tk.GetNextToken();
1745
wxString logLine = tk.GetNextToken();
1746
logStack = tk.GetNextToken(); // GPDB only.
1749
wxString logFuncFileLine = tk.GetNextToken();
1751
logList->InsertItem(row, logTime, -1); // Insert timestamp (with time zone)
1753
logList->SetItem(row, 1, logSeverity);
1755
// Display the logMessage, breaking it into lines
1756
wxStringTokenizer lm(logMessage,wxT("\n"));
1757
logList->SetItem(row, 2, lm.GetNextToken());
1759
logList->SetItem(row, 3, logSession);
1760
logList->SetItem(row, 4, logCmdcount);
1761
logList->SetItem(row, 5, logDatabase);
1762
if ((!gpdb) || (logSegment.length() > 0 && logSegment != wxT("seg-1")))
1764
logList->SetItem(row, 6, logSegment);
1768
// If we are reading the masterDB log only, the logSegment won't
1769
// have anything useful in it. Look in the logMessage, and see if the
1770
// segment info exists in there. It will always be at the end.
1771
if (logMessage.length() > 0 && logMessage[logMessage.length()-1] == wxT(')'))
1774
segpos = logMessage.Find(wxT("(seg"));
1776
segpos = logMessage.Find(wxT("(mir"));
1779
logSegment = logMessage.Mid(segpos+1);
1780
if (logSegment.Find(wxT(' ')) > 0)
1781
logSegment = logSegment.Mid(0,logSegment.Find(wxT(' ')));
1782
logList->SetItem(row, 6, logSegment);
1787
// The rest of the lines from the logMessage
1788
while (lm.HasMoreTokens())
1790
int controw=logList->GetItemCount();
1791
logList->InsertItem(controw, wxEmptyString, -1);
1792
logList->SetItem(controw, 2, lm.GetNextToken());
1796
wxStringTokenizer ld(logDetail,wxT("\n"));
1797
while (ld.HasMoreTokens())
1799
int controw=logList->GetItemCount();
1800
logList->InsertItem(controw, wxEmptyString, -1);
1801
logList->SetItem(controw, 2, ld.GetNextToken());
1805
wxStringTokenizer lh(logHint,wxT("\n"));
1806
while (lh.HasMoreTokens())
1808
int controw=logList->GetItemCount();
1809
logList->InsertItem(controw, wxEmptyString, -1);
1810
logList->SetItem(controw, 2, lh.GetNextToken());
1813
if (logDebug.length() > 0)
1815
wxString logState3 = logState.Mid(0,3);
1816
if (logState3 == wxT("426") || logState3 == wxT("22P") || logState3 == wxT("427")
1817
|| logState3 == wxT("42P") || logState3 == wxT("458")
1818
|| logMessage.Mid(0,9) == wxT("duration:") || logSeverity == wxT("FATAL") || logSeverity == wxT("PANIC"))
1820
// If not redundant, add the statement from the debug_string
1821
wxStringTokenizer lh(logDebug,wxT("\n"));
1822
if (lh.HasMoreTokens())
1824
int controw=logList->GetItemCount();
1825
logList->InsertItem(controw, wxEmptyString, -1);
1826
logList->SetItem(controw, 2, wxT("statement: ") + lh.GetNextToken());
1828
while (lh.HasMoreTokens())
1830
int controw=logList->GetItemCount();
1831
logList->InsertItem(controw, wxEmptyString, -1);
1832
logList->SetItem(controw, 2, lh.GetNextToken());
1838
if (logSeverity == wxT("PANIC") ||
1839
(logSeverity == wxT("FATAL") && logState != wxT("57P03") && logState != wxT("53300")))
1841
// If this is a severe error, add the stack trace.
1842
wxStringTokenizer ls(logStack,wxT("\n"));
1843
if (ls.HasMoreTokens())
1845
int controw=logList->GetItemCount();
1846
logList->InsertItem(controw, wxEmptyString, -1);
1847
logList->SetItem(controw, 1, wxT("STACK"));
1848
logList->SetItem(controw, 2, ls.GetNextToken());
1850
while (ls.HasMoreTokens())
1852
int controw=logList->GetItemCount();
1853
logList->InsertItem(controw, wxEmptyString, -1);
1854
logList->SetItem(controw, 2, ls.GetNextToken());
1859
else if (connection->GetIsGreenplum())
1861
// Greenplum 3.2 and before. log_line_prefix = "%m|%u|%d|%p|%I|%X|:-"
1863
wxString logSeverity;
1864
// Skip prefix, get message. In GPDB, always follows ":-".
1865
wxString rest = str.Mid(str.Find(wxT(":-"))+1) ;
1866
if (rest.Length() > 0 && rest[0] == wxT('-'))
1869
// Separate loglevel from message
1871
if (rest.Length() > 1 && rest[0] != wxT(' ') && rest.Find(':') > 0)
1873
logSeverity = rest.BeforeFirst(':');
1874
rest = rest.AfterFirst(':').Mid(2);
1877
wxString ts = str.BeforeFirst(logFormat.c_str()[logFmtPos+2]);
1878
if (ts.Length() < 20 || (logHasTimestamp && (ts.Left(2) != wxT("20") || str.Find(':') < 0)))
1880
// No Timestamp? Must be a continuation of a previous line?
1881
// Not sure if it is possible to get here.
1882
logList->InsertItem(row, wxEmptyString, -1);
1883
logList->SetItem(row, 2, rest);
1885
else if (logSeverity.Length() > 1)
1887
// Normal case: Start of a new log record.
1888
logList->InsertItem(row, ts, -1);
1889
logList->SetItem(row, 1, logSeverity);
1890
logList->SetItem(row, 2, rest);
1894
// Continuation of previous line
1895
logList->InsertItem(row, wxEmptyString, -1);
1896
logList->SetItem(row, 2, rest);
1901
// All Non-csv-format non-GPDB PostgreSQL systems.
816
1905
if (logHasTimestamp)