diff --git a/ctl/wxTopActivity.cpp b/ctl/wxTopActivity.cpp new file mode 100644 index 0000000..f524c18 --- /dev/null +++ b/ctl/wxTopActivity.cpp @@ -0,0 +1,1699 @@ + +#include "pgAdmin3.h" +#include "ctl/wxTopActivity.h" +#include +#include +#include "wx/regex.h" +#include "wx/display.h" +#include +#include "utils/FormatterSQL.h" +int s_pid_HIGHLIGH = -1; +std::vector sort_vec_map(const std::vector& src, int& sum) { + std::vector tmp(src.size()); + std::vector ok(src.size()); + for (int i = 0; i < src.size(); i++) { + int k = -1; + int max = -1; + for (int j = 0; j < src.size(); j++) { + if (ok[j] == 0 && src[j] > max) { max = src[j]; k = j; } + } + if (k == -1) break; + ok[k] = 1; + tmp[i] = k; + sum += src[k]; + } + return tmp; +}; + +//---------------------------------------------------------------------------- +// SimpleTransientPopup +//---------------------------------------------------------------------------- +wxIMPLEMENT_CLASS(SimpleTransientPopup, wxFrame); + +wxBEGIN_EVENT_TABLE(SimpleTransientPopup, wxFrame) +//EVT_MOUSE_EVENTS(SimpleTransientPopup::OnMouse) +EVT_SIZE(SimpleTransientPopup::OnSize) +EVT_SET_FOCUS(SimpleTransientPopup::OnSetFocus) +EVT_KILL_FOCUS(SimpleTransientPopup::OnKillFocus) +wxEND_EVENT_TABLE() + +SimpleTransientPopup::SimpleTransientPopup(wxWindow* parent, bool scrolled, wxTopActivity* small_ctl, wxPoint p,wxString title) + :wxFrame(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxFRAME_TOOL_WINDOW | wxCLOSE_BOX | wxTINY_CAPTION) +{ + m_panel = new wxScrolledWindow(this, wxID_ANY); + m_panel->SetBackgroundColour(*wxLIGHT_GREY); + + m_panel->Bind(wxEVT_MOTION, &SimpleTransientPopup::OnMouse, this); + WaitSample* w = NULL; + int agg, right_g; + w = small_ctl->getViewRange(agg, right_g); + wxSize top_sz = wxSize(1000, 500); + top = new wxTopActivity(m_panel, w, top_sz); + top->setViewRange(agg, right_g); + wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL); + topSizer->Add(top, 0, wxCENTRE | wxALL, 5); + int style = 0; + dvc = new topDataViewCtrl(m_panel, wxID_ANY, + wxDefaultPosition, + wxSize(1000, 155), + style, + top + ); + m_index_list_model = new MyIndexListModel(w); + dvc->AssociateModel(m_index_list_model.get()); + dvc->BuildColumn(0); + dvc->CalcRowsDataView(true, true); + m_taskTimer.Start(100); + m_taskTimer.Bind(wxEVT_TIMER, &SimpleTransientPopup::OnTimerEvent, this); + + topSizer->Add(dvc, 0, wxCENTRE | wxALL, 2); + //dvc->AppendTextColumn("Pid", 0); + //dvc->AppendTextColumn("String2", 1); + wxPoint posScreen; + wxSize sizeScreen; + const int displayNum = wxDisplay::GetFromPoint(p); + if (displayNum != wxNOT_FOUND) + { + const wxRect rectScreen = wxDisplay(displayNum).GetGeometry(); + posScreen = rectScreen.GetPosition(); + sizeScreen = rectScreen.GetSize(); + } + else // outside of any display? + { + // just use the primary one then + posScreen = wxPoint(0, 0); + sizeScreen = wxGetDisplaySize(); + } + if (p.x + top_sz.x > sizeScreen.x) p.x = sizeScreen.x - top_sz.x - 20; + if (p.y + top_sz.y > sizeScreen.y) p.y = sizeScreen.y - top_sz.y - 20; + Move(p); + if (scrolled) + { + // Add a big window to ensure that scrollbars are shown when we set the + // panel size to a lesser size below. + topSizer->Add(new wxPanel(m_panel, wxID_ANY, wxDefaultPosition, + wxSize(600, 900))); + } + + m_panel->SetSizer(topSizer); + if (scrolled) + { + // Set the fixed size to ensure that the scrollbars are shown. + m_panel->SetSize(300, 300); + + // And also actually enable them. + m_panel->SetScrollRate(10, 10); + } + else + { + // Use the fitting size for the panel if we don't need scrollbars. + topSizer->Fit(m_panel); + } + + SetClientSize(m_panel->GetSize()); +} + +SimpleTransientPopup::~SimpleTransientPopup() +{ + s_pid_HIGHLIGH = -1; +} + + + + +void SimpleTransientPopup::OnSize(wxSizeEvent& event) +{ + //wxLogMessage("%p SimpleTransientPopup::OnSize", this); + event.Skip(); +} + +void SimpleTransientPopup::OnSetFocus(wxFocusEvent& event) +{ + //wxLogMessage("%p SimpleTransientPopup::OnSetFocus", this); + //event.Skip(); +} + +void SimpleTransientPopup::OnKillFocus(wxFocusEvent& event) +{ + //wxLogMessage("%p SimpleTransientPopup::OnKillFocus", this); + //event.Skip(); +} +void SimpleTransientPopup::OnClose(wxCommandEvent& event) +{ + //wxLogMessage("%p SimpleTransientPopup::OnKillFocus", this); + //event.Skip(); + //dvc->Unbind() + m_panel->Unbind(wxEVT_MOTION, &SimpleTransientPopup::OnMouse, this); + m_taskTimer.Stop(); + m_taskTimer.Unbind(wxEVT_TIMER, &SimpleTransientPopup::OnTimerEvent, this); + Close(true); +} + +void SimpleTransientPopup::OnMouse(wxMouseEvent& event) +{ + wxColour colour(*wxLIGHT_GREY); + if (event.Dragging() && event.LeftIsDown() && !dragg) { mouseDownPos_ = event.GetPosition(); dragg = true; } + + if (event.Dragging() && event.LeftIsDown()) + { + if (mouseDownPos_ != event.GetPosition()) { + const auto screenPosCurrent = ClientToScreen(mouseDownPos_); + auto wp = ClientToScreen(event.GetPosition()) - screenPosCurrent; + auto w = GetPosition() + wp; + Move(w); + } + } + if (!event.LeftIsDown()) dragg = false; + event.Skip(); +} +void SimpleTransientPopup::OnTimerEvent(wxTimerEvent& pEvent) +{ + bool isf = dvc->GetColumnPosition(dvc->GetColumn(0)) == 0;//"PID"; + if (dvc->CalcRowsDataView(false, isf)) + this->Refresh(); + top->Refresh(); +} + + + +BEGIN_EVENT_TABLE(wxTopActivity, wxPanel) + +EVT_MOTION(wxTopActivity::mouseMoved) +EVT_LEFT_DOWN(wxTopActivity::mouseDown) +EVT_LEFT_UP(wxTopActivity::mouseReleased) +EVT_RIGHT_UP(wxTopActivity::mouseReleased) +EVT_LEAVE_WINDOW(wxTopActivity::mouseLeftWindow) +EVT_KEY_DOWN(wxTopActivity::keyPressed) +EVT_KEY_UP(wxTopActivity::keyReleased) +EVT_SIZE(wxTopActivity::resize) +EVT_MOUSEWHEEL(wxTopActivity::mouseWheelMoved) + +// catch paint events +EVT_PAINT(wxTopActivity::paintEvent) +EVT_ERASE_BACKGROUND(wxTopActivity::OnEraseBackground) + +END_EVENT_TABLE() + + +wxTopActivity::wxTopActivity(wxWindow* parent, WaitSample* WS, wxSize sz) : + wxControl(parent, wxID_ANY) +{ + ws = WS; + m_title = "TOP activity"; + SetBackgroundStyle(wxBG_STYLE_PAINT); + SetMinSize(sz); + SetSize(sz); + setsize = sz; + + if (sz.GetHeight() < 150) { + SetName("wxTopActivitySmall"); + } + else { + SetName("wxTopActivityBig"); + } + + m_simplePopup = NULL; +} +void wxTopActivity::SetFilter(long long qid) { + if (qid != -1) { + unsigned long long ull = qid; + int h = ull >> 32; + int l = ull & 0xFFFFFFFF; + m_filter_detail = wxString::Format("%llx", ull); + m_qid_filter = qid; + } + else { + m_filter_detail = wxEmptyString; + m_qid_filter = -1; + } + m_regroup = true; + Refresh(); + +} +void wxTopActivity::render(wxDC& dc) +{ + wxColour c; + dc.SetBrush(*wxGREY_BRUSH); + // wxRect r=dc.GetWindow()->GetClientRect(); + + wxRect r = GetClientRect(); + wxSize sz = r.GetSize(); + //dc.DrawRectangle(0, 0, r.width, r.height); + dc.DrawRectangle(0, 0, sz.x, sz.y); + int VERT_SPC = 3; + wxSize time_sz = dc.GetTextExtent("00:00"); + wxSize title_sz; + int ypos = 2; + int YaxisWidth = 50; + int LegengWidth = 140; + int xw = sz.x - YaxisWidth - LegengWidth; + int btl_y = 0; + if (xw > 100 && sz.y > 300) + { + wxDCFontChanger nfont(dc, dc.GetFont().Bold()); + wxString tit = m_title + wxString::Format(" [period: %d s]", m_agg_int / 1000); + title_sz = dc.GetTextExtent(tit); + wxSize dp = dc.GetTextExtent(m_filter_detail); + wxPoint p; + p.y = ypos; + p.x = sz.x / 2 - (title_sz.x + dp.x) / 2; + wxRect dpr(p.x + title_sz.x, p.y, dp.GetWidth(), dp.GetHeight()); + if (dpr.Contains(mouse) && m_click == 1) { + // remove filter_detail + m_click = 0; + m_filter_detail = wxEmptyString; + m_qid_filter = -1; + m_regroup = true; + return; + } + dc.DrawText(tit + m_filter_detail, p); + ypos += title_sz.y + VERT_SPC; + // button line + btl_y = sz.y - ypos - time_sz.y - VERT_SPC; + } + else { + YaxisWidth = 0; + LegengWidth = 0; + ypos = 0; + xw = sz.x; + btl_y = sz.y; + if (m_click == 1) { + //delete m_simplePopup; + wxPoint pp(20, 20); + wxPoint pos = this->GetParent()->ClientToScreen(pp); + wxWindow* f = this->GetParent()->FindWindowByName("wxTopActivityBig", this->GetParent()); + if (f == NULL) { + wxString tit = "TopActivity "; + wxString s = this->GetParent()->GetParent()->GetLabel(); + //wxString s2 = this->GetParent()->GetParent()->GetName(); + m_simplePopup = new SimpleTransientPopup(this->GetParent(), false, this, pos,tit+s); + //wxWindow* btn = (wxWindow*)event.GetEventObject(); + //m_simplePopup->Move(pos); + //m_simplePopup->Position(pos, sz); + //wxLogMessage("%p Simple Popup Shown pos(%d, %d) size(%d, %d)", m_simplePopup, pos.x, pos.y, sz.x, sz.y); + if (m_simplePopup) m_simplePopup->Show(); + } + else { + f->SetFocus(); + } + + } + } + + // Graph Area + + wxRect a(YaxisWidth, ypos, xw, btl_y); + m_area = a; + int max_label = xw / time_sz.x; + int msLen = ws->GetInterval(0, -1); + if (msLen == 0) return; + int width_sample = 2; + int needGrpMax = a.width / width_sample; + int realGrp = 0; + int tmp = ws->GetHomeInterval(-1, m_agg_int); + if (m_lastInterval != tmp || m_regroup) { + if (m_lastInterval != tmp && m_lastInterval == m_RightTime) + m_RightTime = tmp; // update last position + realGrp = ws->GetGroupingData(m_RightTime, needGrpMax, m_agg_int, m_filter + (m_filter_detail.IsEmpty() ? "" : "@" + m_filter_detail + ";"), seriosName, xAxis, yAxis, val, colors); + m_count_wait = ws->GetCountWaits(); + m_fix_detail_idx = -1; + m_lastInterval = tmp; + m_regroup = false; + m_sumtotal.clear(); + // calc sum + for (size_t j = 0; j < m_count_wait; j++) // serios group + { + int Yv = val[0][j]; + if (Yv < 0) continue; + int sum = 0; + for (size_t i = 0; i < val.size(); i++) + { + sum += val[i][j]; // vertical sum + } + wxString n = ws->GetName(j, WAIT_FULL); + m_sumtotal.emplace(n, sum); + wxString g = n.BeforeFirst(':'); + if (g.IsEmpty()) continue; + if (m_sumtotal.find(g) != m_sumtotal.end()) { + m_sumtotal[g] += sum; + } + else m_sumtotal[g] = sum; + } + + // title info + std::stack s; + bool all_remove = true; + int cnt_rem = 0; + m_title_i.clear(); + for (int i = seriosName.GetCount() - 1; i >= 0; i--) + { + wxString name = seriosName[i]; + title_info info; + info.down_line = false; + info.remove = false; + if (name[0] == ' ') { + name = name.substr(2); + info.iner = true; + info.title = name; + all_remove = false; + } + else if (name.StartsWith("--")) { // remove individual wait + name = name.substr(2); + info.iner = true; + info.title = name; + info.remove = true; + cnt_rem++; + } + else if (name[0] == '-') { // remove group + name = name.substr(1); + info.iner = false; + info.title = name; + info.remove = true; + all_remove = true; + } + else { + info.title = name; + info.iner = false; + info.remove = all_remove; + info.down_line = (!all_remove) && cnt_rem > 0; + } + s.push(info); + if (info.iner == false) { + if (m_collapse.find(name) != m_collapse.end()) m_collapse.emplace(name, 0); + wxString fn; + wxString grp_name = name; + long long w_sum = 0; + int grp_total = m_sumtotal[name]; + int start = m_title_i.size() + 1; + while (!s.empty()) + { + m_title_i.push_back(s.top()); + s.pop(); + int i = m_title_i.size() - 1; + if (m_sumtotal.find(m_title_i[i].title) == m_sumtotal.end()) fn = grp_name + ':' + m_title_i[i].title; + else fn = m_title_i[i].title; + m_title_i[i].total = m_sumtotal[fn]; + } + all_remove = true; + cnt_rem = 0; + // sort buuble + for (int j = 1; j < m_title_i.size() - start; j++) { + bool exit = true; + for (int i = start; i <= m_title_i.size() - j - 1; i++) { + if (m_title_i[i].total < m_title_i[i + 1].total) { + info = m_title_i[i]; + m_title_i[i] = m_title_i[i + 1]; + m_title_i[i + 1] = info; + exit = false; + } + } + if (exit) break; + } + + } + } + + + } + else { + realGrp = val.size(); + } + width_sample = a.width / realGrp; + if (width_sample < 2) width_sample = 2; + // legend + wxRect t(a.x + a.width + 5, a.y, sz.x - (a.x + a.width + 5 + 5), a.height); + + //dc.DrawRectangle(t.x, t.y, t.width, t.height); + int yy = t.y + 3; + int _maxx = 0; + wxPoint p; + wxRect r1(t.x, a.y, t.width - 20, 0); // mouse control + wxRect grp; + wxString grp_name; + int iscollapse = 0; + int total = 0; + for (int i = 0; i < m_title_i.size() && LegengWidth>0; i++) + { + + title_info info = m_title_i[i]; + + wxSize _sz; + wxString name = info.title; + wxFont f = dc.GetFont(); + int addspc = 0; + long long w_sum = 0; + wxString fn; + wxString tpr; + if (info.iner) { + if (iscollapse == 0) continue; + f.SetPointSize(f.GetPointSize() - 1); + addspc = 0; + if (info.total == 0) w_sum = -1; + else + w_sum = 100 * info.total / total; + + if (m_sumtotal.find(name) == m_sumtotal.end()) fn = grp_name + ':' + name; + else fn = name; + + } + else { + long cl = ws->GetColorByWaitName(name); + c.Set(cl); + dc.SetBrush(c); + dc.DrawRectangle(t.x + 3, yy, time_sz.GetHeight(), time_sz.GetHeight()); + iscollapse = m_collapse[name]; + grp_name = name; + total = info.total; + if (info.total != 0) tpr = wxString::Format("%.1fs", (float)info.total / 1000.0); + } + { + wxDCFontChanger nfont(dc, f); + _sz = dc.GetTextExtent(name); + wxSize dp = dc.GetTextExtent(tpr); + p.y = yy; + p.x = t.x + time_sz.GetHeight() + 8; + wxPoint pdp(t.x + t.width - dp.GetWidth() - 3, p.y); + + r1.y = p.y; + r1.x = p.x; + r1.height = _sz.GetHeight() + 1; + wxString pr = wxString::Format("%d", (int)w_sum); + wxPoint p3(t.x + 2, p.y); + if (w_sum > 0) dc.DrawText(pr, p3); + if (r1.Contains(mouse)) { + wxDCFontChanger nfont(dc, f.Bold()); + dc.DrawText(name, p); + if (!tpr.IsEmpty()) dc.DrawText(tpr, pdp); + if (m_click == 1) { // LeftUp + if (info.iner) { + m_title_i[i].remove = !info.remove; + m_regroup = true; + if (info.remove) m_filter.Replace("-" + fn + ";", ""); + else m_filter += "-" + fn + ";"; + + } + else { + int vv = m_collapse[name]; + if (vv == 0) vv++; else vv--; + m_collapse[name] = vv; + } + m_click = 0; + return; + } + } + else { + dc.DrawText(name, p); + if (!tpr.IsEmpty()) dc.DrawText(tpr, pdp); + } + + } + if (info.remove) { + wxPoint p1(p.x, p.y + _sz.y / 2 + 1); + wxPoint p2(p.x + _sz.GetWidth(), p.y + _sz.y / 2 + 1); + dc.DrawLine(p1, p2); + } + if (info.down_line) { + wxPoint p1(p.x, p.y + _sz.y); + wxPoint p2(p.x + _sz.GetWidth(), p.y + _sz.y); + dc.DrawLine(p1, p2); + } + yy += _sz.y + 1; + if (_maxx < _sz.GetWidth()) _maxx = _sz.GetWidth(); + } + dc.SetBrush(*wxTRANSPARENT_BRUSH); + //t.width = _maxx + p.x + 3 -t.x; + t.height = yy - t.y + 3; + if (LegengWidth > 0) dc.DrawRectangle(t.x, t.y, t.width, yy - t.y + 3); + + dc.SetBrush(*wxGREY_BRUSH); + dc.SetPen(*wxBLACK_PEN); + dc.DrawRectangle(a.x, a.y, a.width, a.height); + wxTimeSpan maxY = yAxis[0]; + wxLongLong t_maxYms = maxY.GetMilliseconds(); + int t_maxY = t_maxYms.GetLo(); + //Yaxis + int nlab = a.height / time_sz.GetHeight(); + nlab = nlab / 2; + int delta = t_maxY / (nlab == 0 ? 99999 : nlab); + int y = a.y + 1; + int x = a.x - 1; + float fl = 0; + + for (int i = 0; i <= nlab && LegengWidth > 0; i++) + { + wxString txt = wxString::Format("%.2f", fl / 1000); + wxSize dx = dc.GetTextExtent(txt); + y = a.y + a.height - i * (a.height / nlab); + dc.DrawText(txt, x - dx.x - 4, y - dx.y / 2); + fl += delta; + dc.SetPen(*wxBLACK_PEN); + wxPoint p1(a.x, y); + wxPoint p2(a.x - 3, y); + dc.DrawLine(p1, p2); + { + wxDCPenChanger npen(dc, wxPen(*wxLIGHT_GREY, 1, wxPENSTYLE_LONG_DASH)); + p2.x = a.x + a.width - 2; + p1.x += 1; + if (i != 0) dc.DrawLine(p1, p2); + } + } + + int cx = a.x + a.width - 1; + int cy = a.y + a.height - 1; + std::vector down_poly; + // xAxis + int xAareaW = time_sz.GetWidth() + 24; + int Nlabel = (a.width - 1) / xAareaW; + int stepx = (xAareaW / width_sample); + if (stepx == 0) stepx = 1; + dc.SetPen(*wxBLACK_PEN); + wxRect rd; + wxPoint ptest; + for (int i = stepx / 2; i < xAxis.size() && LegengWidth > 0; i = i + stepx) + { + wxDateTime t = xAxis.at(i); + //t.Add(wxTimeSpan(0, 0, 0, m_agg_int)); + wxString labeltext = t.Format("%H:%M"); + //Tick + wxPoint p1(cx - i * width_sample, cy + 1); + wxPoint p2(cx - i * width_sample, cy + 3); + dc.DrawLine(p1, p2); + //label + p2.x = p2.x - time_sz.GetWidth() / 2; + p2.y += 1; + ptest = p2; + ptest.x = p2.x + time_sz.GetWidth(); + if (!rd.Contains(ptest)) { + dc.DrawText(labeltext, p2); + rd.x = p2.x; rd.y = p2.y; rd.width = time_sz.GetWidth(); rd.height = time_sz.GetHeight(); + } + + } + + // Area + dc.SetPen(*wxTRANSPARENT_PEN); + for (size_t i = 0; i < val.size(); i++) + { + down_poly.push_back(wxPoint(cx, cy)); + cx -= width_sample; + } + if (down_poly.size() < 2) down_poly.push_back(wxPoint(cx, cy)); + //down_poly.push_back(wxPoint(cx,cy)); + //float koef=(float)t_maxY /(float)(a.height - 10) ; + int vert_line = m_agg_int; + float koef = (float)(a.height - 2) / (float)t_maxY; + wxPoint selP(0, 0); + int selIdx = -1; + for (size_t j = m_count_wait; j < val[0].size(); j++) // serios group + { + int Yv = val[0][j]; + if (Yv < 0) continue; + + int ii = down_poly.size() - 1; + ii = 0; + std::vector up_poly; + wxPoint p; + for (size_t i = 0; i < val.size(); i++) + { + int Yv = val[i][j]; + if (Yv < 0) continue; + int pixY = Yv * koef; + p = down_poly[i]; + p.y = p.y - pixY; + up_poly.push_back(wxPoint(p)); + if (width_sample > 19 && i > 0) { + wxDCPenChanger npen(dc, wxPen(*wxLIGHT_GREY, 1, wxPENSTYLE_DOT_DASH)); + dc.DrawLine(wxPoint(p.x, down_poly[i].y - 1), wxPoint(p.x, a.y + 1)); + } + wxPoint dis = mouse - p; + if ((dis.x * dis.x + dis.y * dis.y) < 20 && LegengWidth > 0) { + if (m_fix_detail_idx == -1) { + selP = p; + selIdx = i; + } + } + } + vert_line = -1; + if (up_poly.size() < 2) { + up_poly.push_back(wxPoint(down_poly[1].x, p.y)); + } + std::vector poly(down_poly.size()); + for (int i = 0; i < poly.size(); i++) + { + poly[i] = down_poly[i]; + } + for (int i = up_poly.size() - 1; i >= 0; i--) + { + poly.push_back(up_poly[i]); + } + long cl = colors[j]; + c.Set(cl); + dc.SetBrush(c); + dc.DrawPolygon(poly.size(), poly.data()); + for (int i = 0; i < down_poly.size(); i++) + { + down_poly[i] = up_poly[i]; + } + //break; + } + if (LegengWidth > 0) paintSelRange(dc, width_sample); + + + // select Point + if (selIdx != -1 || m_fix_detail_idx != -1) { + if (m_fix_detail_idx == -1) { + dc.SetPen(*wxWHITE_PEN); + dc.SetBrush(*wxBLACK_BRUSH); + dc.DrawCircle(selP, 3); + if (m_click == 1) { + m_fix_detail_idx = selIdx; + m_fix_pos = selP; + m_click = 0; + } + } + else { + selIdx = m_fix_detail_idx; + selP = m_fix_pos; + } + /// Detail panel + auto dt = xAxis[selIdx]; + int endt = ws->d_time(dt.GetValue().GetValue()); + //endt -= m_agg_int; + std::vector* smp = ws->GetSamples(); + int start_t = ws->GetHomeInterval(m_RightTime, m_agg_int) - selIdx * m_agg_int; + int ps = ws->getPositionByTime(start_t); + + Sample sa; + int sz2 = smp->size(); + std::map qid_wait_pid_count; // [qid]=pid1,pid2 + std::map qid_wait_pid_BG_sum; // [qid]=pid1,pid2 + std::map qid_wait_pid_FG_sum; // [qid]=pid1,pid2 + + std::map pid_btype; + // quid -> idx + // быстрый поиск + //std::map map_qid_idx; + std::vector qid_; + //std::vector qid_wait_id; + // сумма ожидания для каждого idx + std::vector> qid_wait_id_SUM; + //std::vector> qid_wait_id; + std::vector sum_bg(m_count_wait); + std::vector sum_all(m_count_wait); + while (ps < sz2) + { + sa = smp->at(ps++); + if (sa.btime >= (start_t + m_agg_int)) break; + long long q = sa.qid; + if (m_qid_filter != -1 && m_qid_filter != q) continue; + int idx = -1; + for (int i = 0; i < qid_.size(); i++) { + if (qid_[i] == q) { idx = i; break; } + } + if (idx == -1) { + qid_.push_back(q); + idx = qid_.size() - 1; + std::vector wait(m_count_wait); + qid_wait_id_SUM.push_back(wait); + + } + qid_wait_id_SUM[idx][sa.wait_id] += sa.samples; + key3 k{ q,sa.wait_id,sa.pid }; + sum_all[sa.wait_id] += sa.samples; + if (sa.btype == 0) ++qid_wait_pid_count[k]; // only for FG + k.pid = sa.btype; // pid agregate (FG or BG) + if (sa.btype > 0) { + qid_wait_pid_BG_sum[k] += sa.samples; + sum_bg[sa.wait_id] += sa.samples; + pid_btype[sa.pid] = sa.btype; + } + else qid_wait_pid_FG_sum[k] += sa.samples; + } + ///// GUI panel + int nwx = selP.x; + int w_right = sz.GetWidth() - LegengWidth - selP.x; + int w_left = selP.x - YaxisWidth; + int w_panel = 300; + int h_panel = 300; + if (w_left > w_right) { + nwx = selP.x - w_panel; + if (nwx < 0) nwx = 3; + } + int nwy = a.y + 5; + + wxRect pp(nwx, nwy, w_panel, h_panel); + if (m_fix_detail_idx == -1) + dc.SetPen(*wxBLACK_PEN); + else + dc.SetPen(*wxBLUE_PEN); + + dc.SetBrush(*wxGREY_BRUSH); + dc.DrawRectangle(pp); + // Title + ypos = pp.y + 3; + { + wxDCFontChanger nfont(dc, dc.GetFont().Bold()); + dt -= wxTimeSpan(0, 0, m_agg_int / 1000); + wxString tit = dt.Format("%d %H:%M:%S ") + wxString::Format("[period: %ds]", m_agg_int / 1000); + title_sz = dc.GetTextExtent(tit); + wxPoint p; + p.y = ypos; + p.x = pp.x + pp.width / 2 - title_sz.x / 2; + dc.DrawText(tit, p); + ypos += title_sz.y + VERT_SPC; + } + key3 prev{ -1,-1,-1 }; + std::map qid_wait_countPID; //count(pid) GROUP (qid,wait) + for (const auto& pair : qid_wait_pid_count) { + key3 k = pair.first; + if (!k.cmp2field(prev)) + { + prev = k; + prev.pid = -1; + prev.sum = 0; + } + ++qid_wait_countPID[prev]; + } + wxFont f = dc.GetFont(); + f.SetPointSize(f.GetPointSize() - 1); + wxString sql; + int itog = 0; + std::vector map_sum_all = sort_vec_map(sum_all, itog); + int period = ws->getPeriod(); + int total = itog; + if (total != 0) { + + for (int i = 0; i < map_sum_all.size(); i++) { + int wait_index = map_sum_all[i]; + long long w_sum = (100 * sum_all[wait_index] / total); + float sek = (period * sum_all[wait_index]) / 1000.0; + if (sek < 1) continue; + wxString w_name = ws->GetName(wait_index, WAIT_NAME); + wxString w_grp = ws->GetName(wait_index, WAIT_GRP); + wxString pr = w_name + wxString::Format(" %lld%%(%.1fs)", w_sum, sek); + long clr = ws->GetColorByWaitName(w_grp); + c.Set(clr); + dc.SetBrush(c); + p.x = pp.x + 3; + p.y = ypos; + dc.DrawRectangle(p.x, p.y, title_sz.GetHeight(), title_sz.GetHeight()); + p.x = p.x + title_sz.GetHeight() + 3; + wxString bgproc; + int v = -1; + // background wait + int sum_bg_w = 0; + for (const auto& pair : qid_wait_pid_BG_sum) { + key3 k = pair.first; + if (k.w == wait_index) { + v = pair.second * period; + sum_bg_w += v; + int bt = -1; + //if (pid_btype.find(k.pid)!= pid_btype.end()) bt= pid_btype.at(k.pid); + bt = k.pid; + wxString txt; + if (bt >= 0) txt = ws->GetBackendTypeNameShort(bt); + w_sum = v; + float f = (float)w_sum / 1000; + if (f < 0.1) continue; + if (!bgproc.IsEmpty()) bgproc += ','; + bgproc += wxString::Format("%s(%.1fs)", txt, (float)f); + //title_sz = dc.GetTextExtent(txt + pr); + //p.x = p.x + title_sz.GetHeight() + 3; +// p.y = ypos; +// dc.DrawText(txt + pr, p); +// ypos = p.y + title_sz.GetHeight() + 1; + + } + } + if (!bgproc.IsEmpty()) { + float f = (100 * sum_bg_w / (sum_all[wait_index] * period)); + bgproc = wxString::Format("BG[%d%%]: ", (int)f) + bgproc; + } + title_sz = dc.GetTextExtent(pr + bgproc); + + dc.DrawText(pr + bgproc, p); + ypos = p.y + title_sz.GetHeight() + 2; + { + wxDCFontChanger nfont(dc, f); + // detail client + std::vector sortv; + for (const auto& pair : qid_wait_pid_FG_sum) { + key3 k = pair.first; + if (k.w == wait_index) { + v = pair.second * period; + k.sum = v; + if (v < 100) continue; + bool ff = true; + for (int p = 0; p < sortv.size(); p++) { + if (sortv[p].sum < v) { + sortv.insert(sortv.begin() + p, k); + ff = false; + break; + } + } + if (ff) sortv.push_back(k); + } + } + for (int j1 = 0; j1 < sortv.size(); j1++) { + key3 k = sortv[j1]; + if (k.w == wait_index) { + v = k.sum; + wxString txt; + w_sum = v; + float fsek = (float)w_sum / 1000; + if (fsek < 0.1) continue; + unsigned long long ull = k.qid; + int h = ull >> 32; + int l = ull & 0xFFFFFFFF; + wxString tqid = wxString::Format("%llx", ull); + k.pid = -1; + int cnt = qid_wait_countPID[k]; + + bgproc = wxString::Format("%s ( %.1fs ) [%d]", tqid, (float)fsek, cnt); + title_sz = dc.GetTextExtent(bgproc); + //p.x = p.x + title_sz.GetHeight() + 3; + p.y = ypos; + wxRect r(p.x, p.y, title_sz.GetWidth(), title_sz.GetHeight()); + if (r.Contains(mouse)) { + wxDCFontChanger nfont(dc, f.Bold()); + dc.DrawText(bgproc, p); + if (m_click == 0) { + // hint sql + sql = ws->GetQueryByQid(k.qid); + } + if (m_click == 2) { // RightUp + // set filter qid + if (wxTheClipboard->Open()) + { + wxDataObjectComposite* dataobj = new wxDataObjectComposite(); + dataobj->Add(new wxTextDataObject(tqid)); + wxTheClipboard->SetData(dataobj); + wxTheClipboard->Close(); + } + m_click = 0; + } + if (m_click == 1) { // LeftUp + // set filter qid + m_click = 0; + m_filter_detail = tqid; + m_qid_filter = k.qid; + m_regroup = true; + return; + } + + } + else + dc.DrawText(bgproc, p); + ypos = p.y + title_sz.GetHeight() + 1; + + } + } + } + + } + if (!sql.IsEmpty()) { + FSQL::FormatterSQL f(sql); + if (f.ParseSql(0) != 0) { + wxRect r(a.x, a.y, 0, a.height); + if (mouse.x > (a.x + a.width / 2)) r.width = mouse.x - a.x; + else { r.width = a.x + a.width - mouse.x - 50; r.x = mouse.x + 50; } + f.Formating(dc, r); + } + } + + } + + } + if (m_click == 1) { + m_fix_detail_idx = -1; + } + //m_click = 0; +} + +int wxTopActivity::getTimeSelRange(bool isLeftRange) { + wxDateTime r; + if (isLeftRange) r = fix_pos_L; else r = fix_pos_R; + if (!r.IsValid()) return -1; + wxLongLong ll(r.GetValue()); + int msvaluetime = ws->d_time(ll.GetValue()); + return msvaluetime; +} +void wxTopActivity::paintSelRange(wxDC& dc, int width_sample) { + // selCuror or selRect + wxDateTime t; + if (m_fix_detail_idx != -1) + return; + int cx = m_area.x + m_area.width - 1; + if (m_area.Contains(mouse)) { + int dl = cx - mouse.x; + dl = dl / width_sample; + if (dl >= 0 && dl < xAxis.size()) { + t = xAxis.at(dl); + // t.Add(wxTimeSpan(0, 0, 0, m_agg_int)); + } + } + wxColour c; + c.Set(0x00001fff); + dc.SetPen(c); + long dx1 = 0, dx2 = 0; + wxDateTime t1, t2; + if (xAxis.size() > 0) t1 = xAxis.at(0); + if (fix_pos_L.IsValid()) { + //t1.Add(wxTimeSpan(0, 0, 0, m_agg_int)); + if (t1 > fix_pos_L) { + wxTimeSpan ll = t1 - fix_pos_L; + dx1 = (ll.GetMilliseconds() * width_sample / m_agg_int).GetValue(); + if (m_area.width > (dx1)) { + wxPoint p1(cx - dx1, m_area.y + 1); + wxPoint p2(cx - dx1, m_area.y + m_area.height); + { + wxDCPenChanger npen(dc, wxPen(*wxBLACK, 2, wxPENSTYLE_SOLID)); + dc.DrawLine(p1, p2); + } + } + else dx1 = m_area.width; + if (fix_pos_R.IsValid()) { + if (t1 > fix_pos_R) { + wxTimeSpan ll = t1 - fix_pos_R; + dx2 = ((ll.GetMilliseconds() * width_sample / m_agg_int)).GetValue(); + if (m_area.width > (dx2)) { + wxPoint p1(cx - dx2, m_area.y + 1); + wxPoint p2(cx - dx2, m_area.y + m_area.height); + { + wxDCPenChanger npen(dc, wxPen(*wxBLACK, 2, wxPENSTYLE_SOLID)); + dc.DrawLine(p1, p2); + } + } + } + else dx2 = 0; + + } + } + //t1.Add(wxTimeSpan(0, 0, 0, m_agg_int)); + } + wxString labeltext; + if (t.IsValid()) labeltext = t.Format("%d %H:%M:%S"); + wxSize sz = dc.GetTextExtent(labeltext); + wxPoint p(mouse.x + 3, mouse.y - 3 - sz.y); + wxPoint p1(mouse.x, m_area.y + 1); + wxPoint p2(mouse.x, m_area.y + m_area.height - 1); + wxColour bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK); + if (!fix_pos_R.IsValid()) + { + wxRect r(p.x - 1, p.y - 1, sz.x + 2, sz.y + 2); + { + // current vert line + if (m_area.Contains(p2) && m_area.Contains(p1) && t.IsValid()) { + dc.SetBrush(bgCol); + dc.SetPen(*wxBLACK); + dc.DrawRectangle(r); + dc.DrawText(labeltext, p); + dc.DrawLine(p1, p2); + } + } + + dx2 = cx - p1.x; + if (dx2 < 0) dx2 = 0; + } + // arrow line + wxPoint points[3]; + if (fix_pos_L.IsValid() && (dx2 < dx1)) { + wxString labelLeft = fix_pos_L.Format("%d %H:%M:%S"); + wxSize szf = dc.GetTextExtent(labelLeft); + wxPoint p1(cx - dx1, m_area.y + 25); + wxPoint p2(cx - dx2, m_area.y + 25); + dc.SetBrush(*wxBLACK); + dc.SetPen(*wxBLACK); + { + wxDCPenChanger npen(dc, wxPen(*wxBLACK, 2, wxPENSTYLE_SOLID)); + dc.DrawLine(p1, p2); + } + + points[0].x = cx - dx1; points[0].y = m_area.y + 25; + points[1].x = cx - dx1 + 5; points[1].y = m_area.y + 25 - 4; + points[2].x = cx - dx1 + 5; points[2].y = m_area.y + 25 + 4; + wxPoint tx1(cx - dx1 + 2, points[0].y - szf.GetHeight() - 5); + dc.DrawPolygon(3, points); + points[0].x = cx - dx2; points[0].y = m_area.y + 25; + points[1].x = cx - dx2 - 5; points[1].y = m_area.y + 25 - 4; + points[2].x = cx - dx2 - 5; points[2].y = m_area.y + 25 + 4; + dc.DrawPolygon(3, points); + wxTimeSpan ll; + + if (fix_pos_R.IsValid()) { + ll = fix_pos_R - fix_pos_L; + labeltext = fix_pos_R.Format("%d %H:%M:%S"); + sz = dc.GetTextExtent(labeltext); + } + else if (t.IsValid()) ll = t - fix_pos_L; else return; + wxPoint tx2(cx - dx2 - 2 - sz.GetWidth(), points[0].y - sz.GetHeight() - 5); + wxRect r(tx1.x - 1, tx1.y, szf.x + 2, szf.y); + dc.SetBrush(bgCol); + dc.SetPen(*wxBLACK); + + wxString l3text = ElapsedTimeToStr(ll.GetValue()); + wxSize sz3 = dc.GetTextExtent(l3text); + wxRect r2(tx2.x - 1, tx2.y, sz.x + 2, sz.y); + int maxx = 0; + if (szf.x < (p2.x - p1.x)) { + dc.DrawRectangle(r); + dc.DrawText(labelLeft, tx1); + maxx = r.width; + } + if (sz.x + maxx < (p2.x - p1.x) && fix_pos_R.IsValid()) { + dc.DrawRectangle(r2); + dc.DrawText(labeltext, tx2); + maxx += r2.width; + } + if (sz3.x + maxx < (p2.x - p1.x)) { + wxRect r3(r.x + r.width + (p2.x - p1.x - maxx) / 2 - sz3.x / 2, r.y, sz3.x + 2, sz3.y); + dc.DrawRectangle(r3); + dc.DrawText(l3text, r3.x + 1, r3.y); + maxx += r3.width; + } + + + } + + if (m_click == 2 && !fix_pos_L.IsValid()) { + fix_pos_L = t; + } + else if (m_click == 2 && !fix_pos_R.IsValid()) { + if (fix_pos_L < t) fix_pos_R = t; else fix_pos_L = wxLongLong(wxINT64_MIN); + + } + else if (m_click == 2 && fix_pos_L.IsValid() && fix_pos_R.IsValid()) { + fix_pos_L = wxLongLong(wxINT64_MIN); + fix_pos_R = wxLongLong(wxINT64_MIN); + } + + + +} +void wxTopActivity::paintEvent(wxPaintEvent& evt) +{ + // depending on your system you may need to look at double-buffered dcs + wxBufferedPaintDC dc(this); + int tmp = m_click; + render(dc); + if (tmp != m_click) render(dc); + m_click = 0; + //wxString sql = "select $1 '\'' ''' ($$fsda$$ $as$vvv $as$), e'\\'text' \"b\" $1,45.78 \"sas\" U&' '' ' '1line'\n'2 line' from table a\n where a.id=23"; + + //FormatterSQL f(sql); + //int rez=f.ParseSql(0); + //if (rez < 0) { + // wxLogError(wxString::Format("sql parse error = %d",rez)); + // return; + //} + //wxSize sz=GetSize(); + //wxRect r(0, 0, sz.x, sz.y); + //f.Formating(dc, r); +} + + + +void wxTopActivity::mouseDown(wxMouseEvent& event) +{ + wxPoint p = event.GetPosition(); + if (m_area.Contains(p)) { + mouseS = p; + } + else mouseS = wxPoint(0, 0); +} + + +void wxTopActivity::mouseReleased(wxMouseEvent& event) +{ + //delete m_simplePopup; + //m_simplePopup = new SimpleTransientPopup(this, false); + //wxPoint pos = ClientToScreen(event.GetPosition()); + //wxSize sz = GetSize(); + //m_simplePopup->Move(pos); + //m_simplePopup->Popup(); + + if (event.LeftUp()) m_click = 1; + if (event.RightUp()) + m_click |= 2; + mouseS = wxPoint(0, 0); + + Refresh(); + // wxMessageBox(wxT("You pressed a custom button")); +} +void wxTopActivity::mouseLeftWindow(wxMouseEvent& event) +{ +} +void wxTopActivity::OnEraseBackground(wxEraseEvent& event) { + +} +// currently unused events +void wxTopActivity::mouseMoved(wxMouseEvent& event) { + wxPoint pos = event.GetPosition(); + mouse = pos; + if (mouseS != wxPoint(0, 0)) { + // shift right bound + int d = pos.x - mouseS.x; + mouseS = pos; + if (d > 0) { + // back shift + int vtime = ws->GetHomeInterval(m_RightTime, m_agg_int); + //vtime--; + //vtime = ws->GetHomeInterval(vtime, m_agg_int); + int max_grp = m_area.width / 2; + if (vtime <= m_agg_int * max_grp) return; + if (vtime / m_agg_int > 50) m_RightTime = vtime - d * m_agg_int; + if (m_RightTime <= 0) m_RightTime = vtime; + + } + else { + d = d * -1; + int vtime = ws->GetHomeInterval(m_RightTime, m_agg_int); + int vend = ws->GetHomeInterval(-1, m_agg_int); + if (vend != vtime) { + m_RightTime = vtime + d * m_agg_int; + if (m_RightTime > vend) m_RightTime = vend; + } + } + m_regroup = true; + } + Refresh(); +} +wxSize wxTopActivity::DoGetBestClientSize() { + return setsize; +}; + +void wxTopActivity::resize(wxSizeEvent& event) { + Refresh(); + m_regroup = true; +}; + + +void wxTopActivity::mouseWheelMoved(wxMouseEvent& event) { + int r = event.GetWheelRotation(); + int n = -1; + for (int i = 0; i < sizeof(m_inter) / sizeof(int); i++) + { + if (m_inter[i] == m_agg_int) { + n = i; + if (r < 0) { + i--; + n = i < 0 ? -1 : i; + break; + } + else { + i++; + n = i >= (sizeof(m_inter) / sizeof(int)) ? -1 : i; + break; + } + } + } + if (n != -1) { + m_agg_int = m_inter[n]; + m_regroup = true; + Refresh(true); + } +} +void wxTopActivity::setViewRange(int m_aggregate_interval, int RightTime) { + m_regroup = true; + m_agg_int = m_aggregate_interval; + m_RightTime = RightTime; +} +/// +/// Получение объекта WaitSample и некоторых настроечных параметров. +/// +/// +/// Переменная в которую записывается текущий агрегатный период +/// Перменная в которую записывается текущая правая граница +/// Возвращает адрес WaitSample объекта +WaitSample* wxTopActivity::getViewRange(int& m_aggregate_interval, int& RightTime) { + + m_aggregate_interval = m_agg_int; + RightTime = m_RightTime; + return ws; +} + +void wxTopActivity::rightClick(wxMouseEvent& event) {} +void wxTopActivity::keyPressed(wxKeyEvent& event) { } +void wxTopActivity::keyReleased(wxKeyEvent& event) {} +///// +BEGIN_EVENT_TABLE(topDataViewCtrl, wxDataViewCtrl) +//EVT_MOTION(topDataViewCtrl::OnMouseMove) +END_EVENT_TABLE() + +//void topDataViewCtrl::OnMouseMove(wxMouseEvent& event) {} + +bool topDataViewCtrl::CalcRowsDataView(bool force, bool IsPidFirst) { + int sel_left = top->getTimeSelRange(true); + int sel_right = top->getTimeSelRange(false); + if (sel_left > -1 && sel_right > -1) { + // set select range + } + else { + sel_left = 0; + sel_right = w->GetHomeInterval(-1, agg); + } + if (sel_left == left_g && sel_right == right_g && !force) + return false; + // recalc + int ps = w->getPositionByTime(sel_left); + std::vector* smp = w->GetSamples(); + Sample sa; + int m_count_wait = w->GetCountWaits(); + std::map wait_id_SUM; // Group by qid,pid, sum(wait) + std::map PID_SUM; // + std::map QID_SUM; // + std::map QID_PID_SUM; // + std::map PID_QID_SUM; // + std::map PID_BG; // + int sz2 = smp->size(); + long long col1 = -3; + while (ps < sz2) + { + sa = smp->at(ps++); + if (sa.btime >= (sel_right)) break; + long long q = sa.qid; + if (sa.btype > 0 && ignoreBG) { + continue; + } + if (PID_BG.count(sa.pid) == 0) PID_BG[sa.pid] = sa.btype; + key3 k{ q,-1,sa.pid }; // mask wait_id + key3p k2{ q,-1,sa.pid }; // mask wait_id + QID_PID_SUM[k] += sa.samples; + PID_QID_SUM[k2] += sa.samples; + // group by pid,qid + auto iter = wait_id_SUM.find(k); + if (iter != wait_id_SUM.end()) { + //std::cout << "Found the key " << iter->first << " with the value " << iter->second << "\n"; + iter->second[sa.wait_id] += sa.samples; + } + else { + vec_int array_wait(m_count_wait); + array_wait[sa.wait_id] += sa.samples; + wait_id_SUM.emplace(k, array_wait); + } + // Add Group by Pid + key3 k_all_pid{ -1,-1,sa.pid }; // mask wait_id ,qid + iter = wait_id_SUM.find(k_all_pid); + if (iter != wait_id_SUM.end()) { + //std::cout << "Found the key " << iter->first << " with the value " << iter->second << "\n"; + iter->second[sa.wait_id] += sa.samples; + } + else { + vec_int array_wait(m_count_wait); + array_wait[sa.wait_id] += sa.samples; + wait_id_SUM.emplace(k_all_pid, array_wait); + } + PID_SUM[k_all_pid] += sa.samples; //All waits for PID + // Add Group by Qid + key3 k_all_qid{ sa.qid,-1,-1 }; // mask wait_id ,pid + iter = wait_id_SUM.find(k_all_qid); + if (iter != wait_id_SUM.end()) { + //std::cout << "Found the key " << iter->first << " with the value " << iter->second << "\n"; + iter->second[sa.wait_id] += sa.samples; + } + else { + vec_int array_wait(m_count_wait); + array_wait[sa.wait_id] += sa.samples; + wait_id_SUM.emplace(k_all_qid, array_wait); + } + QID_SUM[k_all_qid] += sa.samples;//All waits for QID + } + // + //bool IsPidFirst = false; + //if (GetColumnAt(0)->GetTitle() == "PID") IsPidFirst = true; + typedef std::pair pair; + // sort map by value; + std::vector vecp; + if (IsPidFirst) { + std::copy(PID_SUM.begin(), + PID_SUM.end(), + std::back_inserter>(vecp)); + + } + else + { + std::copy(QID_SUM.begin(), + QID_SUM.end(), + std::back_inserter>(vecp)); + + } + std::sort(vecp.begin(), vecp.end(), + [](const pair& l, const pair& r) + { + if (l.second != r.second) { + return !(l.second < r.second); + } + return l.first < r.first; + }); + int rows = 0; + std::vector ROWS; + for (auto const& pa : vecp) { + int col = 0; + std::vector vecSORT; + if (IsPidFirst) { + key3p k3{ -1,999,pa.first.pid }; + k3.pid--; + auto l = PID_QID_SUM.upper_bound(k3); + k3.pid++; + while (l != PID_QID_SUM.end()) { + if (l->first.pid != k3.pid) break; + key3 k4{ l->first.qid,l->first.w, l->first.pid }; + vecSORT.push_back(std::make_pair(k4, l->second)); + ++l; + } + if (vecSORT.size() > 1) vecSORT.push_back(std::make_pair(key3{ -1,pa.first.w,pa.first.pid }, pa.second)); + } + else { + key3 k3 = pa.first; + k3.w = 999; + k3.qid--; + auto l = QID_PID_SUM.upper_bound(k3); + k3.qid++; + while (l != QID_PID_SUM.end()) { + if (l->first.qid != k3.qid) break; + vecSORT.push_back(*l); + ++l; + } + if (vecSORT.size() > 1) vecSORT.push_back(std::make_pair(key3{ pa.first.qid,pa.first.w,-1 }, pa.second)); + } + std::sort(vecSORT.begin(), vecSORT.end(), + [](const pair& l, const pair& r) + { + if (l.second != r.second) { + return !(l.second < r.second); + } + return l.first < r.first; + }); + for (auto& k5 : vecSORT) { + if (PID_BG.count(k5.first.pid)) k5.first.sum = PID_BG[k5.first.pid]; else k5.first.sum = 0; + ROWS.push_back(k5.first); + } + } + wxDataViewItem selectRow = GetSelection(); + + MyIndexListModel* m = static_cast(GetModel()); + m->SetAllRows(ROWS, wait_id_SUM, IsPidFirst); + if (selectRow.IsOk()) { + SetCurrentItem(selectRow); + // EnsureVisible(selectRowGroup); + } + + left_g = sel_left; + right_g = sel_right; + return true; +} +void topDataViewCtrl::BuildColumn(int mode) +{ + AppendColumn( + new wxDataViewColumn("PID", + new MyCustomRendererGraph(wxDATAVIEW_CELL_INERT, 0), + 0, + wxCOL_WIDTH_AUTOSIZE, + wxALIGN_NOT, + wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE + )); + AppendColumn( + new wxDataViewColumn("QID", + new MyCustomRendererGraph(wxDATAVIEW_CELL_INERT, 1), + 1, + wxCOL_WIDTH_AUTOSIZE, + wxALIGN_NOT, + wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE + )); + AppendColumn( + new wxDataViewColumn("graph", + new MyCustomRendererGraph(wxDATAVIEW_CELL_INERT, 2), + 2, + wxCOL_WIDTH_AUTOSIZE, + wxALIGN_NOT, + wxDATAVIEW_COL_RESIZABLE + )); + +}; +/// +/// /// Small panel +/// +class wxCustomButton : public wxWindow +{ + + bool pressedDown; + wxString text; + wxPoint cur; + wxPoint cur_prev; + WaitSample* ws; + static const int buttonWidth = 200; + static const int buttonHeight = 50; + +public: + wxCustomButton(wxFrame* parent, wxString text, WaitSample* WS); + + void paintEvent(wxPaintEvent& evt); + void OnEraseBackground(wxEraseEvent& event); + void paintNow(); + + void render(wxDC& dc); + + // some useful events + void mouseMoved(wxMouseEvent& event); + void mouseDown(wxMouseEvent& event); + void mouseWheelMoved(wxMouseEvent& event); + void mouseReleased(wxMouseEvent& event); + void rightClick(wxMouseEvent& event); + void mouseLeftWindow(wxMouseEvent& event); + void keyPressed(wxKeyEvent& event); + void keyReleased(wxKeyEvent& event); + + DECLARE_EVENT_TABLE() +}; + + +BEGIN_EVENT_TABLE(wxCustomButton, wxPanel) + +EVT_MOTION(wxCustomButton::mouseMoved) +EVT_LEFT_DOWN(wxCustomButton::mouseDown) +EVT_LEFT_UP(wxCustomButton::mouseReleased) +EVT_RIGHT_DOWN(wxCustomButton::rightClick) +EVT_LEAVE_WINDOW(wxCustomButton::mouseLeftWindow) +EVT_KEY_DOWN(wxCustomButton::keyPressed) +EVT_KEY_UP(wxCustomButton::keyReleased) +EVT_MOUSEWHEEL(wxCustomButton::mouseWheelMoved) + +// catch paint events +EVT_PAINT(wxCustomButton::paintEvent) +EVT_ERASE_BACKGROUND(wxCustomButton::OnEraseBackground) + +END_EVENT_TABLE() + + + +wxCustomButton::wxCustomButton(wxFrame* parent, wxString text, WaitSample* WS) : + wxWindow(parent, wxID_ANY) +{ + ws = WS; + SetBackgroundStyle(wxBG_STYLE_PAINT); + SetMinSize(wxSize(buttonWidth, buttonHeight)); + this->text = text; + pressedDown = false; + +} + +/* + * Called by the system of by wxWidgets when the panel needs + * to be redrawn. You can also trigger this call by + * calling Refresh()/Update(). + */ + +void wxCustomButton::paintEvent(wxPaintEvent& evt) +{ + // depending on your system you may need to look at double-buffered dcs + wxBufferedPaintDC dc(this); + render(dc); +} + +/* + * Alternatively, you can use a clientDC to paint on the panel + * at any time. Using this generally does not free you from + * catching paint events, since it is possible that e.g. the window + * manager throws away your drawing when the window comes to the + * background, and expects you will redraw it when the window comes + * back (by sending a paint event). + */ +void wxCustomButton::paintNow() +{ + // depending on your system you may need to look at double-buffered dcs + //wxPaintDC dc(this); + //render(dc); + this->Refresh(false); +} + +struct ClrSum { + int clr; + int sum = 0; +}; +/* + * Here we do the actual rendering. I put it in a separate + * method so that it can work no matter what type of DC + * (e.g. wxPaintDC or wxClientDC) is used. + */ +void wxCustomButton::render(wxDC& dc) +{ + if (pressedDown) + dc.SetBrush(*wxRED_BRUSH); + else + dc.SetBrush(*wxGREY_BRUSH); + wxRect r = dc.GetWindow()->GetClientRect(); + wxSize sz = r.GetSize(); + //dc.DrawRectangle(0, 0, r.width, r.height); + dc.DrawRectangle(0, 0, sz.x, sz.y); + wxColour c; + //dc.SetPen(*wxTRANSPARENT_PEN); + int widthLine = 4; + int period = 10, interval = 1000; + int countLine = sz.GetWidth() / widthLine; + int full = sz.GetHeight() - 3; + int minHeight = 4; + int maxHeight = minHeight * 2; + int minRange = 200; // ms + int x = sz.GetWidth() - widthLine; + int y = sz.GetHeight(); + std::vector* smp = ws->GetSamples(); + Sample sa; + int vtime = 0; + std::vector::iterator it = smp->end(); + + + int idx = smp->size() - 1; + + // vertical serios + std::vector clr = ws->GetColors(); + std::vector hz = clr; + std::vector graph; + for (int i = 0; i < hz.size(); i++) hz[i] = 0; + // sum(samples) from group by wait_id + int prev_c = -1; + int sum_by_clr = 0; + int serios_sum = 0; + int prev_t = -1; + while (idx >= 0 && countLine > 0) { + sa = smp->at(idx); + if (prev_t == -1) prev_t = sa.btime; + hz[sa.wait_id] += sa.samples; // sum() + int c = clr[sa.wait_id]; + + if (sa.btime != prev_t) { + // new serios + // new color + ClrSum cs; + cs.clr = prev_c; + cs.sum = sum_by_clr; + graph.push_back(cs); + prev_c = c; + sum_by_clr = 0; + y = sz.GetHeight(); + bool isNext = true; + while (isNext) { + int h = 0; + isNext = false; + for (auto i : graph) { + if (i.sum * period < minRange) h += minHeight; + else h += maxHeight; + if (h > full && minHeight >= 3) { + if (minRange == 1) { + minHeight--; + } + if (minRange > 1) minRange--; + isNext = true; + break; + } + } + } + // draw serios + int h = 0; + wxColour c; + for (auto i : graph) { + if (i.sum * period < minRange) h = minHeight; + else h = maxHeight; + unsigned long clr = i.clr; + c.Set(clr); + dc.SetBrush(c); + dc.DrawRectangle(x, y - h, widthLine, h); + y = y - h; + } + x = x - widthLine; + int skip = (prev_t - sa.etime) / interval; // не было ожиданий + if (skip > 0) { + x -= skip * widthLine; + } + + graph.clear(); + serios_sum = 0; + countLine--; + // return; + } + if (prev_c == -1) prev_c = c; + if (prev_c != c) { + // new color + ClrSum cs; + cs.clr = prev_c; + cs.sum = sum_by_clr; + graph.push_back(cs); + prev_c = c; + sum_by_clr = 0; + } + sum_by_clr += sa.samples; + serios_sum += sa.samples; + prev_t = sa.btime; + idx--; + } + + + wxString s = wxString::Format("x:%d,y:%d", cur.x, cur.y); + dc.DrawText(s, 20, 15); +} + +void wxCustomButton::mouseDown(wxMouseEvent& event) +{ + pressedDown = true; + paintNow(); +} + +void wxCustomButton::mouseReleased(wxMouseEvent& event) +{ + pressedDown = false; + paintNow(); + //delete m_simplePopup; + //m_simplePopup = new SimpleTransientPopup(this, false); + //wxPoint pos = ClientToScreen(event.GetPosition()); + //wxSize sz = GetSize(); + //m_simplePopup->Move(pos); + //m_simplePopup->Popup(); + + + // wxMessageBox(wxT("You pressed a custom button")); +} +void wxCustomButton::mouseLeftWindow(wxMouseEvent& event) +{ + if (pressedDown) + { + pressedDown = false; + paintNow(); + } +} +void wxCustomButton::OnEraseBackground(wxEraseEvent& event) { + +} +// currently unused events +void wxCustomButton::mouseMoved(wxMouseEvent& event) { + wxPoint pos = event.GetPosition(); + + if (cur != pos) { + cur = pos; + paintNow(); + } +} +void wxCustomButton::mouseWheelMoved(wxMouseEvent& event) {} +void wxCustomButton::rightClick(wxMouseEvent& event) {} +void wxCustomButton::keyPressed(wxKeyEvent& event) {} +void wxCustomButton::keyReleased(wxKeyEvent& event) {} + + diff --git a/frm/frmStatus.cpp b/frm/frmStatus.cpp index a427eb8..44e05e9 100644 --- a/frm/frmStatus.cpp +++ b/frm/frmStatus.cpp @@ -19,7 +19,8 @@ #include #include #include - +#include +#include // wxAUI #include @@ -36,7 +37,9 @@ #include "ctl/ctlMenuToolbar.h" #include "ctl/ctlAuiNotebook.h" #include "utils/csvfiles.h" - +#include "utils/utffile.h" +#include "ctl/ctlNavigatePanel.h" +#include "ctl/wxTopActivity.h" // Icons #include "images/clip_copy.pngc" #include "images/readdata.pngc" @@ -48,10 +51,11 @@ #include "images/down.pngc" #include "images/up.pngc" #include "images/server_status.pngc" - +#include #include "db/pgConn.h" +extern int s_pid_HIGHLIGH; #define CTRLID_DATABASE 4200 @@ -68,6 +72,7 @@ BEGIN_EVENT_TABLE(frmStatus, pgFrame) EVT_MENU(MNU_XACTPAGE, frmStatus::OnToggleXactPane) EVT_MENU(MNU_LOGPAGE, frmStatus::OnToggleLogPane) EVT_MENU(MNU_QUERYSTATEPAGE, frmStatus::OnToggleQuerystatePane) + EVT_MENU(MNU_WAITENABLE, frmStatus::OnToggleWaitEnable) EVT_MENU(MNU_QUERYSTATEVERBOSE, frmStatus::OnEmptyAction) EVT_MENU(MNU_QUERYSTATETIME, frmStatus::OnEmptyAction) EVT_MENU(MNU_QUERYSTATEBUFFER, frmStatus::OnEmptyAction) @@ -78,7 +83,7 @@ BEGIN_EVENT_TABLE(frmStatus, pgFrame) EVT_MENU(MNU_HIGHLIGHTSTATUS, frmStatus::OnHighlightStatus) EVT_AUI_PANE_CLOSE( frmStatus::OnPaneClose) - + //EVT_AUI_PANE_ACTIVATED( frmStatus::OnPaneActivated) EVT_COMBOBOX(CTL_RATECBO, frmStatus::OnRateChange) EVT_MENU(MNU_REFRESH, frmStatus::OnRefresh) EVT_MENU(MNU_CANCEL, frmStatus::OnCancelBtn) @@ -112,13 +117,14 @@ BEGIN_EVENT_TABLE(frmStatus, pgFrame) EVT_LIST_COL_CLICK(CTL_XACTLIST, frmStatus::OnSortXactGrid) EVT_LIST_COL_RIGHT_CLICK(CTL_XACTLIST, frmStatus::OnRightClickXactGrid) EVT_LIST_COL_END_DRAG(CTL_XACTLIST, frmStatus::OnChgColSizeXactGrid) - + //EVT_KEY_UP(CTL_LOGLIST, frmStatus::OnLogKeyUp) EVT_TIMER(TIMER_LOG_ID, frmStatus::OnRefreshLogTimer) EVT_LIST_ITEM_SELECTED(CTL_LOGLIST, frmStatus::OnSelLogItem) EVT_LIST_ITEM_DESELECTED(CTL_LOGLIST, frmStatus::OnSelLogItem) + EVT_LIST_ITEM_RIGHT_CLICK(CTL_LOGLIST, frmStatus::OnRightClickLogGrid) EVT_TIMER(TIMER_QUERYSTATE_ID, frmStatus::OnRefreshQuerystateTimer) EVT_LIST_COL_RIGHT_CLICK(CTL_QUERYSTATELIST, frmStatus::OnRightClickQuerystateGrid) @@ -201,7 +207,7 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr mainForm = form; connection = conn; locks_connection = conn; - + logconn = NULL; statusTimer = 0; locksTimer = 0; xactTimer = 0; @@ -226,12 +232,78 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr connection->ExecuteVoid(initquery, false); } //pg_is_in_recovery() - wxString v = connection->ExecuteScalar(wxT("select pg_is_in_recovery()")); - - isrecovery = (v == wxT("t")); - v = connection->ExecuteScalar(wxT("select current_setting('track_commit_timestamp')")); - track_commit_timestamp = (v == wxT("on")); - + waitMenu = new wxMenu(); + waitMenu->Append(MNU_WAITENABLE, _("&Wait trace"), _("Enable the wait event."), wxITEM_CHECK); + waitMenu->Append(MNU_WAITSAVE, _("&Wait event save"), _("Enable the wait event save to file sample.dat."), wxITEM_CHECK); + settings->Read(wxT("frmStatus/WaitTraceEnable"), &wait_enable, false); + settings->Read(wxT("frmStatus/WaitSave"), &wait_save, false); + waitMenu->Check(MNU_WAITENABLE,wait_enable); + waitMenu->Check(MNU_WAITSAVE, wait_save); + //MNU_WAITSAVE + wxString q = "select pg_is_in_recovery() recovery, \ + (select setting from pg_settings s where name = 'pg_wait_sampling.history_size')::integer hsize, \ + (select setting from pg_settings s where name = 'pg_wait_sampling.history_period')::integer hperiod, \ + (select pg_table_is_visible(viewname::regclass) and has_table_privilege(viewname::regclass,'select') from pg_views where viewname = 'pg_wait_sampling_history') as wsh, \ + (select pg_table_is_visible(viewname::regclass) and has_table_privilege(viewname::regclass,'select') from pg_views v where viewname='pgpro_stats_statements') as pro, \ + (select pg_table_is_visible(viewname::regclass) and has_table_privilege(viewname::regclass,'select') from pg_views v where viewname='pg_stats_statements') as std, \ + has_function_privilege('pg_read_binary_file(text,bigint,bigint,boolean)','execute') isreadlog \ + "; + + pgSet* dataSet1 = connection->ExecuteSet(q); + bool pro = false; + bool std = false; + wait_sample = false; + is_read_log = false; + if (dataSet1) + { + while (!dataSet1->Eof()) + { + wxString v = dataSet1->GetVal(wxT("recovery")); + pro= dataSet1->GetBool(wxT("pro")); + std = dataSet1->GetBool(wxT("std")); + is_read_log = dataSet1->GetBool(wxT("isreadlog")); + isrecovery = (v == wxT("t")); + track_commit_timestamp = connection->HasFeature(FEATURE_TRACK_COMMIT_TS); + long sz = dataSet1->GetLong(wxT("hsize")); + long p = dataSet1->GetLong(wxT("hperiod")); + if (!dataSet1->GetBool(wxT("wsh"))) p = 0; + if (sz > 1000000) { + wxLogWarning(_("Value parameter pg_wait_sampling.history_size = %ld greet 1000000 monitoring wait events disabled.\n"), + sz + ); + p = 0; + } + if (p > 0) { + wait_sample = true; + WS.SetConfig(p,sz); + } + dataSet1->MoveNext(); + } + delete dataSet1 ; + } + if (!wait_sample) { + waitMenu->Enable(MNU_WAITENABLE, false); + waitMenu->Enable(MNU_WAITSAVE, false); + } + if (wait_sample && wait_enable && (std || pro)) { + if (std) q = "select distinct queryid,query from pg_stats_statements s"; + if (pro) q = "select distinct queryid,query from pgpro_stats_statements s"; + dataSet1 = connection->ExecuteSet(q); + bool pro = false; + bool std = false; + if (dataSet1) + { + while (!dataSet1->Eof()) + { + wxULongLong qid= dataSet1->GetLongLong("queryid"); + wxString query= dataSet1->GetVal("query"); + WS.AddQuery(qid.GetValue(), query); + dataSet1->MoveNext(); + } + delete dataSet1; + } + + } // Notify wxAUI which frame to use manager.SetManagedWindow(this); @@ -286,9 +358,10 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr viewMenu->Append(MNU_HIGHLIGHTSTATUS, _("Highlight items of the activity list"), _("Highlight or not the items of the activity list."), wxITEM_CHECK); viewMenu->AppendSeparator(); viewMenu->Append(MNU_DEFAULTVIEW, _("&Default view\tCtrl-Alt-V"), _("Restore the default view.")); - + + menuBar->Append(waitMenu, _("&Wait")); menuBar->Append(viewMenu, _("&View")); - + wxMenu *helpMenu = new wxMenu(); helpMenu->Append(MNU_CONTENTS, _("&Help contents"), _("Open the helpfile.")); helpMenu->Append(MNU_HELP, _("&Server status help"), _("Display help on this window.")); @@ -339,6 +412,13 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr toolBar->AddSeparator(); cbDatabase = new ctlComboBoxFix(toolBar, CTRLID_DATABASE, wxDefaultPosition, wxSize(-1, -1), wxCB_READONLY | wxCB_DROPDOWN); toolBar->AddControl(cbDatabase); + if (wait_sample && wait_enable) { + toolBar->AddSeparator(); + top_small = new wxTopActivity(toolBar, &WS, wxSize(100, 32)); + toolBar->AddControl(top_small); + } + else top_small = NULL; + toolBar->Realize(); // Append items to cbo @@ -367,13 +447,13 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr btnRotateLog->Enable(false); // Add the database combobox - pgSet *dataSet1 = connection->ExecuteSet(wxT("SELECT datname FROM pg_database WHERE datallowconn ORDER BY datname")); - while (!dataSet1->Eof()) + pgSet *dataSet3 = connection->ExecuteSet(wxT("SELECT datname FROM pg_database WHERE datallowconn ORDER BY datname")); + while (!dataSet3->Eof()) { - cbDatabase->Append(dataSet1->GetVal(wxT("datname"))); - dataSet1->MoveNext(); + cbDatabase->Append(dataSet3->GetVal(wxT("datname"))); + dataSet3->MoveNext(); } - delete dataSet1; + delete dataSet3; // Image list for all listviews listimages = new wxImageList(13, 8, true, 2); @@ -402,7 +482,7 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr manager.GetPane(wxT("Logfile")).Caption(_("Logfile")); manager.GetPane(wxT("Querystate")).Caption(_("QueryState")); manager.GetPane(wxT("toolBar")).BestSize(toolw); - + //manager.GetPane(wxT("Activity")).GripperTop(true); // Tell the manager to "commit" all the changes just made manager.Update(); @@ -412,15 +492,21 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr viewMenu->Check(MNU_XACTPAGE, manager.GetPane(wxT("Transactions")).IsShown()); viewMenu->Check(MNU_LOGPAGE, manager.GetPane(wxT("Logfile")).IsShown()); pgSet *set = connection->ExecuteSet(wxT("SELECT 1 FROM pg_available_extensions WHERE installed_version is not null and name='pg_query_state'")); - viewMenu->Enable(MNU_QUERYSTATEPAGE,set->NumRows() == 1); + bool queryenable = set->NumRows() == 1; + viewMenu->Enable(MNU_QUERYSTATEPAGE, queryenable); + if (!queryenable) { + viewMenu->Check(MNU_QUERYSTATEPAGE, false); + manager.GetPane(wxT("Querystate")).Hide(); + } //viewMenu->Check(MNU_QUERYSTATEPAGE,set->NumRows() == 1); delete set; viewMenu->Check(MNU_TOOLBAR, manager.GetPane(wxT("toolBar")).IsShown()); // - if (!viewMenu->IsEnabled(MNU_QUERYSTATEPAGE)) { - manager.GetPane(wxT("Querystate")).Hide(); - } else manager.GetPane(wxT("Querystate")).Show(); + //if (!viewMenu->IsEnabled(MNU_QUERYSTATEPAGE)) { + // manager.GetPane(wxT("Querystate")).Hide(); + // } else manager.GetPane(wxT("Querystate")).Show(); + viewMenu->Check(MNU_QUERYSTATEPAGE,manager.GetPane(wxT("Querystate")).IsShown()); // Read the highlight status checkbox settings->Read(wxT("frmStatus/HighlightStatus"), &highlight, true); @@ -459,7 +545,6 @@ frmStatus::~frmStatus() { // Delete the refresh timer delete refreshUITimer; - // If the status window wasn't launched in standalone mode... if (mainForm) mainForm->RemoveFrame(this); @@ -475,7 +560,9 @@ frmStatus::~frmStatus() settings->WriteBool(wxT("frmStatus/QuerystateTimeStatus"), viewMenu->IsChecked(MNU_QUERYSTATETIME)); settings->WriteBool(wxT("frmStatus/QuerystateBufferStatus"), viewMenu->IsChecked(MNU_QUERYSTATEBUFFER)); settings->WriteBool(wxT("frmStatus/QuerystateTriggerStatus"), viewMenu->IsChecked(MNU_QUERYSTATETRIGGER)); - + if (wait_sample) settings->WriteBool(wxT("frmStatus/WaitTraceEnable"), waitMenu->IsChecked(MNU_WAITENABLE)); + if (wait_sample) settings->WriteBool(wxT("frmStatus/WaitSave"), waitMenu->IsChecked(MNU_WAITSAVE)); + if (wait_sample && wait_enable && waitMenu->IsChecked(MNU_WAITSAVE)) WS.SaveFileSamples(); // For each current page, save the slider's position and delete the timer @@ -523,6 +610,18 @@ frmStatus::~frmStatus() if (connection->IsAlive()) delete connection; } + if (logThread) { + logThread->BreakRead(); + wxMilliSleep(50); + logThread->DoTerminate(); + s_CloseLog.Wait(); + logThread=NULL; + } + if (logconn) + { + if (logconn->IsAlive()) + delete logconn; + } } @@ -572,13 +671,21 @@ void frmStatus::Go() void frmStatus::OnClose(wxCloseEvent &event) { - Destroy(); + + frm_exit = true; + if (logThread && logisread) { + logThread->BreakRead(); + event.Veto(); + } else Destroy(); + //Destroy(); } void frmStatus::OnExit(wxCommandEvent &event) { - Destroy(); + wxCloseEvent e; + OnClose(e); + //Destroy(); } @@ -1007,10 +1114,11 @@ void frmStatus::AddLogPane() // Create panel wxPanel *pnlLog = new wxPanel(this); - + //pnlLog->SetBackgroundColour(*wxRED); // Create flex grid - wxFlexGridSizer *grdLog = new wxFlexGridSizer(1, 1, 5, 5); - grdLog->AddGrowableCol(0); + wxFlexGridSizer *grdLog = new wxFlexGridSizer(1, 2, 2, 0); + //wxBoxSizer* grdLog = new wxBoxSizer(wxHORIZONTAL); + grdLog->AddGrowableCol(1); grdLog->AddGrowableRow(0); // Add the list control @@ -1020,12 +1128,22 @@ void frmStatus::AddLogPane() wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), true); #endif wxListCtrl *lstLog = new wxListCtrl(pnlLog, CTL_LOGLIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxSUNKEN_BORDER); + // Add the log list + logList = (ctlListView*)lstLog; + nav = new ctlNavigatePanel(pnlLog, logList); + lstLog->Bind(wxEVT_KEY_UP, &frmStatus::OnLogKeyUp, this); + //lstLog->Bind(wxEVT_MENU, &ctlNavigatePanel::OnContextMenu, this); + Bind(wxEVT_THREAD, &frmStatus::OnAddLabelTextThread, this); + lstLog->Bind(wxEVT_MENU, &frmStatus::OnLogContextMenu, this); + //Connect(wxID_ANY, wxEVT_THREAD, wxThreadEventHandler(frmLog::OnAddLabelTextThread), NULL, this); // Now switch back #ifdef __WXMAC__ wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), false); #endif - grdLog->Add(lstLog, 0, wxGROW, 3); + + grdLog->Add(nav, 0, wxSHRINK, 3); + grdLog->Add(lstLog, 0, wxALL | wxEXPAND, 3); // Add the panel to the notebook manager.AddPane(pnlLog, wxAuiPaneInfo().Center(). @@ -1037,11 +1155,19 @@ void frmStatus::AddLogPane() pnlLog->SetSizer(grdLog); grdLog->Fit(pnlLog); - // Add the log list - logList = (ctlListView *)lstLog; - bgColor = logList->GetBackgroundColour(); + logcol[0] = logList->GetBackgroundColour(); + logcol[1] = wxColour("#afafaf"); // We don't need this report (but we need the pane) // if server release is less than 8.0 or if server has no adminpack + if (!is_read_log) { + logList->InsertColumn(logList->GetColumnCount(), _("Message"), wxLIST_FORMAT_LEFT, 700); + logList->InsertItem(logList->GetItemCount(), _("Function pg_read_binary_file(text,bigint,bigint,boolean) permission denied."), -1); + logList->Enable(false); + logTimer = NULL; + // We're done + return; + + } if (!(connection->BackendMinimumVersion(8, 0) && connection->HasFeature(FEATURE_FILEREAD))) { @@ -1065,7 +1191,7 @@ void frmStatus::AddLogPane() if (!connection->HasFeature(FEATURE_FILEREAD, true)) { - logList->InsertColumn(logList->GetColumnCount(), _("Message"), wxLIST_FORMAT_LEFT, 800); + logList->InsertColumn(logList->GetColumnCount(), _("Message"), wxLIST_FORMAT_LEFT, wxLIST_AUTOSIZE_USEHEADER); logList->InsertItem(logList->GetItemCount(), _("Logs are not available for this server."), -1); logList->Enable(false); logTimer = NULL; @@ -1131,7 +1257,6 @@ void frmStatus::AddLogPane() logTimer = new wxTimer(this, TIMER_LOG_ID); } - void frmStatus::OnCopy(wxCommandEvent &ev) { ctlListView *list; @@ -1266,7 +1391,10 @@ void frmStatus::OnCopyQuery(wxCommandEvent &ev) } } - +void frmStatus::OnPaneActivated(wxAuiManagerEvent& evt) { + wxTimerEvent event; + OnRefreshUITimer(event); +} void frmStatus::OnPaneClose(wxAuiManagerEvent &evt) { if (evt.pane->name == wxT("Activity")) @@ -1288,6 +1416,8 @@ void frmStatus::OnPaneClose(wxAuiManagerEvent &evt) if (evt.pane->name == wxT("Logfile")) { viewMenu->Check(MNU_LOGPAGE, false); + + if (logThread) logThread->BreakRead(); if (logTimer) logTimer->Stop(); } @@ -1369,16 +1499,22 @@ void frmStatus::OnToggleLogPane(wxCommandEvent &event) cbRate->SetValue(rateToCboString(logRate)); if (logRate > 0 && logTimer) logTimer->Start(logRate * 1000L); + wxTimerEvent e; + OnRefreshLogTimer(e); } else { manager.GetPane(wxT("Logfile")).Show(false); + if (logThread) logThread->BreakRead(); if (logTimer) logTimer->Stop(); } // Tell the manager to "commit" all the changes just made manager.Update(); +} +void frmStatus::OnToggleWaitEnable(wxCommandEvent& event) { + } void frmStatus::OnToggleQuerystatePane(wxCommandEvent &event) { @@ -1516,9 +1652,8 @@ void frmStatus::OnRateChange(wxCommandEvent &event) void frmStatus::OnRefreshUITimer(wxTimerEvent &event) { wxListEvent evt; - refreshUITimer->Stop(); - + if (frm_exit && !logisread) Destroy(); for (unsigned int i = 0; i < manager.GetAllPanes().GetCount(); i++) { wxAuiPaneInfo &pane = manager.GetAllPanes()[i]; @@ -1579,14 +1714,16 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) long row = 0; wxString q = wxT("SELECT "); - + wait_enable = waitMenu->IsChecked(MNU_WAITENABLE); // PID q += pidcol + wxT(" AS pid, "); // Application name (when available) if (connection->BackendMinimumVersion(8, 5)) q += wxT("application_name, "); - + if (connection->BackendMinimumVersion(14, 0)) + q += wxT("query_id, "); + // Database, and user name q += wxT("p.datname, usename,\n"); @@ -1621,7 +1758,7 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) // Transaction start timestamp if (connection->BackendMinimumVersion(8, 3)) - q += wxT("date_trunc('second', xact_start) AS xact_start, "); + q += wxT("xact_start AS xact_start_full,date_trunc('second', xact_start) AS xact_start, "); // State if (connection->BackendMinimumVersion(9, 2)) @@ -1689,7 +1826,12 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) if (connection->BackendMinimumVersion(10, 0)) { if (connection->BackendMinimumVersion(13, 0)) - q += wxT(",backend_type,wait_event_type,wait_event,v.progress_info,case when backend_type='autovacuum launcher' then (select min(xmin::text::bigint) from pg_replication_slots) end av_replica\n"); + { + q += wxT(",backend_type,wait_event_type,wait_event,v.progress_info,case when backend_type='autovacuum launcher' then (select min(xmin::text::bigint) from pg_replication_slots) end av_replica\n"); + if (wait_sample && wait_enable) { + q += ",transaction_timestamp() tt,hs.wait_sample,hs.maxts"; + } + } else q += wxT(",backend_type,wait_event_type,wait_event,v.heap_blks_total,v.heap_blks_vacuumed,v.heap_blks_scanned,v.phase\n"); @@ -1704,6 +1846,20 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) else q += wxT("FROM pg_stat_activity p LEFT JOIN pg_stat_progress_vacuum v ON p.pid=v.pid\n"); q += wxT("LEFT JOIN pg_replication_slots sl ON p.pid=sl.active_pid\n"); + if (wait_sample && wait_enable) + { + q += " left join ( \ + select pid, string_agg(format('%s:%s', event_type || ':' || event||':'||queryid, cnt), ';') wait_sample, max(maxts) maxts from( \ + select pid,queryid, event_type, event, max(ts) maxts, count(*) cnt from pg_wait_sampling_history h \ + where h.event not in('ArchiverMain', 'WalWriterMain', 'CheckpointerMain', 'Extension', 'LogicalLauncherMain', 'CfsGcEnable', 'WalSenderMain' \ + , 'AutoVacuumMain', '-ClientRead', 'CheckpointWriteDelay', 'BgWriterMain', 'BgWriterHibernate') \ + "; + + if (!first_tt.IsEmpty()) q += "and h.ts > '"+first_tt+"'"; + + q+="group by pid, event_type, event,queryid \ + ) l group by pid) hs on p.pid = hs.pid\n"; + } iswalsend = true; //backend_type } else @@ -1714,28 +1870,38 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) // And the rest of the query... q += wxT(" ORDER BY ") + NumToStr((long)statusSortColumn) + wxT(" ") + statusSortOrder; - - pgSet *dataSet1 = connection->ExecuteSet(q); + wxString msgerror; + pgSet *dataSet1 = connection->ExecuteSet(q,false); if (dataSet1) { + msgerror = connection->GetLastError(); statusBar->SetStatusText(_("Refreshing status list.")); statusList->Freeze(); // Clear the queries array content queries.Clear(); wxString blocked=wxT(""); + wxArrayLong pids; + wxDateTime tt; while (!dataSet1->Eof()) { pid = dataSet1->GetLong(wxT("pid")); wxString slinfo=wxEmptyString; + wxString backend_xid; + wxDateTime start_transaction; if (iswalsend) { slinfo = dataSet1->GetVal(wxT("slotinfo")); } + if (!tt.IsValid()&&wait_sample && wait_enable) { + tt = dataSet1->GetDateTime("tt"); + WS.BeginSeriosSample(tt.GetValue().GetValue()); + first_tt = dataSet1->GetVal("tt"); + + } // Update the UI if (pid != backend_pid) { - if (row >= statusList->GetItemCount()) { @@ -1744,11 +1910,16 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) } else { - statusList->SetItem(row, 0, NumToStr(pid)); + statusList->SetItem(row, 0, NumToStr(pid),-1); } wxString qry = dataSet1->GetVal(wxT("query")); wxString app_name = dataSet1->GetVal(wxT("application_name")); + wxString backend_type; + if (connection->BackendMinimumVersion(13, 0)) { + backend_type = dataSet1->GetVal(wxT("backend_type")); + if (app_name.IsEmpty() && backend_type != "client backend") app_name = backend_type; + } if (connection->BackendMinimumVersion(9, 6)) { if (connection->BackendMinimumVersion(13, 0)) { @@ -1793,8 +1964,10 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("query_start"))); } - if (connection->BackendMinimumVersion(8, 3)) + if (connection->BackendMinimumVersion(8, 3)) { + start_transaction= dataSet1->GetDateTime("xact_start_full"); statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("xact_start"))); + } if (connection->BackendMinimumVersion(9, 2)) { @@ -1804,7 +1977,8 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) if (connection->BackendMinimumVersion(9, 4)) { - statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("backend_xid"))); + backend_xid= dataSet1->GetVal(wxT("backend_xid")); + statusList->SetItem(row, colpos++, backend_xid); if (!slinfo.IsEmpty()) statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("xmin_slot"))); else { @@ -1822,8 +1996,20 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("wait_event_type"))); statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("wait_event"))); } + wxString blockedby = dataSet1->GetVal(wxT("blockedby")); + if (wait_sample && wait_enable) { + bool isClientReadTransaction = false; + //if ( spt.count>1 && ll!=0) isClientReadTransaction = true; + if (start_transaction.IsValid() + && start_transaction < tt + && !backend_xid.IsEmpty() + )isClientReadTransaction = true; - statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("blockedby"))); + WS.AddSample(pid, isClientReadTransaction, backend_type, dataSet1->GetVal("wait_sample")); + wxULongLong qid = dataSet1->GetLongLong("query_id"); + WS.AddQuery(qid.GetValue(), qry); + } + statusList->SetItem(row, colpos++, blockedby); if (!slinfo.IsEmpty()) { statusList->SetItem(row, colpos, dataSet1->GetVal(wxT("xminlag"))); } @@ -1890,33 +2076,41 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) } if (!flt) { // Add the query content to the queries array - queries.Add(dataSet1->GetVal(wxT("query"))); + queries.Add(qry); pids.Add(pid); + if (pid == s_pid_HIGHLIGH) { + statusList->SetItemBackgroundColour(row, wxColour(wxT("#FF8028"))); + statusList->EnsureVisible(row); + } + row++; } } dataSet1->MoveNext(); } delete dataSet1; - if (viewMenu->IsChecked(MNU_HIGHLIGHTSTATUS)) + if (viewMenu->IsChecked(MNU_HIGHLIGHTSTATUS)) + { + wxString numstr; + wxString str; + numstr=blocked.BeforeFirst(',',&str); + while (!numstr.IsEmpty()) { + int number = wxAtoi(numstr); + for(long i = 0; i < pids.size(); i++) { - wxString numstr; - wxString str; - numstr=blocked.BeforeFirst(',',&str); - while (!numstr.IsEmpty()) { - int number = wxAtoi(numstr); - for(long i = 0; i < pids.size(); i++) - { - if (pids[i]==number) { - statusList->SetItemBackgroundColour(i, - wxColour(settings->GetBlockedbyProcessColour())); + if (pids[i]==number) { + statusList->SetItemBackgroundColour(i, + wxColour(settings->GetBlockedbyProcessColour())); - } - } - blocked=str.Clone(); - numstr=blocked.BeforeFirst(',',&str); } } + blocked=str.Clone(); + numstr=blocked.BeforeFirst(',',&str); + } + } + if (tt.IsValid() && wait_sample && wait_enable) { + WS.EndSeriosSample(); + } bool selverify=true; while (row < statusList->GetItemCount()) { statusList->Select(row,false); @@ -1933,11 +2127,18 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event) manager.Update(); } statusList->Thaw(); - + if (wait_sample && wait_enable && top_small) top_small->Refresh(); wxListEvent ev; //OnSelStatusItem(ev); - statusBar->SetStatusText(_("Done.")); + if (msgerror.length() > 0) { + statusBar->SetStatusText(msgerror); + } + else + { + + statusBar->SetStatusText(_("Done.")); + } } else checkConnection(); @@ -2302,6 +2503,7 @@ void frmStatus::OnRefreshQuerystateTimer(wxTimerEvent &event) void frmStatus::OnRefreshLogTimer(wxTimerEvent &event) { + if (logisread) return; if (! viewMenu->IsEnabled(MNU_LOGPAGE) || ! viewMenu->IsChecked(MNU_LOGPAGE) || !logTimer) return; @@ -2315,8 +2517,99 @@ void frmStatus::OnRefreshLogTimer(wxTimerEvent &event) logTimer->Stop(); return; } + if (!logThread) { + wxString applicationname = "pgAdmin III LogReader"; + logconn = new pgConn(connection->GetHostName(), connection->GetService(), connection->GetHostAddr(), connection->GetDbname(), + connection->GetUser(), connection->GetPassword(), connection->GetPort(), connection->GetRole(), "", connection->GetSslMode(), + 0, applicationname, connection->GetSSLCert(), connection->GetSSLKey(), connection->GetSSLRootCert(), connection->GetSSLCrl(), + connection->GetSSLCompression()); + + if (!logconn->IsAlive()) { + wxString err=logconn->GetLastError(); + //wxMessageBox(err); + statusBar->SetStatusText(err); + delete logconn; + logconn = NULL; + return; + } + else + { + } + if (log_queue.IsOk()) log_queue.Clear(); + logThread = new ReadLogThread(logconn, this,&log_queue); + if (logThread->Create() != wxTHREAD_NO_ERROR) + { + wxLogError(wxT("Can’t create log thread!")); + delete logThread; + logThread = NULL; + } else + logThread->Run(); + } + else + if (logThread) // The thread + { + // Recive lines + if (logThread->isBreak()) return; + wxString sstr; + long lastrow = logList->GetItemCount(); + bool remote = lastrow - 1 == logList->GetFocusedItem(); + long cnt = 0; + float pr = 0; + long timeout = logTimer->GetInterval(); + const wxMilliClock_t waitUntil = wxGetLocalTimeMillis() + timeout; + logisread = true; + if (!logList->IsFrozen()) logList->Freeze(); + while (logThread && log_queue.ReceiveTimeout(1, sstr) == wxMSGQUEUE_NO_ERROR) { + if (logThread->isBreak()) break; + addLogLine(sstr, true, true); + if (logThread->isBreak()) break; + if ((cnt++ % 1000) == 0) { + //pr = 100 * cnt / total; + wxString ll = wxString::Format("append rows %ld ...", cnt+ lastrow); + statusBar->SetStatusText(ll); + wxYield(); + if (frm_exit) { logisread = false; return; } + } + //if (logThread->isBreak()) return; + const wxMilliClock_t now = wxGetLocalTimeMillis(); + if (now >= waitUntil) break; + + }; + if (logList->IsFrozen()) + { + logList->Thaw(); + nav->Refresh(); + } + logisread = false; + if (logThread && logThread->isBreak()) { + return; + } + if (cnt > 0) { + cnt += lastrow; + //wxString ll = wxString::Format("append rows GUI %ld ...", cnt); + //statusBar->SetStatusText(ll); + addodd++; + if (remote) { + logList->Focus(logList->GetItemCount() - 1); + } + logList->Refresh(); + } + //statusBar->SetStatusText(s); + if (logThread && logThread->isReadyRows()) { + long read = logThread->GetReadByteFile(savedPartialLine); // result last read + logfileLength = read; + // Ready next lines + } + else { + return; /// not ready next lines + } + } + + + wxCriticalSectionLocker lock(gs_critsect); + if (logList->IsFrozen()) logList->Thaw(); if (connection->GetLastResultError().sql_state == wxT("42501")) { @@ -2355,6 +2648,8 @@ void frmStatus::OnRefreshLogTimer(wxTimerEvent &event) } else { + logDirectory = wxEmptyString; + return; logDirectory = wxT("-"); if (connection->BackendMinimumVersion(8, 3)) logList->AppendItem(-1, wxString(_("logging_collector not enabled or log_filename misconfigured"))); @@ -2368,45 +2663,39 @@ void frmStatus::OnRefreshLogTimer(wxTimerEvent &event) if (logDirectory == wxT("-")) return; - if (isCurrent) + if (isCurrent && logfileName.Len()>0) { // check if the current logfile changed pgSet* set; if ((connection->BackendMinimumVersion(10, 0))) - set = connection->ExecuteSet(wxT("select size len from pg_stat_file(") + connection->qtDbString(logfileName) + wxT(")")); + set = connection->ExecuteSet(wxT("select size len from pg_stat_file(") + connection->qtDbString(logfileName) + wxT(")"),false); else set = connection->ExecuteSet(wxT("SELECT pg_file_length(") + connection->qtDbString(logfileName) + wxT(") AS len")); - if (set) + if (set ) { - newlen = set->GetLong(wxT("len")); + if (set->NumCols()>0) newlen = set->GetLong(wxT("len")); + else { + logDirectory = ""; // reRead directory + logfileName = ""; + newlen = 0; + showCurrent = true; + } delete set; } else { checkConnection(); + //logDirectory = ""; // reRead directory + logfileName = ""; return; } if (newlen > logfileLength) { - long lastrow = logList->GetItemCount(); - bool remote = lastrow-1 == logList->GetFocusedItem(); statusBar->SetStatusText(_("Refreshing log list.")); addLogFile(logfileName, logfileTimestamp, newlen, logfileLength, false); - statusBar->SetStatusText(_("Done.")); - if (bgColor == logList->GetBackgroundColour()) bgColor = wxColour("#afafaf"); else - { - bgColor = logList->GetBackgroundColour(); - } - if (remote) { - //logList->Select(lastrow - 1,false); - //logList->SetScrollPos(wxGA_VERTICAL, logList->GetItemCount() - 1, true); - //logList->Select(logList->GetItemCount() - 1); - logList->Focus(logList->GetItemCount() - 1); - - //logList->Show - } + statusBar->SetStatusText(_("Wait...")); // as long as there was new data, the logfile is probably the current // one so we don't need to check for rotation return; @@ -2437,7 +2726,7 @@ void frmStatus::OnRefreshLogTimer(wxTimerEvent &event) addLogLine(_("pgadmin:Logfile rotated."), false); wxDateTime *ts = (wxDateTime *)cbLogfiles->wxItemContainer::GetClientData(pos++); wxASSERT(ts != 0); - + if (logThread) logThread->BreakRead(); addLogFile(ts, skipFirst); skipFirst = false; @@ -2483,6 +2772,7 @@ void frmStatus::checkConnection() actionMenu->Enable(MNU_REFRESH, false); toolBar->EnableTool(MNU_REFRESH, false); statusBar->SetStatusText(_("Connection broken.")); + SetTitle(_("Connection broken.")); } } } @@ -2492,20 +2782,20 @@ void frmStatus::addLogFile(wxDateTime *dt, bool skipFirst) { pgSet* set; if (settings->GetASUTPstyle()) { - set = connection->ExecuteSet( - wxT("select current_setting('log_directory')||'/'||name filename,modification filetime,size len\n") - wxT(" FROM pg_ls_logdir() where modification = '") + DateToAnsiStr(*dt) + wxT("'::timestamp")); + wxString sql = "select current_setting('log_directory')||'/'||name filename,modification filetime,size len\n" + " FROM pg_ls_logdir() where name ~ '.csv' and modification >= '" + DateToAnsiStr(*dt) + "'::timestamp order by modification-'" + DateToAnsiStr(*dt) + "'::timestamp limit 1"; + set = connection->ExecuteSet(sql); } else set = connection->ExecuteSet( - wxT("SELECT filetime, filename, pg_file_length(filename) AS len ") - wxT(" FROM pg_logdir_ls() AS A(filetime timestamp, filename text) ") - wxT(" WHERE filetime = '") + DateToAnsiStr(*dt) + wxT("'::timestamp")); + wxT("SELECT modification filetime, name filename, size AS len ") + wxT(" FROM pg_ls_logdir()") + wxT(" WHERE modification = '") + DateToAnsiStr(*dt) + wxT("'::timestamp"),false); if (set) { logfileName = set->GetVal(wxT("filename")); logfileTimestamp = set->GetDateTime(wxT("filetime")); long len = set->GetLong(wxT("len")); - + //if (logThread) logThread->BreakRead(); logfileLength = 0; addLogFile(logfileName, logfileTimestamp, len, logfileLength, skipFirst); @@ -2547,19 +2837,29 @@ void frmStatus::addLogFile(const wxString &filename, const wxDateTime timestamp, else line = savedPartialLine; } + if (logThread) { + if (logThread->isReadyRows()) { + logThread->SetParameters(filename,len,read,savedPartialLine); + logThread->GoReadRows(); + return; + } + } wxString funcname = "pg_read_binary_file("; - if (!settings->GetASUTPstyle()) funcname = "pg_file_read("; + //if (!settings->GetASUTPstyle()) funcname = "pg_file_read("; + wxString msg = _("Reading log from server..."); while (len > read) { - statusBar->SetStatusText(_("Reading log from server...")); - pgSet *set = connection->ExecuteSet(wxT("SELECT ") + funcname + - connection->qtDbString(filename) + wxT(", ") + NumToStr(read) + wxT(", 50000)")); +#define PG_READ_BUFFER 500000 + float pr = 100.0 * read / len; + statusBar->SetStatusText(wxString::Format("%s %.2f MB (%.1f %%)", msg, len / 1048576.0, pr)); + wxString readsql = wxString::Format("select %s%s,%s, %d)", funcname, connection->qtDbString(filename), NumToStr(read), PG_READ_BUFFER); + pgSet *set = connection->ExecuteSet(readsql); if (!set) { connection->IsAlive(); return; } - + wxSafeYield(); char *raw1 = set->GetCharPtr(0); if (!raw1 || !*raw1) @@ -2568,7 +2868,7 @@ void frmStatus::addLogFile(const wxString &filename, const wxDateTime timestamp, break; } char* raw; - unsigned char m[50001]; + unsigned char m[PG_READ_BUFFER + 1]; if (settings->GetASUTPstyle()) { raw =( char *) &m[0]; @@ -2626,7 +2926,7 @@ void frmStatus::addLogFile(const wxString &filename, const wxDateTime timestamp, // str = line + wxTextBuffer::Translate(wxString(raw, set->GetConversion()), wxTextFileType_Unix); //} - +#undef PG_READ_BUFFER delete set; if (str.Len() == 0) @@ -2770,8 +3070,11 @@ void frmStatus::addLogLine(const wxString &str, bool formatted, bool csv_log_for if (!logFormatKnown) { logList->AppendItem(-1, str); - if (bgColor != logList->GetBackgroundColour()) logList->SetItemBackgroundColour(row, bgColor); - + int colorindex = nav->TryMarkItem(row, str); + if (colorindex>=0) + logList->SetItemBackgroundColour(row, nav->GetColorByIndex(colorindex)); + else + logList->SetItemBackgroundColour(row, logcol[addodd % 2]); } else if ((!csv_log_format) && str.Find(':') < 0) { @@ -3068,6 +3371,13 @@ void frmStatus::addLogLine(const wxString &str, bool formatted, bool csv_log_for } } +void frmStatus::OnLogKeyUp(wxKeyEvent& event) +{ + if (currentPane == PANE_LOG) { + if (nav->RunKeyCommand(event)) return; + } + event.Skip(); +} void frmStatus::emptyLogfileCombo() { @@ -3096,12 +3406,12 @@ int frmStatus::fillLogfileCombo() set = connection->ExecuteSet( wxT("select name filename,modification filetime\n") wxT(" FROM pg_ls_logdir() where name ~ '.csv'\n") - wxT(" ORDER BY modification DESC")); + wxT(" ORDER BY modification DESC"),false); else set = connection->ExecuteSet( - wxT("SELECT filename, filetime\n") - wxT(" FROM pg_logdir_ls() AS A(filetime timestamp, filename text) \n") - wxT(" ORDER BY filetime DESC")); + wxT("SELECT name filename,modification filetime\n") + wxT(" FROM pg_ls_logdir()\n") + wxT(" ORDER BY filetime DESC"),false); if (set) @@ -3128,7 +3438,27 @@ int frmStatus::fillLogfileCombo() delete set; } + if (count > 0) { + unsigned int i; + int maxWidth(0), width; + for (i = 0; i < cbLogfiles->GetCount(); i++) + { + cbLogfiles->GetTextExtent(cbLogfiles->GetString(i), &width, NULL); + if (width > maxWidth) + maxWidth = width; + } + //cbLogfiles->SetMinSize(wxSize(maxWidth + 2, -1)); + //int sz = wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, cbLogfiles); + int sz = 24; + cbLogfiles->SetSize(wxSize(maxWidth + sz, -1)); + toolBar->Realize(); + + wxSize newszT = toolBar->GetBestSize(); + manager.GetPane(wxT("toolBar")).BestSize(newszT); + //manager.GetPane(wxT("toolBar")).MinSize(newszT); + manager.Update(); + } return count; } @@ -3146,12 +3476,267 @@ void frmStatus::OnLoadLogfile(wxCommandEvent &event) if (ts != NULL && (!logfileTimestamp.IsValid() || *ts != logfileTimestamp)) { + if (logThread) logThread->BreakRead(); + logList->DeleteAllItems(); + nav->ClearMark(); + //bgColor = wxColour("#afafaf"); + //bgColor = logList->GetBackgroundColour(); + addodd = 0; addLogFile(ts, true); + nav->Refresh(); } } } +ReadLogThread::~ReadLogThread() { + s_CloseLog.Post(); +} +void ReadLogThread::BreakRead() { + if (!isReadyRows()) { + m_break = true; + while (!isReadyRows()) { + wxMilliSleep(20); + } + } + log_queue->Clear(); +} +void ReadLogThread::DoTerminate() { + m_exit = true; + if (isReadyRows()) { + s_goReadLog.Post(); + } + return; +} +void* ReadLogThread::Entry() { + int size_rows = 0; + while (!m_exit) + { + { + wxMutexLocker lock(s_mutexDBLogReading); + //s_mutexDBLogReading.Lock(); + //rows.clear(); + getFilename(); + } + if (m_exit) break; + s_goReadLog.Wait(); + } + return NULL; +} +void ReadLogThread::getFilename() { + pgSet* set; + if (logfileName.length() == 0) return; + if (m_exit || m_break) return; + if (!conn->IsAlive()) { + wxDateTime n = wxDateTime::Now(); + if (!nextrun.IsValid() || nextrun < n) { + if (!conn->Reconnect(false)) + { + wxTimeSpan sp(0, 2); + nextrun = wxDateTime::Now() + sp; + } + } + return; + } + readLogFile(logfileName, len, logfileLength, savedPartialLine); + + //if (namepage.IsEmpty()) namepage = "not connect"; + //if (m_notebook->GetPageText(0) != namepage) m_notebook->SetPageText(0, namepage); +} +void ReadLogThread::readLogFile(wxString logfileName, long& lenfile, long& logfileLength, wxString& savedPartialLine) { + wxString line; + + // If GPDB 3.3 and later, log is normally in CSV format. Let's get a whole log line before calling addLogLine, + // so we can do things smarter. + + // PostgreSQL can log in CSV format, as well as regular format. Normally, we'd only see + // the regular format logs here, because pg_logdir_ls only returns those. But if pg_logdir_ls is + // changed to return the csv format log files, we should handle it. + + bool csv_log_format = logfileName.Right(4) == wxT(".csv"); + if (csv_log_format && savedPartialLine.length() > 0) + { + if (logfileLength == 0) // Starting at beginning of log file + savedPartialLine.clear(); + line = savedPartialLine; + } + wxString funcname = "pg_read_binary_file("; + int countLine = 0; + long logf = logfileLength; + while (lenfile > logfileLength) + { + //statusBar->SetStatusText(_("Reading log from server...")); + if (m_exit) return; + +#define PG_READ_BUFFER 500000 + wxString readsql = wxString::Format("select %s%s,%s, %d,true)", funcname, conn->qtDbString(logfileName), NumToStr(logfileLength), PG_READ_BUFFER); + pgSet* set = conn->ExecuteSet(readsql,false); + if (!set) + { + conn->IsAlive(); + return; + } + if (set->NumRows() == 0 || set->NumCols() ==0 || set->GetVal(0).IsNull()) { + delete set; + break; + } + char* raw1 = set->GetCharPtr(0); + if (!raw1 || !*raw1) + { + delete set; + break; + } + char* rawbuff; + char m[PG_READ_BUFFER + 1]; + if (true) { + + rawbuff = &m[0]; + unsigned char c; + unsigned char* startChar; + unsigned char* startLine= (unsigned char*)&m[0]; + int pos = 0; + raw1 = raw1 + 2; // bytea data \x01cf23 .... + int utf8charLen = 0; + unsigned int unichar = 0; + unsigned int unicharcurrent = 0; + int shift; + while (*raw1 != 0) { + if (m_exit) return; + if (m_break) { + log_queue->Clear(); + return; + } + c = *raw1; + c = c - '0'; + if (c > 9) c = *raw1 - 'a' + 10; + raw1++; + m[pos] = c << 4; + c = *raw1 - '0'; + if (c > 9) c = *raw1 - 'a' + 10; + c = c | m[pos]; // hex string -> byte + m[pos] = c; + // check utf-8 char + if (utf8charLen == 0) { + startChar = (unsigned char*) &m[pos]; + + if (c >> 7 == 0) + utf8charLen = 1; + else if (c >> 5 == 0x6) + utf8charLen = 2; + else if (c >> 4 == 0xE) + utf8charLen = 3; + else if (c >> 5 == 0x1E) + utf8charLen = 4; + else + utf8charLen = 0; + // bad utf8 format + shift = 0; + unichar = c; + } + unicharcurrent = c << shift; + shift += 8; + unichar = unichar | unicharcurrent; + pos++; + raw1++; + utf8charLen--; + if (utf8charLen == 0) { + // utf-8 char complite + if (unichar == '\"' && csv_log_format) + inquote = !inquote; + //wxString linebuff(startChar, lencsvstr); + if (unichar == '\n' && !inquote) { + // end line + size_t lencsvstr = (unsigned char*)&m[pos] - startLine; + wxString linebuff(startLine, set->GetConversion(),lencsvstr); // include '\n' + if (line.length() > 0) { + linebuff = line + linebuff; + line.clear(); + } + startLine = (unsigned char*)&m[pos]; + //rows.push_back(linebuff.Trim()); + log_queue->Post(linebuff.Trim()); + countLine++; + } + + } + } + // + m[pos] = 0; + if (utf8charLen != 0) { + //read = startChar - &m[0]; + // remove bad utf-8 char + *startChar = 0; + pos = startChar- (unsigned char*)&m[0]; + // start position bad utf-8 char + } else + m[pos] = 0; + if (startLine != (unsigned char*)&m[pos]) { + // partial line + size_t lencsvstr = (unsigned char*)&m[pos] - startLine; + wxString linebuff(startLine, lencsvstr); // include '\n' + if (line.length() > 0) { + linebuff = line + linebuff; + line.clear(); + } + line = linebuff; + } + } + else { + rawbuff = raw1; + } + int l = strlen(rawbuff); + logfileLength += l; + //status->SetLabelText(wxString::Format("%s Load bytes %ld", host, logfileLength)); + + wxString str; + //str = line + wxTextBuffer::Translate(wxString(rawbuff, set->GetConversion()), wxTextFileType_Unix); + sendText(wxString::Format("@Load log line %d ...", countLine)); +#undef PG_READ_BUFFER + delete set; + + if (countLine == 0) + { + wxString msgstr = "@ The server log contains entries in multiple encodings and cannot be displayed by pgAdmin."; + //wxMessageBox(msgstr); + sendText(msgstr); + return; + } + + } + + savedPartialLine.clear(); + + if (!line.IsEmpty()) + { + // We finished reading to the end of the log file, but still have some data left + if (csv_log_format) + { + savedPartialLine = line; // Save partial log line for next read of the data file. + line.Clear(); + } + else + //my_view->AddRow(line.Trim()); + log_queue->Post(line.Trim()); + //rows.push_back(line.Trim()); + + } + if (logf==0) sendText(wxString::Format("Done %d", countLine)); +} + +void frmStatus::OnAddLabelTextThread(wxThreadEvent& event) { + wxString s = event.GetString(); + if (s[0] == '@') { + s = s.substr(1); + statusBar->SetStatusText(s); + return; + } + { + wxTimerEvent event; + OnRefreshLogTimer(event); + } + +} +/////////////////////////////// void frmStatus::OnRotateLogfile(wxCommandEvent &event) { @@ -3541,6 +4126,8 @@ void frmStatus::OnSelStatusItem(wxListEvent &event) #endif currentPane = PANE_STATUS; cbRate->SetValue(rateToCboString(statusRate)); + statusList->SetFocus(); + ActivatePane("Activity"); if (connection && connection->BackendMinimumVersion(8, 0)) { if(statusList->GetSelectedItemCount() > 0) @@ -3571,7 +4158,14 @@ void frmStatus::OnSelStatusItem(wxListEvent &event) editMenu->Enable(MNU_COPY, statusList->GetFirstSelected() >= 0); actionMenu->Enable(MNU_COPY_QUERY, statusList->GetFirstSelected() >= 0); toolBar->EnableTool(MNU_COPY_QUERY, statusList->GetFirstSelected() >= 0); - OnRefresh(event); + + //OnRefresh(event); + wxTimerEvent evt; + OnRefreshStatusTimer(evt); + OnRefreshLocksTimer(evt); + OnRefreshXactTimer(evt); + OnRefreshQuerystateTimer(evt); + } @@ -3586,6 +4180,8 @@ void frmStatus::OnSelLockItem(wxListEvent &event) manager.Update(); #endif currentPane = PANE_LOCKS; + lockList->SetFocus(); + ActivatePane("Locks"); cbRate->SetValue(rateToCboString(locksRate)); if (connection && connection->BackendMinimumVersion(8, 0)) { @@ -3631,6 +4227,8 @@ void frmStatus::OnSelXactItem(wxListEvent &event) manager.Update(); #endif currentPane = PANE_XACT; + xactList->SetFocus(); + ActivatePane("Transactions"); cbRate->SetValue(rateToCboString(xactRate)); if(xactList->GetSelectedItemCount() > 0) { @@ -3669,6 +4267,8 @@ void frmStatus::OnSelQuerystateItem(wxListEvent &event) manager.Update(); #endif currentPane = PANE_QUERYSTATE; + querystateList->SetFocus(); + ActivatePane("Querystate"); cbRate->SetValue(rateToCboString(querystateRate)); { toolBar->EnableTool(MNU_COMMIT, false); @@ -3688,6 +4288,25 @@ void frmStatus::OnSelQuerystateItem(wxListEvent &event) toolBar->EnableTool(MNU_COPY_QUERY, false); } +void frmStatus::ActivatePane(wxString name) { + if (!manager.GetPane(name).HasFlag(wxAuiPaneInfo::optionActive)) { + //manager.GetPane("Logfile").HasFlag(wxAuiPaneInfo::optionActive); + int i, pane_count; + wxAuiPaneInfo* active_paneinfo = NULL; + for (unsigned int i = 0; i < manager.GetAllPanes().GetCount(); i++) + { + wxAuiPaneInfo& pane = manager.GetAllPanes()[i]; + pane.state &= ~wxAuiPaneInfo::optionActive; + if (pane.name == name) + { + pane.state |= wxAuiPaneInfo::optionActive; + active_paneinfo = &pane; + } + } + if (active_paneinfo) manager.Update(); + } +} + void frmStatus::OnSelLogItem(wxListEvent &event) { @@ -3701,7 +4320,8 @@ void frmStatus::OnSelLogItem(wxListEvent &event) #endif currentPane = PANE_LOG; cbRate->SetValue(rateToCboString(logRate)); - + logList->SetFocus(); + ActivatePane("Logfile"); // if there's no log, don't enable items if (logDirectory != wxT("-")) { @@ -3720,6 +4340,7 @@ void frmStatus::OnSelLogItem(wxListEvent &event) editMenu->Enable(MNU_COPY, logList->GetFirstSelected() >= 0); actionMenu->Enable(MNU_COPY_QUERY, false); toolBar->EnableTool(MNU_COPY_QUERY, false); + event.Skip(); } @@ -3913,6 +4534,16 @@ void frmStatus::OnRightClickQuerystateGrid(wxListEvent &event) { querystateList->PopupMenu(querystatePopupMenu, event.GetPoint()); } +void frmStatus::OnLogContextMenu(wxCommandEvent& event) { + nav->OnContextMenu(event); +} + +void frmStatus::OnRightClickLogGrid(wxListEvent& event) +{ + wxMenu* logListPopupMenu; + logListPopupMenu = nav->GetPopupMenu(); + logList->PopupMenu(logListPopupMenu, event.GetPoint()); +} void frmStatus::OnChgColSizeStatusGrid(wxListEvent &event) diff --git a/include/ctl/wxTopActivity.h b/include/ctl/wxTopActivity.h new file mode 100644 index 0000000..00ee48a --- /dev/null +++ b/include/ctl/wxTopActivity.h @@ -0,0 +1,583 @@ +#pragma once +#include +#include "utils/WaitSample.h" +#include "wx/popupwin.h" +#include "wx/dataview.h" +#include "wx/headerctrl.h" +#include +#include +//#include "utils/misc.h" +// ---------------------------------------------------------------------------- +// MyCustomRendererText +// ---------------------------------------------------------------------------- +extern std::vector sort_vec_map(const std::vector& src, int& sum); +#define sepListWait ";" +extern int s_pid_HIGHLIGH; +class MyCustomRendererGraph : public wxDataViewCustomRenderer +{ +public: + // This renderer can be either activatable or editable, for demonstration + // purposes. In real programs, you should select whether the user should be + // able to activate or edit the cell and it doesn't make sense to switch + // between the two -- but this is just an example, so it doesn't stop us. + explicit MyCustomRendererGraph(wxDataViewCellMode mode, int column) + : wxDataViewCustomRenderer("string", mode, wxALIGN_LEFT) + { + EnableEllipsize(wxELLIPSIZE_END); + col = column; + } + + virtual bool Render(wxRect rect, wxDC* dc, int state) wxOVERRIDE + { + wxString l; + wxRect orig = rect; + if (col < 2) { + l = m_value; + if (m_value == "ffffffffffffffff" || m_value == "-1") { + l = "SUM"; + RenderText(l, 0, rect, dc, state); + return true; + } + } + + if (col == 0) { + if (m_value[0] == '*') { + l = m_value.AfterFirst('*'); + + // wxFont fn = dc->GetFont().Italic(); + // wxDCFontChanger nfont(*dc, fn); + dc->SetBrush(*wxLIGHT_GREY_BRUSH); + dc->SetPen(*wxTRANSPARENT_PEN); + rect.Deflate(1); + dc->DrawRoundedRectangle(rect, 3); + RenderText(l, 0, rect, dc, state); + } + else + { + l = m_value; + RenderText(l, 0, rect, dc, state); + } + + return true; + + } + if (col == 1) { + RenderText(l, 0, rect, dc, state); + return true; + } + //dc->SetBrush( *wxLIGHT_GREY_BRUSH ); + dc->SetBrush(*wxYELLOW_BRUSH); + //dc->SetPen(*wxTRANSPARENT_PEN); + dc->SetPen(*wxBLACK_PEN); + rect.Deflate(1); + //WaitSample*ws= static_cast(GetView())->GetSample(); + //dc->DrawRoundedRectangle( rect, 3 ); + wxFont fn = dc->GetFont(); + fn.SetPointSize(fn.GetPointSize() - 1); + wxDCFontChanger nfont(*dc, fn); + + wxString s = m_value, t; + wxStringTokenizer tk(s, sepListWait, wxTOKEN_DEFAULT); + + bool isDis = true; + bool isGrp = true; + int f = 0; + float itog = 0; + int widt = orig.width - 20; + wxPoint p(orig.x, orig.y); + while (tk.HasMoreTokens()) + { + l = tk.GetNextToken(); + if (f == 0) { + float tmp; + l = l.AfterLast(' '); + wxSscanf(l, "%f", &tmp); + itog = tmp; + float sek = itog / 1000; + wxString tt = wxString::Format("%.1f", sek); // time sec + wxSize sz = GetTextExtent(tt); + wxRect drw(orig.x + orig.width - sz.x - 2, orig.y, sz.x + 2, orig.GetHeight()); + wxRect npos(0, 0, sz.x, sz.y); + npos = npos.CentreIn(drw); + dc->DrawText(tt, npos.x, npos.y); + widt = orig.width - sz.x - 2; + } + if (f > 0) { + float tmp; + wxString w; + long cl; + l = l.AfterFirst(' '); + wxSscanf(l, "%ld %f", &cl, &tmp); + + wxColour c(cl); + //c.Set(cl); + dc->SetBrush(c); + + + int ww = widt * tmp; + wxRect drw(p.x, p.y, ww, rect.GetHeight()); + float sek = itog * tmp / 1000; + wxString tt = wxString::Format("%.1f", sek); // time sec + wxSize sz = GetTextExtent(tt); + wxRect npos(0, 0, sz.x, sz.y); + npos = npos.CentreIn(drw); + dc->DrawRectangle(drw); + { + wxColour fg(ContrastColorBlackOrWhite(c)); + wxDCTextColourChanger setfg(*dc, fg); + if (sz.GetWidth() < drw.GetWidth()) dc->DrawText(tt, npos.x, npos.y); + } + p.x = p.x + ww; + + } + f++; + + } + + return true; + } + + virtual bool ActivateCell(const wxRect& WXUNUSED(cell), + wxDataViewModel* WXUNUSED(model), + const wxDataViewItem& WXUNUSED(item), + unsigned int WXUNUSED(col), + const wxMouseEvent* mouseEvent) wxOVERRIDE + { + return false; + } + + virtual wxSize GetSize() const wxOVERRIDE + { + wxSize txtSize = GetTextExtent(m_value); + int lines = m_value.Freq('\n') + 1; + if (lines > 1) { + // wxLogMessage("MyCustomRendererText GetSize() %s", position); + txtSize.SetHeight(txtSize.GetHeight() * lines + 1 * lines); + } + else { + #ifdef __WXGTK__ + txtSize.SetHeight(txtSize.GetHeight() + 3); + #else + txtSize.SetHeight(-1); + #endif + + + } + if (col == 2) txtSize.SetWidth(-1); + else + { + //maxw = txtSize.GetWidth(); + //maxw=wxMax(txtSize.GetWidth(), maxw); + txtSize.SetWidth(txtSize.GetWidth() + 1); + } + return txtSize; + + //return GetView()->FromDIP(wxSize(60, 20)); + } + + virtual bool SetValue(const wxVariant& value) wxOVERRIDE + { + m_value = value.GetString(); + return true; + } + + virtual bool GetValue(wxVariant& WXUNUSED(value)) const wxOVERRIDE { return true; } + +#if wxUSE_ACCESSIBILITY + virtual wxString GetAccessibleDescription() const wxOVERRIDE + { + return m_value; + } +#endif // wxUSE_ACCESSIBILITY + + virtual bool HasEditorCtrl() const wxOVERRIDE { return false; } +private: + wxString m_value; + int col; + int maxw = -1; +}; + +class MyIndexListModel : public wxDataViewIndexListModel +{ +public: + MyIndexListModel(WaitSample* w) { ws = w; } + + void SetAllRows(const std::vector& keys, const std::map& wait, bool isfp) { + k = keys; + w = wait; + //IsFirstPid = isfp; + + Reset(keys.size()); + + } + key3 GetRowValue(long row) { + key3 r{}; + if (row >= 0 && row < k.size()) { + r = k[row]; + } + return r; + } + // Implement base class pure virtual methods. + unsigned GetCount() const wxOVERRIDE { return k.size(); } + void GetValueByRow(wxVariant& val, unsigned row, unsigned col) const wxOVERRIDE + { + //val=wxString::Format("r:%d,c:%d",row,col); + //val = m_strings[row]; + //if (row + 1 < m_strings.Count() && col == 1 ) val = m_strings[row + 1]; + bool ishint = false; + int r = row; + if (!val.IsNull()) { + //r = r * -1; + ishint = true; + } + if (k.size() > 0) { + key3 kk = k.at(r); + if ((col == 0)) { + long ttmp = kk.pid; + if (kk.sum > 0) val = wxString::Format("*%ld", ttmp); // backend + else + val = wxString::Format("%ld", ttmp); + + } + else + val = wxString::Format("%llx", kk.qid); + if (col == 2) { + vec_int v = w.at(kk); + int sz = v.size(); + val = wxString::Format("count w=%d", sz); + int itog = 0; + std::vector map_sum_all = sort_vec_map(v, itog); + int period = ws->getPeriod(); + int total = itog; + wxString h; + if (total != 0) { + wxString x = wxString::Format("all %ld", (long)itog * period); + for (int i = 0; i < map_sum_all.size(); i++) { + int wait_index = map_sum_all[i]; + if (v[wait_index] == 0) continue; + float w_sum = (v[wait_index] / (float)total); + float sek = ((period * v[wait_index]) / 1000.0); + wxString w_name = ws->GetName(wait_index, WAIT_NAME); + wxString w_grp = ws->GetName(wait_index, WAIT_GRP); + wxString full = ws->GetName(wait_index, WAIT_FULL); + long clr = ws->GetColorByWaitName(full); + wxString pr = wxString::Format("%s %ld %.3f", w_name, clr, w_sum); + if (ishint) { + if (!h.IsEmpty()) h += "\n"; + h.Append(wxString::Format("%-8.1f%-15s", sek, w_name)); + } + else { + if (!x.IsEmpty()) x += sepListWait; + x += pr; + } + } + if (ishint) val = h; + else + val = x; + } + + } + } + } + bool SetValueByRow(const wxVariant&, unsigned, unsigned) wxOVERRIDE + { + return false; + } + unsigned GetRow(const wxDataViewItem& item) const wxOVERRIDE { return (unsigned long)item.GetID()-1; } // 0 row = header + unsigned int GetColumnCount() const wxOVERRIDE { return 0; } + wxString GetColumnType(unsigned int) const wxOVERRIDE { return ""; } + + +private: + bool IsFirstPid = true; + std::vector k; + std::map w; + WaitSample* ws = NULL; + wxDECLARE_NO_COPY_CLASS(MyIndexListModel); +}; + +//---------------------------------------------------------------------------- +// SimpleTransientPopup +//---------------------------------------------------------------------------- +class wxTopActivity; +class topDataViewCtrl; + +class SimpleTransientPopup : public wxFrame +{ +public: + friend class wxTopActivity; + friend class topDataViewCtrl; + SimpleTransientPopup(wxWindow* parent, bool scrolled, wxTopActivity* small_ctl, wxPoint p,wxString title); + virtual ~SimpleTransientPopup(); + + // wxPopupTransientWindow virtual methods are all overridden to log them + +private: + wxScrolledWindow* m_panel; + wxTopActivity* top; + topDataViewCtrl* dvc; + wxObjectDataPtr m_index_list_model; + wxPoint mouseDownPos_; + bool dragg = false; + wxTimer m_taskTimer; +private: + void OnMouse(wxMouseEvent& event); + void OnSize(wxSizeEvent& event); + void OnSetFocus(wxFocusEvent& event); + void OnKillFocus(wxFocusEvent& event); + void OnTimerEvent(wxTimerEvent& pEvent); + void OnClose(wxCommandEvent& event); + +private: + wxDECLARE_ABSTRACT_CLASS(SimpleTransientPopup); + wxDECLARE_EVENT_TABLE(); +}; + +struct title_info { + bool iner = false; + bool remove; + bool down_line; + int total; + wxString title; + +}; +/// +/// Графический элемент отображающий данные WaitSample +/// Может использоваться РІ РґРІСѓС… режимах. +/// +class wxTopActivity : public wxControl +{ + WaitSample* ws; + wxString m_title; + wxSize setsize; + wxArrayString seriosName; + std::vector xAxis; + std::vector yAxis; + std::vector val; + std::vector colors; + std::vector m_title_i; + std::map m_collapse; + std::map m_sumtotal; + wxPoint mouse, mouseS; + wxRect m_area; + int m_click = 0; + int m_fix_detail_idx = -1; + // fix sel Range + wxDateTime fix_pos_L; + wxDateTime fix_pos_R; + + wxPoint m_fix_pos; // context win + wxString m_filter_detail; + long long m_qid_filter = -1; + bool m_regroup = false; + int m_lastInterval = 0; + int m_RightTime = -1; + wxString m_filter; + int m_agg_int = 5000; + int m_count_wait; + int m_inter[9] = { + 5000 , + 10000 , + 30000 ,//30 s + 60000 ,//1 min + 5 * 60000 ,//5 min + 10 * 60000,//10 min + 15 * 60000,//10 min + 30 * 60000,//30 min + 60 * 60000 //60 min + }; + SimpleTransientPopup* m_simplePopup; + void paintSelRange(wxDC& dc, int width_sample); +public: + wxTopActivity(wxWindow* parent, WaitSample* WS, wxSize sz); + wxSize DoGetBestClientSize(); + void setViewRange(int m_aggregate_interval, int RightTime); + WaitSample* getViewRange(int& m_aggregate_interval, int& RightTime); + void paintEvent(wxPaintEvent& evt); + void OnEraseBackground(wxEraseEvent& event); + void paintNow(); + void SetFilter(long long qid); + /// + /// Возвращает время указаной границы + /// + /// true для левой границы, инаце правая + /// + int getTimeSelRange(bool isLeftRange); + void render(wxDC& dc); + + // some useful events + void mouseMoved(wxMouseEvent& event); + void mouseDown(wxMouseEvent& event); + void mouseWheelMoved(wxMouseEvent& event); + void mouseReleased(wxMouseEvent& event); + void rightClick(wxMouseEvent& event); + void mouseLeftWindow(wxMouseEvent& event); + void keyPressed(wxKeyEvent& event); + void keyReleased(wxKeyEvent& event); + void resize(wxSizeEvent& event); + DECLARE_EVENT_TABLE() +}; + +class topDataViewCtrl : + public wxDataViewCtrl +{ +public: + topDataViewCtrl(wxWindow* parent, wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, long style = 0, + wxTopActivity* topactive = NULL, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxASCII_STR(wxDataViewCtrlNameStr) + ) : wxDataViewCtrl(parent, id, pos, size, style, validator, name) + { + //SetMinSize(wxSize(300,200)); + top = topactive; + w = NULL; + w = top->getViewRange(agg, right_g); + Bind(wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, [&](wxDataViewEvent& event) { + int col = event.GetColumn(); + if (GetColumn(col)->GetTitle() == "PID") { + ignoreBG = !ignoreBG; + CalcRowsDataView(true, ispidfirst); + Refresh(); + + } + }); + Bind(wxEVT_DATAVIEW_ITEM_ACTIVATED, [&](wxDataViewEvent& event) { + int col = event.GetColumn(); + wxDataViewItem item(event.GetItem()); + long row = (long)item.GetID(); + row--; + if (col == 1) //qid + { + MyIndexListModel* m = static_cast(GetModel()); + key3 k = m->GetRowValue(row); + if (k.qid != -1) top->SetFilter(k.qid); + } + if (col == 0) { //pid + MyIndexListModel* m = static_cast(GetModel()); + key3 k = m->GetRowValue(row); + if (k.pid>0) s_pid_HIGHLIGH = k.pid; + // else + // s_pid_HIGHLIGH = -1; + } + }); + + Bind(wxEVT_DATAVIEW_COLUMN_REORDERED, [&](wxDataViewEvent& event) { + wxDataViewColumn* const col = event.GetDataViewColumn(); + if (!col) + { + return; + } + + ispidfirst = col->GetTitle() == "PID" && event.GetColumn() == 0; + if (!ispidfirst) ispidfirst = col->GetTitle() == "QID" && event.GetColumn() == 1; + CalcRowsDataView(true, ispidfirst); + Refresh(); + }); + GetMainWindow()->Bind(wxEVT_MOTION, [&](wxMouseEvent& event) { + if (event.Dragging()) + return; + + wxClientDC dc(GetMainWindow()); + PrepareDC(dc); + + //wxPoint logPos(event.GetLogicalPosition(dc)); + //wxPoint mc= GetMainWindow()->ScreenToClient(event.GetPosition()); + wxPoint mc = event.GetPosition(); + wxString position; + //position = wxString::Format("x=%d y=%d", logPos.x, logPos.y); + //wxLogMessage("Mouse pos %s", position); + int dy = 0; + wxSize sz; +#ifdef WIN32 + wxHeaderCtrl* const header = GenericGetHeader(); + if (header) { + sz = header->GetSize(); + //header->Refresh(); + dy = sz.GetHeight(); + } + mc.y += dy; +#else + mc.y += 18; // only linux compile +#endif + wxDataViewItem item; + wxDataViewColumn* column; + + HitTest(mc, item, column); + if (item != NULL && column != NULL) + { + int row = (long)item.GetID() - 1; + int ncol = column->GetModelColumn(); + if (row >= 0) { + if (column && column->GetModelColumn() == 2) { + wxVariant vr; + vr = "gethint"; + if ((lastcol != ncol) || (lastrow != row)) { + MyIndexListModel* m = static_cast(GetModel()); + m->GetValueByRow(vr, row, ncol); + GetMainWindow()->SetToolTip(vr.GetString()); + lastrow = row; + lastcol = ncol; + } + + } + else if (column && column->GetModelColumn() == 0 ) { + // PID + MyIndexListModel* m = static_cast(GetModel()); + key3 k=m->GetRowValue(row); + if (k.sum > 0) { + if (((lastcol != ncol) || (lastrow != row))) { + wxString s = w->GetBackendTypeName(k.sum); + GetMainWindow()->SetToolTip(s); + lastrow = row; + lastcol = ncol; + + } + } + else { GetMainWindow()->UnsetToolTip(); lastcol = -1; + } + } + else + { + GetMainWindow()->UnsetToolTip(); + lastcol = -1; + } + } + } + else + { + GetMainWindow()->UnsetToolTip(); + lastcol = -1; + } + + }); + + } + WaitSample* GetSample() { return w; } + void BuildColumn(int mode); + bool CalcRowsDataView(bool force, bool IsPidFirst); + //void AddRow(wxString csvtext); + //void OnMouseMove(wxMouseEvent& event); + //void OnMouseDown(wxMouseEvent& event); + //void OnKEY_DOWN(wxKeyEvent& event); + //void OnKEY_UP(wxKeyEvent& event); + //void OnEVT_DATAVIEW_COLUMN_HEADER_CLICK(wxDataViewEvent& event); + //void OnEVT_DATAVIEW_CONTEXT_MENU(wxCommandEvent& event); + //void OnEVT_DATAVIEW_SELECTION_CHANGED(wxDataViewEvent& event); + //void OnContextMenu(wxDataViewEvent& event); + + DECLARE_EVENT_TABLE() + + +private: + int lastrow = -1, lastcol = 1; + int agg, right_g, left_g; + bool ignoreBG = false; + bool ispidfirst = true; + wxTopActivity* top; + WaitSample* w; +}; + +#undef sepListWait + diff --git a/include/dlg/dlgClasses.h b/include/dlg/dlgClasses.h index c8b44b1..85d5b3c 100644 --- a/include/dlg/dlgClasses.h +++ b/include/dlg/dlgClasses.h @@ -94,7 +94,7 @@ protected: wxString dlgName; wxString lastFilename, lastDir, lastPath; wxString recentKey; - wxMenu *fileMenu, *editMenu, *viewMenu, *recentFileMenu, *helpMenu; + wxMenu *fileMenu, *editMenu, *viewMenu, *recentFileMenu, *helpMenu, *waitMenu; wxStatusBar *statusBar; wxMenuBar *menuBar; ctlMenuToolbar *toolBar; diff --git a/include/frm/frmStatus.h b/include/frm/frmStatus.h index be80b3b..337d7d5 100644 --- a/include/frm/frmStatus.h +++ b/include/frm/frmStatus.h @@ -22,57 +22,63 @@ // wxAUI #include +#include #include "dlg/dlgClasses.h" #include "utils/factory.h" #include "ctl/ctlAuiNotebook.h" +#include "ctl/ctlNavigatePanel.h" +#include "utils/WaitSample.h" +#include "ctl/wxTopActivity.h" enum { - CTL_RATECBO = 250, - CTL_REFRESHBTN, - CTL_CANCELBTN, - CTL_TERMINATEBTN, - CTL_COMMITBTN, - CTL_ROLLBACKBTN, - CTL_LOGCBO, - CTL_ROTATEBTN, - CTL_STATUSLIST, - CTL_LOCKLIST, - CTL_XACTLIST, - CTL_LOGLIST, - CTL_QUERYSTATELIST, - MNU_STATUSPAGE, - MNU_LOCKPAGE, - MNU_XACTPAGE, - MNU_LOGPAGE, - MNU_QUERYSTATEPAGE, - MNU_TERMINATE, - MNU_COMMIT, - MNU_ROLLBACK, - MNU_COPY_QUERY, - MNU_CLEAR_FILTER_SERVER_STATUS, - MNU_COPY_QUERY_PLAN, - MNU_HIGHLIGHTSTATUS, - MNU_QUERYSTATEVERBOSE, - MNU_QUERYSTATETIME, - MNU_QUERYSTATEBUFFER, - MNU_QUERYSTATETRIGGER, - TIMER_REFRESHUI_ID, - TIMER_STATUS_ID, - TIMER_LOCKS_ID, - TIMER_XACT_ID, - TIMER_LOG_ID, - TIMER_QUERYSTATE_ID + CTL_RATECBO = 250, + CTL_REFRESHBTN, + CTL_CANCELBTN, + CTL_TERMINATEBTN, + CTL_COMMITBTN, + CTL_ROLLBACKBTN, + CTL_LOGCBO, + CTL_ROTATEBTN, + CTL_STATUSLIST, + CTL_LOCKLIST, + CTL_XACTLIST, + CTL_LOGLIST, + CTL_QUERYSTATELIST, + MNU_STATUSPAGE, + MNU_LOCKPAGE, + MNU_XACTPAGE, + MNU_LOGPAGE, + MNU_QUERYSTATEPAGE, + MNU_TERMINATE, + MNU_COMMIT, + MNU_ROLLBACK, + MNU_COPY_QUERY, + MNU_CLEAR_FILTER_SERVER_STATUS, + MNU_COPY_QUERY_PLAN, + MNU_HIGHLIGHTSTATUS, + MNU_QUERYSTATEVERBOSE, + MNU_QUERYSTATETIME, + MNU_QUERYSTATEBUFFER, + MNU_QUERYSTATETRIGGER, + MNU_WAITENABLE, + MNU_WAITSAVE, + TIMER_REFRESHUI_ID, + TIMER_STATUS_ID, + TIMER_LOCKS_ID, + TIMER_XACT_ID, + TIMER_LOG_ID, + TIMER_QUERYSTATE_ID }; enum { - PANE_STATUS = 1, - PANE_LOCKS, - PANE_XACT, - PANE_LOG, - PANE_QUERYSTATE + PANE_STATUS = 1, + PANE_LOCKS, + PANE_XACT, + PANE_LOG, + PANE_QUERYSTATE }; @@ -87,7 +93,7 @@ enum #ifdef __WXGTK__ #define FRMSTATUS_DEFAULT_PERSPECTIVE wxT("layout2|name=Activity;caption=Activity;state=6309884;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=Locks;caption=Locks;state=6293500;dir=4;layer=0;row=0;pos=1;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=Transactions;caption=Prepared Transactions;state=6293500;dir=4;layer=0;row=0;pos=2;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=Querystate;caption=QueryState;state=6293502;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=Logfile;caption=Logfile;state=6293500;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=toolBar;caption=Tool bar;state=2108144;dir=1;layer=10;row=0;pos=0;prop=100000;bestw=690;besth=39;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|dock_size(4,0,0)=800|dock_size(5,0,0)=22|dock_size(1,10,0)=41|") #else -#define FRMSTATUS_DEFAULT_PERSPECTIVE wxT("layout2|name=Activity;caption=Activity;state=6293500;dir=4;layer=0;row=1;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=174;floaty=216;floatw=578;floath=282|name=Locks;caption=Locks;state=6293500;dir=4;layer=0;row=1;pos=2;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=136;floaty=339;floatw=576;floath=283|name=Transactions;caption=Transactions;state=6293500;dir=4;layer=0;row=1;pos=3;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=133;floaty=645;floatw=577;floath=283|name=Querystate;caption=Query State;state=6309884;dir=4;layer=0;row=1;pos=1;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=154;floaty=255;floatw=1360;floath=751|name=Logfile;caption=Logfile;state=6293500;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=toolBar;caption=toolBar;state=2108144;dir=1;layer=10;row=0;pos=0;prop=100000;bestw=766;besth=39;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=586;floaty=525;floatw=483;floath=49|dock_size(1,10,0)=25|dock_size(4,0,1)=1115|dock_size(5,0,0)=22|") +#define FRMSTATUS_DEFAULT_PERSPECTIVE wxT("layout2|name=Activity;caption=Activity;state=6293500;dir=4;layer=0;row=1;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=174;floaty=216;floatw=578;floath=282|name=Locks;caption=Locks;state=6293500;dir=4;layer=0;row=1;pos=2;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=136;floaty=339;floatw=576;floath=283|name=Transactions;caption=Transactions;state=6293500;dir=4;layer=0;row=1;pos=3;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=133;floaty=645;floatw=577;floath=283|name=Querystate;caption=Query State;state=6309884;dir=4;layer=0;row=1;pos=4;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=154;floaty=255;floatw=800;floath=751|name=Logfile;caption=Logfile;state=6293500;dir=4;layer=0;row=1;pos=5;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=150;floaty=90;floatw=400;floath=800|name=toolBar;caption=toolBar;state=2108144;dir=1;layer=10;row=0;pos=0;prop=100000;bestw=766;besth=39;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=586;floaty=525;floatw=483;floath=49|dock_size(1,10,0)=25|dock_size(4,0,1)=1115|dock_size(5,0,0)=22|") #endif #endif @@ -96,175 +102,268 @@ static wxCriticalSection gs_critsect; // Class declarations +static wxMutex s_mutexDBLogReading; +static wxSemaphore s_goReadLog(0, 1); +static wxSemaphore s_ResultOkLog(0, 1); +static wxSemaphore s_CloseLog(0, 1); + +class ReadLogThread : public wxThread +{ +public: + ReadLogThread(pgConn *conlog, wxWindow* p, wxMessageQueue *queue) + { + + log_queue = queue; + theParent = p; + logfileName = wxEmptyString; + savedPartialLine=wxEmptyString; + logfileLength=0; + len=0; + conn = conlog; + //nextrun = wxDateTime(0); + } + ~ReadLogThread(); + void DoTerminate(); + bool IsTerminate() { return m_exit; } + void SetParameters(wxString plogfileName, long plenfile, long plogfileLength, wxString psavedPartialLine) { + logfileName = plogfileName; + len = plenfile; + logfileLength = plogfileLength; + if (plogfileLength==0) inquote = false; + savedPartialLine = psavedPartialLine; + } + long GetReadByteFile(wxString &part) { + part = savedPartialLine; + return logfileLength; + } + bool isReadyRows() { + wxMutexError e = s_mutexDBLogReading.TryLock(); + if (e == wxMUTEX_NO_ERROR) { + s_mutexDBLogReading.Unlock(); + return true; + } + return false; + } + void BreakRead(); + bool isBreak() { return m_break; } + bool GoReadRows() { + m_break = false; + wxSemaError e = s_goReadLog.Post(); + if (e == wxSEMA_NO_ERROR) { + return true; + } + //wxLogError("Semafore return error"); + return false; + } + + virtual void* Entry(); +private: + void readLogFile(wxString logfileName, long& lenfile, long& logfileLength, wxString& savedPartialLine); + void getFilename(); + void sendText(wxString s) { + wxThreadEvent e(wxEVT_THREAD); + e.SetString(s); + theParent->GetEventHandler()->AddPendingEvent(e); + } + wxDateTime nextrun; + wxWindow* theParent; + bool m_exit = false; + bool m_break = false; + pgConn *conn; + wxMessageQueue* log_queue; + // + wxString logfileName; + wxString savedPartialLine; + long logfileLength; + long len; + bool inquote = false; + +}; class frmStatus : public pgFrame { public: - frmStatus(frmMain *form, const wxString &_title, pgConn *conn); - ~frmStatus(); - void Go(); + frmStatus(frmMain *form, const wxString &_title, pgConn *conn); + ~frmStatus(); + void Go(); private: - wxAuiManager manager; + wxAuiManager manager; - frmMain *mainForm; - pgConn *connection, *locks_connection; + frmMain *mainForm; + pgConn *connection, *locks_connection, *logconn; - wxString logFormat; - bool logHasTimestamp, logFormatKnown; - int logFmtPos; + wxString logFormat,logFindString; + bool logHasTimestamp, logFormatKnown; + int logFmtPos; + long logFinditem=-1; + ReadLogThread *logThread=NULL; + wxMessageQueue log_queue; + wxDateTime logfileTimestamp, latestTimestamp; + wxString logDirectory, logfileName; - wxDateTime logfileTimestamp, latestTimestamp; - wxString logDirectory, logfileName; + wxString savedPartialLine; - wxString savedPartialLine; + bool showCurrent, isCurrent; - bool showCurrent, isCurrent; + long backend_pid; + int wait_event_type_col; + bool isrecovery,track_commit_timestamp, is_read_log; + bool wait_sample, wait_enable, wait_save; + bool frm_exit = false; // need close form + bool logisread = false; // need close form + WaitSample WS; + wxTopActivity* top_small; + wxString first_tt; + bool loaded; + long logfileLength; + wxColour logcol[2]; + int addodd = 0; + int currentPane; - long backend_pid; - int wait_event_type_col; - bool isrecovery,track_commit_timestamp; - bool loaded; - long logfileLength; - wxColour bgColor; + int statusSortColumn; + wxString statusSortOrder; + int lockSortColumn; + wxString lockSortOrder; + int xactSortColumn; + wxString xactSortOrder; - int currentPane; + wxComboBox *cbRate; + wxComboBox *cbLogfiles; + wxButton *btnRotateLog; + ctlComboBoxFix *cbDatabase; - int statusSortColumn; - wxString statusSortOrder; - int lockSortColumn; - wxString lockSortOrder; - int xactSortColumn; - wxString xactSortOrder; + wxTimer *refreshUITimer; + wxTimer *statusTimer, *locksTimer, *xactTimer, *logTimer, *querystateTimer; + int statusRate, locksRate, xactRate, logRate, querystateRate; + + ctlListView *statusList; + ctlListView *lockList; + ctlListView *xactList; + ctlListView *logList; + ctlNavigatePanel* nav; + ctlListView *querystateList; - wxComboBox *cbRate; - wxComboBox *cbLogfiles; - wxButton *btnRotateLog; - ctlComboBoxFix *cbDatabase; + wxMenu *actionMenu; + wxMenu *statusPopupMenu; + wxMenu *lockPopupMenu; + wxMenu *xactPopupMenu; + wxMenu *querystatePopupMenu; + wxString queryplan; + wxArrayString queries; + wxArrayInt filterColumn; + wxArrayString filterValue; - wxTimer *refreshUITimer; - wxTimer *statusTimer, *locksTimer, *xactTimer, *logTimer, *querystateTimer; - int statusRate, locksRate, xactRate, logRate, querystateRate; + int statusColWidth[12], lockColWidth[10], xactColWidth[5], querystateColWidth[5]; - ctlListView *statusList; - ctlListView *lockList; - ctlListView *xactList; - ctlListView *logList; - ctlListView *querystateList; + int cboToRate(); + wxString rateToCboString(int rate); - wxMenu *actionMenu; - wxMenu *statusPopupMenu; - wxMenu *lockPopupMenu; - wxMenu *xactPopupMenu; - wxMenu *querystatePopupMenu; - wxString queryplan; - wxArrayString queries; - wxArrayInt filterColumn; - wxArrayString filterValue; - - int statusColWidth[12], lockColWidth[10], xactColWidth[5], querystateColWidth[5]; - - int cboToRate(); - wxString rateToCboString(int rate); - - wxImageList *listimages; - long getlongvalue(wxString source,wxString match_str); - void AddStatusPane(); - void AddLockPane(); - void AddXactPane(); - void AddLogPane(); + wxImageList *listimages; + long getlongvalue(wxString source,wxString match_str); + void AddStatusPane(); + void AddLockPane(); + void AddXactPane(); + void AddLogPane(); void AddQuerystatePane(); - void OnHelp(wxCommandEvent &ev); - void OnContents(wxCommandEvent &ev); - void OnExit(wxCommandEvent &event); + void OnHelp(wxCommandEvent &ev); + void OnContents(wxCommandEvent &ev); + void OnExit(wxCommandEvent &event); - void OnCopy(wxCommandEvent &ev); - void OnCopyQuery(wxCommandEvent &ev); + void OnCopy(wxCommandEvent &ev); + void OnCopyQuery(wxCommandEvent &ev); - void OnToggleStatusPane(wxCommandEvent &event); - void OnToggleLockPane(wxCommandEvent &event); - void OnToggleXactPane(wxCommandEvent &event); - void OnToggleLogPane(wxCommandEvent &event); - void OnToggleQuerystatePane(wxCommandEvent &event); - void OnEmptyAction(wxCommandEvent &event); - - void OnToggleToolBar(wxCommandEvent &event); - void OnDefaultView(wxCommandEvent &event); - void OnHighlightStatus(wxCommandEvent &event); + void OnToggleStatusPane(wxCommandEvent &event); + void OnToggleLockPane(wxCommandEvent &event); + void OnToggleXactPane(wxCommandEvent &event); + void OnToggleLogPane(wxCommandEvent &event); + void OnToggleQuerystatePane(wxCommandEvent &event); + void OnToggleWaitEnable(wxCommandEvent& event); + void OnEmptyAction(wxCommandEvent &event); + void OnLogContextMenu(wxCommandEvent& event); - void OnRefreshUITimer(wxTimerEvent &event); - void OnRefreshStatusTimer(wxTimerEvent &event); - void OnRefreshLocksTimer(wxTimerEvent &event); - void OnRefreshXactTimer(wxTimerEvent &event); - void OnRefreshLogTimer(wxTimerEvent &event); - void OnRefreshQuerystateTimer(wxTimerEvent &event); + void OnToggleToolBar(wxCommandEvent &event); + void OnDefaultView(wxCommandEvent &event); + void OnHighlightStatus(wxCommandEvent &event); - void SetColumnImage(ctlListView *list, int col, int image); - void OnSortStatusGrid(wxListEvent &event); - void OnRightClickStatusItem(wxListEvent& event); - void OnSortLockGrid(wxListEvent &event); - void OnSortXactGrid(wxListEvent &event); + void OnRefreshUITimer(wxTimerEvent &event); + void OnRefreshStatusTimer(wxTimerEvent &event); + void OnRefreshLocksTimer(wxTimerEvent &event); + void OnRefreshXactTimer(wxTimerEvent &event); + void OnRefreshLogTimer(wxTimerEvent &event); + void OnRefreshQuerystateTimer(wxTimerEvent &event); - void OnRightClickStatusGrid(wxListEvent &event); - void OnRightClickLockGrid(wxListEvent &event); - void OnRightClickXactGrid(wxListEvent &event); - void OnRightClickQuerystateGrid(wxListEvent &event); + void SetColumnImage(ctlListView *list, int col, int image); + void OnSortStatusGrid(wxListEvent &event); + void OnRightClickStatusItem(wxListEvent& event); + void OnSortLockGrid(wxListEvent &event); + void OnSortXactGrid(wxListEvent &event); - void OnStatusMenu(wxCommandEvent &event); - void OnLockMenu(wxCommandEvent &event); - void OnXactMenu(wxCommandEvent &event); - void OnQuerystateMenu(wxCommandEvent &event); + void OnRightClickStatusGrid(wxListEvent &event); + void OnRightClickLockGrid(wxListEvent &event); + void OnRightClickXactGrid(wxListEvent &event); + void OnRightClickQuerystateGrid(wxListEvent &event); + void OnRightClickLogGrid(wxListEvent& event); + + void OnStatusMenu(wxCommandEvent &event); + void OnLockMenu(wxCommandEvent &event); + void OnXactMenu(wxCommandEvent &event); + void OnQuerystateMenu(wxCommandEvent &event); - void OnChgColSizeStatusGrid(wxListEvent &event); - void OnChgColSizeLockGrid(wxListEvent &event); - void OnChgColSizeXactGrid(wxListEvent &event); - void OnChgColSizeQuerystateGrid(wxListEvent &event); - - void OnRateChange(wxCommandEvent &event); + void OnChgColSizeStatusGrid(wxListEvent &event); + void OnChgColSizeLockGrid(wxListEvent &event); + void OnChgColSizeXactGrid(wxListEvent &event); + void OnChgColSizeQuerystateGrid(wxListEvent &event); + + void OnRateChange(wxCommandEvent &event); - void OnPaneClose(wxAuiManagerEvent &evt); + void OnPaneClose(wxAuiManagerEvent &evt); + void OnPaneActivated(wxAuiManagerEvent& evt); - void OnClose(wxCloseEvent &event); - void OnRefresh(wxCommandEvent &event); - void OnCancelBtn(wxCommandEvent &event); - void OnStatusCancelBtn(wxCommandEvent &event); - void OnLocksCancelBtn(wxCommandEvent &event); - void OnTerminateBtn(wxCommandEvent &event); - void OnStatusTerminateBtn(wxCommandEvent &event); - void OnLocksTerminateBtn(wxCommandEvent &event); - void OnSelStatusItem(wxListEvent &event); - void OnSelLockItem(wxListEvent &event); - void OnSelXactItem(wxListEvent &event); - void OnSelLogItem(wxListEvent &event); - void OnSelQuerystateItem(wxListEvent &event); - void OnLoadLogfile(wxCommandEvent &event); - void OnRotateLogfile(wxCommandEvent &event); - void OnCommit(wxCommandEvent &event); - void OnRollback(wxCommandEvent &event); - void OnClearFilter(wxCommandEvent& event); + void OnClose(wxCloseEvent &event); + void OnRefresh(wxCommandEvent &event); + void OnCancelBtn(wxCommandEvent &event); + void OnStatusCancelBtn(wxCommandEvent &event); + void OnLocksCancelBtn(wxCommandEvent &event); + void OnTerminateBtn(wxCommandEvent &event); + void OnStatusTerminateBtn(wxCommandEvent &event); + void OnLocksTerminateBtn(wxCommandEvent &event); + void OnSelStatusItem(wxListEvent &event); + void OnSelLockItem(wxListEvent &event); + void OnSelXactItem(wxListEvent &event); + void OnSelLogItem(wxListEvent &event); + void OnSelQuerystateItem(wxListEvent &event); + void OnLoadLogfile(wxCommandEvent &event); + void OnRotateLogfile(wxCommandEvent &event); + void OnCommit(wxCommandEvent &event); + void OnRollback(wxCommandEvent &event); + void OnClearFilter(wxCommandEvent& event); + void OnLogKeyUp(wxKeyEvent& event); + void OnAddLabelTextThread(wxThreadEvent& event); + void ActivatePane(wxString name); - void OnChangeDatabase(wxCommandEvent &ev); + void OnChangeDatabase(wxCommandEvent &ev); - int fillLogfileCombo(); - void emptyLogfileCombo(); + int fillLogfileCombo(); + void emptyLogfileCombo(); - void addLogFile(wxDateTime *dt, bool skipFirst); - void addLogFile(const wxString &filename, const wxDateTime timestamp, long len, long &read, bool skipFirst); - void addLogLine(const wxString &str, bool formatted = true, bool csv_log_format = false); + void addLogFile(wxDateTime *dt, bool skipFirst); + void addLogFile(const wxString &filename, const wxDateTime timestamp, long len, long &read, bool skipFirst); + void addLogLine(const wxString &str, bool formatted = true, bool csv_log_format = false); - void checkConnection(); + void checkConnection(); - DECLARE_EVENT_TABLE() + DECLARE_EVENT_TABLE() }; class serverStatusFactory : public actionFactory { public: - serverStatusFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar); - wxWindow *StartDialog(frmMain *form, pgObject *obj); - bool CheckEnable(pgObject *obj); + serverStatusFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar); + wxWindow *StartDialog(frmMain *form, pgObject *obj); + bool CheckEnable(pgObject *obj); }; #endif diff --git a/include/utils/WaitSample.h b/include/utils/WaitSample.h new file mode 100644 index 0000000..d7d18cd --- /dev/null +++ b/include/utils/WaitSample.h @@ -0,0 +1,195 @@ +#pragma once + +#include +struct Sample +{ + int btime; + int etime; + int wait_id; + int pid; + int btype; // backend_type = 0 Client backend + long long qid; + int samples; +}; +enum iswhat { + WAIT_FULL, + WAIT_GRP, + WAIT_NAME +} ; +/// +/// qid,wait_id,pid +/// +struct key3 { + long long qid; + int w, pid; + int sum; + + bool const operator==(const key3& o) const { + return qid == o.qid && w == o.w && pid==o.pid; + } + bool const cmp2field(const key3& o) const { + return qid == o.qid && w == o.w; + } + + bool const operator<(const key3& o) const { + return qid < o.qid || (qid == o.qid && w < o.w)|| (qid == o.qid && w == o.w && pid +/// compare pid,wait,qid +/// +struct key3p { + long long qid; + int w, pid; + int sum; + + bool const operator==(const key3p& o) const { + return qid == o.qid && w == o.w && pid == o.pid; + } + bool const cmp2field(const key3p& o) const { + return qid == o.qid && w == o.w; + } + + bool const operator<(const key3p& o) const { + return pid < o.pid || (pid == o.pid && w < o.w) || (pid == o.pid && w == o.w && qid < o.qid); + } +}; + +typedef std::vector vec_int; +class WaitSample +{ +private: + int periodms = 10; + int history_size; + wxJSONValue opt; + std::map pids; + std::map chkpids; +// + std::vector btype = { "client backend","background writer","checkpointer" + ,"walreceiver","walsender","walwriter","autovacuum launcher","autovacuum worker" + ,"logical replication launcher","logical replication worker","parallel worker" + ,"archiver","startup" }; + std::vector btypeshort = { "CL","BGW","CKP" + ,"walR","walS","walW","avL","avW" + ,"lrL","lrW","pW" + ,"ARC","startup" }; + std::map qid_sql; + std::map wait_idx; // mapping wait_name -> color rgb + std::map wait_disable; + std::map wait_id; + std::map wait_id_name; // number wait -> full name wait + std::vector colors; // mapping colors[wait_id] -> color rgb + std::vector group; + std::vector smp; // + std::vector tmp_smp; // + long long basetime = 0; + int timebegiserios = 0, timeendserios = 0; + int start_index_serios; + /// + /// Получение номера РіСЂСѓРїРїС‹ РїРѕ имени РіСЂСѓРїРїС‹. + /// + /// + /// + int wait_class(wxString wclass); +public: + void SaveFileSamples(); + void LoadFileSamples(); + bool AddQuery(long long qid, wxString sql); + wxString GetQueryByQid(long long qid); + /// + /// Получить Id backend_type + /// Если неизвестный backend_type то РѕРЅ получит новый ID + /// + /// + /// + int GetBackendTypeId(wxString backend_type); + wxString GetBackendTypeName(int backend_id) { + return btype[backend_id]; + }; + wxString GetBackendTypeNameShort(int backend_id) { + return backend_id>=btypeshort.size() ? GetBackendTypeName(backend_id): btypeshort[backend_id]; + }; + /// + /// Получение индекса цвета РїРѕ полному имени ожидания + /// Если для ожидание нет цвета то используется цвет РіСЂСѓРїРїС‹ + /// + /// Полное РёРјСЏ ожидания + /// Рндекс РІ массиве colors + long GetColorByWaitName(wxString wait_name) { + auto clr = wait_idx.find(wait_name); + if (clr == wait_idx.end()) { + wxString grp_name = wait_name.BeforeFirst(':'); + clr = wait_idx.find(grp_name); + } + + return clr->second; + }; + /// + /// Получение Текстового имени ожидания + /// + /// РРґ ожидания + /// WAIT_FULL - полное РёРјСЏ,WAIT_GRP - РіСЂСѓРїРїР°, WAIT_NAME - РёРјСЏ ожидания + /// + wxString GetName(int wait_id, iswhat isGrp) { + wxString n = wait_id_name[wait_id]; + if (isGrp == WAIT_FULL) return n; + wxString grp_name = n.BeforeFirst(':'); + if (grp_name.IsEmpty()) return n; + if (isGrp==WAIT_GRP) return grp_name; + else + return n.AfterFirst(':'); + }; + int GetCountWaits() { return wait_id.size(); } + inline int d_time(long long ms) { + return ms - basetime; + } + std::vector* GetSamples(); + std::vector GetColors(); + /// + /// Получение начальной границы интервала для переданного времени. + /// + /// -1 текущая левая граница, или время + /// Агрегирующий интервал + /// Время начала интервала. + int GetHomeInterval(int timeEnd, int AggrigateInterval); + int GetInterval(int posStart, int posEnd); + wxArrayString GetWaitIdNameArray(bool onlyGroup); + int GetGroupingData(int timeEnd, // -1 для правой границы + int needCountGroup, // сколько интервалов получить + int groupInterval, // 1 min, 5 min, 10 min, 20 min, 30 min, 1 hour + wxString groupRule, // как проводить РіСЂСѓРїРёСЂРѕРІРєСѓ + wxArrayString& nameGroup, // эаполняет именами ожиданий или РіСЂСѓРїРї ожиданий + std::vector& xAxisValue,// границы интервалов + std::vector& yAxisValue, + std::vector& Values, + std::vector& clr + ); + /// + /// Получение позиции РІ массиве РїРѕ указанному времени + /// + /// + /// + int getPositionByTime(int time); + inline int getPeriod() { return periodms; } + void SetConfig(long periodmills, long history_size) { + periodms = periodmills; + this->history_size = history_size; + }; + void Init(); + + WaitSample() { + //c2.FromString("#3644ff"); + Init(); + }; + void BeginSeriosSample(long long timeserios) { + chkpids.clear(); + if (basetime == 0) basetime = timeserios; + timebegiserios = timeendserios; + timeendserios = d_time(timeserios); + start_index_serios = smp.size(); + + } + void EndSeriosSample(); + void AddSample(int pid, bool isXidTransation, wxString& active, const wxString& sample); + +}; diff --git a/ui/xrcDialogs.cpp b/ui/xrcDialogs.cpp index a2b64b2..65bba79 100644 --- a/ui/xrcDialogs.cpp +++ b/ui/xrcDialogs.cpp @@ -27584,9 +27584,593 @@ static unsigned char xml_res_file_65[] = { 47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62,10, 60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_66 = 16218; +static size_t xml_res_size_66 = 12680; static unsigned char xml_res_file_66[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, +110,99,111,100,105,110,103,61,34,85,84,70,45,56,34,63,62,10,60,114,101, +115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,119,120,68,105,97,108,111,103,34,32,110,97,109,101,61,34, +100,108,103,84,114,97,110,115,102,111,114,109,84,101,120,116,34,62,10,32, +32,32,32,60,115,116,121,108,101,62,119,120,68,69,70,65,85,76,84,95,68,73, +65,76,79,71,95,83,84,89,76,69,124,119,120,67,65,80,84,73,79,78,124,119, +120,77,65,88,73,77,73,90,69,95,66,79,88,124,119,120,82,69,83,73,90,69,95, +66,79,82,68,69,82,60,47,115,116,121,108,101,62,10,32,32,32,32,60,116,105, +116,108,101,62,84,114,97,110,115,102,111,114,109,32,116,101,120,116,60, +47,116,105,116,108,101,62,10,32,32,32,32,60,99,101,110,116,101,114,101, +100,62,49,60,47,99,101,110,116,101,114,101,100,62,10,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105, +122,101,114,34,32,110,97,109,101,61,34,98,83,105,122,101,114,49,34,62,10, +32,32,32,32,32,32,60,111,114,105,101,110,116,62,119,120,86,69,82,84,73, +67,65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,60,111,98, +106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101, +109,34,62,10,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88, +80,65,78,68,32,124,32,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32, +32,32,32,32,32,32,60,98,111,114,100,101,114,62,51,60,47,98,111,114,100, +101,114,62,10,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48, +60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,60,111,98,106, +101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,32,110, +97,109,101,61,34,115,114,99,79,112,116,34,62,10,32,32,32,32,32,32,32,32, +32,32,60,115,116,121,108,101,62,119,120,84,65,66,95,84,82,65,86,69,82,83, +65,76,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,60, +111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116, +105,99,66,111,120,83,105,122,101,114,34,32,110,97,109,101,61,34,115,98, +83,105,122,101,114,49,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +114,105,101,110,116,62,119,120,86,69,82,84,73,67,65,76,60,47,111,114,105, +101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101, +108,62,83,111,117,114,99,101,32,116,101,120,116,32,111,112,116,105,111, +110,115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101, +114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114, +62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111, +110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99, +116,32,99,108,97,115,115,61,34,119,120,71,114,105,100,66,97,103,83,105, +122,101,114,34,32,110,97,109,101,61,34,103,98,83,105,122,101,114,50,34, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112, +62,48,60,47,118,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114, +111,119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +103,114,111,119,97,98,108,101,99,111,108,115,62,48,44,49,60,47,103,114, +111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115, +105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102, +108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111, +115,62,48,44,48,60,47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62, +49,44,49,60,47,99,101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97, +109,101,61,34,109,95,115,116,97,116,105,99,84,101,120,116,56,34,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101, +108,62,80,67,82,69,32,114,101,103,101,120,112,60,47,108,97,98,101,108,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114, +97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99, +108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119, +120,69,88,80,65,78,68,32,124,32,119,120,65,76,76,60,47,102,108,97,103,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, +100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111,115,62,49, +44,48,60,47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62,51,44,49, +60,47,99,101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61, +34,99,116,108,83,116,121,108,101,100,84,101,120,116,34,32,110,97,109,101, +61,34,82,101,103,84,101,120,116,34,47,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115, +115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76, +76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108, +108,112,111,115,62,48,44,49,60,47,99,101,108,108,112,111,115,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,115,112, +97,110,62,49,44,49,60,47,99,101,108,108,115,112,97,110,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99, +108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32, +110,97,109,101,61,34,109,95,115,116,97,116,105,99,84,101,120,116,57,34, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108, +97,98,101,108,62,82,101,112,108,97,99,101,32,101,120,112,114,101,115,115, +105,111,110,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114, +97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105, +122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,32,124, +32,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98, +111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,99,101,108,108,112,111,115,62,49,44,49,60,47,99,101,108,108, +112,111,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,99,101,108,108,115,112,97,110,62,51,44,49,60,47,99,101,108,108,115,112, +97,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,99,116,108,83,116,121,108, +101,100,84,101,120,116,34,32,110,97,109,101,61,34,82,101,112,108,97,99, +101,84,101,120,116,34,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115, +105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102, +108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111, +115,62,49,44,50,60,47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62, +49,44,49,60,47,99,101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97, +109,101,61,34,109,95,115,116,97,116,105,99,84,101,120,116,49,50,34,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98, +101,108,62,82,111,119,115,32,108,105,109,105,116,60,47,108,97,98,101,108, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119, +114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116, +32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103, +62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98, +111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,99,101,108,108,112,111,115,62,49,44,51,60,47,99,101,108,108, +112,111,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,99,101,108,108,115,112,97,110,62,49,44,49,60,47,99,101,108,108,115,112, +97,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,84,101,120,116,67, +116,114,108,34,32,110,97,109,101,61,34,76,105,109,105,116,82,111,119,115, +84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,109,97,120,108,101,110,103,116,104,62, +48,60,47,109,97,120,108,101,110,103,116,104,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99, +116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97, +103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47, +98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,99,101,108,108,112,111,115,62,50,44,50,60,47,99,101,108, +108,112,111,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,99,101,108,108,115,112,97,110,62,49,44,49,60,47,99,101,108,108,115, +112,97,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116, +105,99,84,101,120,116,34,32,110,97,109,101,61,34,109,95,115,116,97,116, +105,99,84,101,120,116,49,51,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,104,97,114,115,32,108, +105,109,105,116,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114, +97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105, +122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97, +103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111, +114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111,115,62, +50,44,51,60,47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62,49,44, +49,60,47,99,101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, +61,34,119,120,84,101,120,116,67,116,114,108,34,32,110,97,109,101,61,34, +76,105,109,105,116,67,104,97,114,115,84,101,120,116,34,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,109, +97,120,108,101,110,103,116,104,62,48,60,47,109,97,120,108,101,110,103,116, +104,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111, +98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122, +101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, +100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111,115,62,51, +44,51,60,47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62,49,44,49, +60,47,99,101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61, +34,119,120,67,104,101,99,107,66,111,120,34,32,110,97,109,101,61,34,99,104, +107,72,105,103,104,76,105,103,104,116,34,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,82,101,102, +114,101,115,104,32,104,105,103,104,108,105,103,104,116,60,47,108,97,98, +101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,99,104,101,99,107,101,100,62,49,60,47,99,104,101,99,107,101,100,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98, +106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116, +62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, +32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101, +114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,60,102,108,97,103, +62,119,120,69,88,80,65,78,68,32,124,32,119,120,65,76,76,60,47,102,108,97, +103,62,10,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,51,60,47, +98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,60,111,112,116,105, +111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32, +32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110, +101,108,34,32,110,97,109,101,61,34,109,95,112,97,110,101,108,51,34,62,10, +32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,84,65,66, +95,84,82,65,86,69,82,83,65,76,60,47,115,116,121,108,101,62,10,32,32,32, +32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34, +119,120,83,116,97,116,105,99,66,111,120,83,105,122,101,114,34,32,110,97, +109,101,61,34,115,98,83,105,122,101,114,50,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,60,111,114,105,101,110,116,62,119,120,86,69,82,84,73,67, +65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,60,108,97,98,101,108,62,83,111,117,114,99,101,32,116,101,120,116, +60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116, +101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97, +103,62,119,120,69,88,80,65,78,68,32,124,32,119,120,65,76,76,60,47,102,108, +97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100, +101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105, +111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101, +99,116,32,99,108,97,115,115,61,34,99,116,108,83,116,121,108,101,100,84, +101,120,116,34,32,110,97,109,101,61,34,115,114,99,84,101,120,116,34,47, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60, +47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116, +32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10, +32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68, +32,124,32,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32, +32,32,60,98,111,114,100,101,114,62,51,60,47,98,111,114,100,101,114,62,10, +32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112, +116,105,111,110,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116, +32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,97,109,101, +61,34,109,95,112,97,110,101,108,56,34,62,10,32,32,32,32,32,32,32,32,32, +32,60,115,116,121,108,101,62,119,120,84,65,66,95,84,82,65,86,69,82,83,65, +76,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105, +99,66,111,120,83,105,122,101,114,34,32,110,97,109,101,61,34,115,98,83,105, +122,101,114,53,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114, +105,101,110,116,62,119,120,86,69,82,84,73,67,65,76,60,47,111,114,105,101, +110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108, +62,84,114,97,110,115,102,111,114,109,32,116,101,120,116,60,47,108,97,98, +101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99, +116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, +69,88,80,65,78,68,32,124,32,119,120,65,76,76,60,47,102,108,97,103,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62, +53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116, +32,99,108,97,115,115,61,34,99,116,108,83,116,121,108,101,100,84,101,120, +116,34,32,110,97,109,101,61,34,116,114,103,84,101,120,116,34,47,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, +32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111, +98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99, +108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32, +32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,32,124, +32,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32, +60,98,111,114,100,101,114,62,51,60,47,98,111,114,100,101,114,62,10,32,32, +32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105, +111,110,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,97,109,101,61,34,109, +95,112,97,110,101,108,55,34,62,10,32,32,32,32,32,32,32,32,32,32,60,115, +116,121,108,101,62,119,120,84,65,66,95,84,82,65,86,69,82,83,65,76,60,47, +115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101, +99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,66,111,120, +83,105,122,101,114,34,32,110,97,109,101,61,34,115,98,83,105,122,101,114, +51,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,101,110, +116,62,119,120,86,69,82,84,73,67,65,76,60,47,111,114,105,101,110,116,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,84,114,97, +110,115,102,111,114,109,32,116,101,120,116,32,111,112,116,105,111,110,115, +60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116, +101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97, +103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98, +111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,119,120,71,114,105,100,66,97,103,83,105,122,101,114,34, +32,110,97,109,101,61,34,103,98,83,105,122,101,114,49,34,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118, +103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104, +103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,47, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119, +97,98,108,101,99,111,108,115,62,49,44,51,60,47,103,114,111,119,97,98,108, +101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114, +105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100, +101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111,115,62,49,44,48, +60,47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62,49,44,49,60,47, +99,101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119, +120,83,116,97,116,105,99,84,101,120,116,34,32,110,97,109,101,61,34,109, +95,115,116,97,116,105,99,84,101,120,116,49,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,65,112,112, +101,110,100,32,98,101,102,111,114,101,32,114,111,119,60,47,108,97,98,101, +108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99, +116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97, +103,62,119,120,65,76,76,124,119,120,69,88,80,65,78,68,60,47,102,108,97, +103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111, +114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111,115,62, +49,44,49,60,47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62,49,44, +49,60,47,99,101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, +61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,98, +101,102,111,114,101,82,111,119,67,66,34,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101, +110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115, +105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102, +108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111, +115,62,49,44,50,60,47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62, +49,44,49,60,47,99,101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97, +109,101,61,34,109,95,115,116,97,116,105,99,84,101,120,116,50,34,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101, +108,62,65,102,116,101,114,32,114,111,119,60,47,108,97,98,101,108,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114, +97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99, +108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119, +120,65,76,76,124,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101, +114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111,115,62,49,44,51,60, +47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62,49,44,49,60,47,99, +101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119, +120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,97,102,116, +101,114,82,111,119,67,66,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98, +106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99, +101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, +100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,99,101,108,108,112,111,115,62,50, +44,50,60,47,99,101,108,108,112,111,115,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,99,101,108,108,115,112,97,110,62,49,44,49, +60,47,99,101,108,108,115,112,97,110,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122, +101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98, +106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114, +34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108, +97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114, +62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,99,101,108,108,112,111,115,62,50,44,51,60,47, +99,101,108,108,112,111,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,99,101,108,108,115,112,97,110,62,49,44,49,60,47,99,101, +108,108,115,112,97,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99, +116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, +101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109, +34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108, +97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60, +47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,99,101,108,108,112,111,115,62,51,44,48,60,47,99,101,108, +108,112,111,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,99,101,108,108,115,112,97,110,62,49,44,49,60,47,99,101,108,108,115, +112,97,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116, +105,99,84,101,120,116,34,32,110,97,109,101,61,34,109,95,115,116,97,116, +105,99,84,101,120,116,51,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,108,97,98,101,108,62,70,105,101,108,100,32,115, +101,112,97,114,97,116,111,114,60,47,108,97,98,101,108,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45, +49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115, +115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76, +76,124,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62, +53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,99,101,108,108,112,111,115,62,51,44,49,60,47,99, +101,108,108,112,111,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,99,101,108,108,115,112,97,110,62,49,44,49,60,47,99,101,108, +108,115,112,97,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,111, +109,98,111,66,111,120,34,32,110,97,109,101,61,34,115,101,112,70,105,101, +108,100,67,66,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101, +99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111, +98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111, +98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32, +60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114, +105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119, +120,69,88,80,65,78,68,32,124,32,119,120,65,76,76,60,47,102,108,97,103,62, +10,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,51,60,47,98,111, +114,100,101,114,62,10,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110, +62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,108, +34,32,110,97,109,101,61,34,109,95,112,97,110,101,108,50,34,62,10,32,32, +32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,84,65,66,95,84, +82,65,86,69,82,83,65,76,60,47,115,116,121,108,101,62,10,32,32,32,32,32, +32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119, +120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,32,110,97,109,101, +61,34,102,103,83,105,122,101,114,50,49,34,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108, +101,114,111,119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,103, +114,111,119,97,98,108,101,99,111,108,115,62,49,44,51,60,47,103,114,111, +119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,60,114,111,119,115,62,48,60,47,114,111,119,115,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,60,99,111,108,115,62,54,60,47,99,111,108,115,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73, +71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,65,76, +76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60, +47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97, +116,105,99,84,101,120,116,34,32,110,97,109,101,61,34,109,95,115,116,97, +116,105,99,84,101,120,116,54,34,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,108,97,98,101,108,62,76,111,97,100,32,111,112,116,105, +111,110,115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76, +124,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111, +114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101, +61,34,111,112,116,105,111,110,115,76,111,97,100,67,66,34,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,62,70,105, +114,115,116,60,47,118,97,108,117,101,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34, +115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114, +62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111, +110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99, +116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,32,110, +97,109,101,61,34,98,116,110,83,97,118,101,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83,97,118,101,60,47, +108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,116,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,97,117,116,104,95, +110,101,101,100,101,100,62,48,60,47,97,117,116,104,95,110,101,101,100,101, +100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,109,97,114, +107,117,112,62,48,60,47,109,97,114,107,117,112,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,47,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, +61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62, +49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115, +115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102, +108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, +100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112, +116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111, +110,34,32,110,97,109,101,61,34,98,116,110,79,107,34,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,111,112,121, +60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108, +116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,97,117,116, +104,95,110,101,101,100,101,100,62,48,60,47,97,117,116,104,95,110,101,101, +100,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,109, +97,114,107,117,112,62,48,60,47,109,97,114,107,117,112,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,47,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60, +47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98, +111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111, +112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116, +111,110,34,32,110,97,109,101,61,34,119,120,73,68,95,67,65,78,67,69,76,34, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101, +108,62,67,97,110,99,101,108,60,47,108,97,98,101,108,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,60, +47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,97,117,116,104,95,110,101,101,100,101,100,62,48,60,47,97, +117,116,104,95,110,101,101,100,101,100,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,109,97,114,107,117,112,62,48,60,47,109,97,114,107, +117,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105, +116,109,97,112,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111, +98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32, +60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114, +105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119, +120,65,76,76,124,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32, +32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100, +101,114,62,10,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48, +60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,60,111,98,106, +101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101, +120,116,34,32,110,97,109,101,61,34,109,95,109,115,103,34,62,10,32,32,32, +32,32,32,32,32,32,32,60,102,111,110,116,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,60,115,116,121,108,101,62,110,111,114,109,97,108,60,47,115,116, +121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,119,101,105,103, +104,116,62,98,111,108,100,60,47,119,101,105,103,104,116,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,60,102,97,109,105,108,121,62,100,101,102,97, +117,108,116,60,47,102,97,109,105,108,121,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,60,117,110,100,101,114,108,105,110,101,100,62,48,60,47,117, +110,100,101,114,108,105,110,101,100,62,10,32,32,32,32,32,32,32,32,32,32, +60,47,102,111,110,116,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98, +101,108,62,82,111,119,115,32,108,111,97,100,105,110,103,60,47,108,97,98, +101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49, +60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101, +99,116,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116, +62,10,60,47,114,101,115,111,117,114,99,101,62,10}; + +static size_t xml_res_size_67 = 16218; +static unsigned char xml_res_file_67[] = { +60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, 32,99,108,97,115,115,61,34,119,120,68,105,97,108,111,103,34,32,110,97,109, @@ -28325,8 +28909,8 @@ static unsigned char xml_res_file_66[] = { 32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116, 62,10,60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_67 = 42127; -static unsigned char xml_res_file_67[] = { +static size_t xml_res_size_68 = 42127; +static unsigned char xml_res_file_68[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -30218,8 +30802,8 @@ static unsigned char xml_res_file_67[] = { 32,60,47,111,98,106,101,99,116,62,10,60,47,114,101,115,111,117,114,99,101, 62,10}; -static size_t xml_res_size_68 = 15263; -static unsigned char xml_res_file_68[] = { +static size_t xml_res_size_69 = 15263; +static unsigned char xml_res_file_69[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -30915,8 +31499,8 @@ static unsigned char xml_res_file_68[] = { 111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62,10,60, 47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_69 = 7985; -static unsigned char xml_res_file_69[] = { +static size_t xml_res_size_70 = 7985; +static unsigned char xml_res_file_70[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -31282,8 +31866,8 @@ static unsigned char xml_res_file_69[] = { 62,10,32,32,60,47,111,98,106,101,99,116,62,10,60,47,114,101,115,111,117, 114,99,101,62,10}; -static size_t xml_res_size_70 = 35899; -static unsigned char xml_res_file_70[] = { +static size_t xml_res_size_71 = 35899; +static unsigned char xml_res_file_71[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -32900,8 +33484,8 @@ static unsigned char xml_res_file_70[] = { 99,116,62,10,32,32,60,47,111,98,106,101,99,116,62,10,60,47,114,101,115, 111,117,114,99,101,62,10}; -static size_t xml_res_size_71 = 9659; -static unsigned char xml_res_file_71[] = { +static size_t xml_res_size_72 = 9659; +static unsigned char xml_res_file_72[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,85,84,70,45,56,34,63,62,10,60,114,101, 115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116,32,99,108,97, @@ -33339,8 +33923,8 @@ static unsigned char xml_res_file_71[] = { 10,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106, 101,99,116,62,10,60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_72 = 17923; -static unsigned char xml_res_file_72[] = { +static size_t xml_res_size_73 = 17923; +static unsigned char xml_res_file_73[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -34157,8 +34741,8 @@ static unsigned char xml_res_file_72[] = { 106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62,10,60,47,114, 101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_73 = 3982; -static unsigned char xml_res_file_73[] = { +static size_t xml_res_size_74 = 3982; +static unsigned char xml_res_file_74[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -34344,8 +34928,8 @@ static unsigned char xml_res_file_73[] = { 32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101, 99,116,62,10,60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_74 = 3909; -static unsigned char xml_res_file_74[] = { +static size_t xml_res_size_75 = 3909; +static unsigned char xml_res_file_75[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -34528,8 +35112,8 @@ static unsigned char xml_res_file_74[] = { 47,111,98,106,101,99,116,62,10,60,47,114,101,115,111,117,114,99,101,62, 10}; -static size_t xml_res_size_75 = 3765; -static unsigned char xml_res_file_75[] = { +static size_t xml_res_size_76 = 3765; +static unsigned char xml_res_file_76[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -34708,8 +35292,8 @@ static unsigned char xml_res_file_75[] = { 60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62, 10,60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_76 = 1443; -static unsigned char xml_res_file_76[] = { +static size_t xml_res_size_77 = 1443; +static unsigned char xml_res_file_77[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -34779,8 +35363,8 @@ static unsigned char xml_res_file_76[] = { 101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62,10,60,47,114,101, 115,111,117,114,99,101,62,10}; -static size_t xml_res_size_77 = 3111; -static unsigned char xml_res_file_77[] = { +static size_t xml_res_size_78 = 3111; +static unsigned char xml_res_file_78[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -34926,8 +35510,8 @@ static unsigned char xml_res_file_77[] = { 60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62, 10,60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_78 = 12040; -static unsigned char xml_res_file_78[] = { +static size_t xml_res_size_79 = 12040; +static unsigned char xml_res_file_79[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -35479,8 +36063,8 @@ static unsigned char xml_res_file_78[] = { 10,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106, 101,99,116,62,10,60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_79 = 5804; -static unsigned char xml_res_file_79[] = { +static size_t xml_res_size_80 = 5804; +static unsigned char xml_res_file_80[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -35747,8 +36331,8 @@ static unsigned char xml_res_file_79[] = { 47,111,98,106,101,99,116,62,10,60,47,114,101,115,111,117,114,99,101,62, 10}; -static size_t xml_res_size_80 = 70799; -static unsigned char xml_res_file_80[] = { +static size_t xml_res_size_81 = 72166; +static unsigned char xml_res_file_81[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -35800,122 +36384,33 @@ static unsigned char xml_res_file_80[] = { 32,32,32,60,104,103,97,112,62,53,60,47,104,103,97,112,62,10,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111, 119,115,62,48,44,49,44,50,44,51,44,52,44,53,44,54,44,55,44,56,44,57,44, -49,48,44,49,49,44,49,50,44,49,51,44,49,52,44,49,53,60,47,103,114,111,119, -97,98,108,101,114,111,119,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,62,48,60,47,103,114, -111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105, -122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120, -80,97,110,101,108,34,32,110,97,109,101,61,34,112,110,108,77,105,115,99, -72,101,108,112,80,97,116,104,34,62,10,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,60,104,105,100,100,101,110,62,49,60,47,104,105,100, -100,101,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101, -120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,62,50,60,47,99,111, -108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,118,103,97,112,62,53,60,47,118,103,97,112,62,10,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,53,60,47, -104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,62,49,60,47,103, -114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32, +49,48,44,49,49,44,49,50,44,49,51,44,49,52,44,49,53,44,49,54,44,49,55,60, +47,103,114,111,119,97,98,108,101,114,111,119,115,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115, +62,48,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, +115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, -97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, -101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101, -120,116,34,32,110,97,109,101,61,34,115,116,80,103,72,101,108,112,80,97, -116,104,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,60,108,97,98,101,108,62,80,71,32,104,101,108,112,32,112, -97,116,104,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108, -97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73, -67,65,76,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73, -71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98, -111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, -97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, -101,99,116,32,99,108,97,115,115,61,34,119,120,84,101,120,116,67,116,114, -108,34,32,110,97,109,101,61,34,116,120,116,80,103,72,101,108,112,80,97, -116,104,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,60,116,111,111,108,116,105,112,62,69,110,116,101,114, -32,116,104,101,32,112,97,116,104,32,111,114,32,85,82,76,32,116,111,32,116, -104,101,32,80,111,115,116,103,114,101,83,81,76,32,100,111,99,117,109,101, -110,116,97,116,105,111,110,60,47,116,111,111,108,116,105,112,62,10,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98, -106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119,120, -84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108, -97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98, -106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122, -101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, -61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97,109,101, -61,34,115,116,69,100,98,72,101,108,112,80,97,116,104,34,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97, -98,101,108,62,69,68,66,32,104,101,108,112,32,112,97,116,104,60,47,108,97, -98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65, -76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120, -84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108, -97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98, -106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122, -101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, -61,34,119,120,84,101,120,116,67,116,114,108,34,32,110,97,109,101,61,34, -116,120,116,69,100,98,72,101,108,112,80,97,116,104,34,47,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97, -103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69, -70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100, -101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, -101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109, -34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97, -116,105,99,84,101,120,116,34,32,110,97,109,101,61,34,115,116,71,112,72, -101,108,112,80,97,116,104,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,71,80,32,104, -101,108,112,32,112,97,116,104,60,47,108,97,98,101,108,62,10,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, -101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84, -69,82,95,86,69,82,84,73,67,65,76,124,119,120,84,79,80,124,119,120,76,69, -70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100, -101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, -101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109, -34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,84,101,120, -116,67,116,114,108,34,32,110,97,109,101,61,34,116,120,116,71,112,72,101, -108,112,80,97,116,104,34,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78, -68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72, -84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114, -100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, -61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32, -99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34, -32,110,97,109,101,61,34,115,116,83,108,111,110,121,72,101,108,112,80,97, -116,104,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,60,108,97,98,101,108,62,83,108,111,110,121,32,104,101, +97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,97,109,101,61,34,112, +110,108,77,105,115,99,72,101,108,112,80,97,116,104,34,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,105,100,100,101,110,62, +49,60,47,104,105,100,100,101,110,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34, +119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115, +62,50,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,118,103,97,112,62,53,60,47,118,103,97,112,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103, +97,112,62,53,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108, +115,62,49,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101, +99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116, +105,99,84,101,120,116,34,32,110,97,109,101,61,34,115,116,80,103,72,101, +108,112,80,97,116,104,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,80,71,32,104,101, 108,112,32,112,97,116,104,60,47,108,97,98,101,108,62,10,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101, 99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, @@ -35929,49 +36424,71 @@ static unsigned char xml_res_file_80[] = { 116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62, 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, 111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,84,101,120,116, -67,116,114,108,34,32,110,97,109,101,61,34,116,120,116,83,108,111,110,121, -72,101,108,112,80,97,116,104,34,47,62,10,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88, -80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82, -73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47, -98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32, +67,116,114,108,34,32,110,97,109,101,61,34,116,120,116,80,103,72,101,108, +112,80,97,116,104,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,116,111,111,108,116,105,112,62,69,110,116, +101,114,32,116,104,101,32,112,97,116,104,32,111,114,32,85,82,76,32,116, +111,32,116,104,101,32,80,111,115,116,103,114,101,83,81,76,32,100,111,99, +117,109,101,110,116,97,116,105,111,110,60,47,116,111,111,108,116,105,112, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78, +68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72, +84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114, +100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, +61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32, +99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34, +32,110,97,109,101,61,34,115,116,69,100,98,72,101,108,112,80,97,116,104, +34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,108,97,98,101,108,62,69,68,66,32,104,101,108,112,32,112,97, +116,104,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, -10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62, -119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84, -124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108, +97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73, +67,65,76,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73, +71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98, -111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, -47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114, -105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101, -108,34,32,110,97,109,101,61,34,112,110,108,77,105,115,99,85,73,34,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,105,100,100, -101,110,62,49,60,47,104,105,100,100,101,110,62,10,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97, -115,115,61,34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114, -34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, -99,111,108,115,62,50,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,53,60,47,118,103, -97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,104,103,97,112,62,53,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101, -99,111,108,115,62,49,60,47,103,114,111,119,97,98,108,101,99,111,108,115, -62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111, -98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116, -101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120, -83,116,97,116,105,99,84,101,120,116,34,32,110,97,109,101,61,34,115,116, -76,97,110,103,117,97,103,101,34,62,10,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,85,115,101, -114,32,108,97,110,103,117,97,103,101,60,47,108,97,98,101,108,62,10,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98, -106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78, -84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,84,79,80,124,119,120,76, +111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, +101,99,116,32,99,108,97,115,115,61,34,119,120,84,101,120,116,67,116,114, +108,34,32,110,97,109,101,61,34,116,120,116,69,100,98,72,101,108,112,80, +97,116,104,34,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119, +120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102, +108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115, +105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110, +97,109,101,61,34,115,116,71,112,72,101,108,112,80,97,116,104,34,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +108,97,98,101,108,62,71,80,32,104,101,108,112,32,112,97,116,104,60,47,108, +97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, +65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119, +120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102, +108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115, +105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,119,120,84,101,120,116,67,116,114,108,34,32,110,97,109, +101,61,34,116,120,116,71,112,72,101,108,112,80,97,116,104,34,47,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108, +97,103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76, 69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, 100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, @@ -35979,16 +36496,15 @@ static unsigned char xml_res_file_80[] = { 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98, 106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101, 109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,111, -109,98,111,66,111,120,34,32,110,97,109,101,61,34,99,98,76,97,110,103,117, -97,103,101,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116, -121,108,101,62,119,120,67,66,95,82,69,65,68,79,78,76,89,124,119,120,67, -66,95,68,82,79,80,68,79,87,78,60,47,115,116,121,108,101,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, -101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119,120, +32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116, +97,116,105,99,84,101,120,116,34,32,110,97,109,101,61,34,115,116,83,108, +111,110,121,72,101,108,112,80,97,116,104,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108, +62,83,108,111,110,121,32,104,101,108,112,32,112,97,116,104,60,47,108,97, +98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65, +76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120, 84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108, 97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114,62,10, @@ -35997,48 +36513,189 @@ static unsigned char xml_res_file_80[] = { 32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122, 101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, -61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97,109,101, -61,34,115,116,83,121,115,116,101,109,83,99,104,101,109,97,115,34,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,108,97,98,101,108,62,83,121,115,116,101,109,32,115,99,104,101,109,97, -115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +61,34,119,120,84,101,120,116,67,116,114,108,34,32,110,97,109,101,61,34, +116,120,116,83,108,111,110,121,72,101,108,112,80,97,116,104,34,47,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102, +108,97,103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120, +76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, +100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80, +124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100, +101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34, +115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34, +119,120,80,97,110,101,108,34,32,110,97,109,101,61,34,112,110,108,77,105, +115,99,85,73,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,104,105,100,100,101,110,62,49,60,47,104,105,100,100,101,110,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101, +99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,71,114,105,100, +83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,99,111,108,115,62,50,60,47,99,111,108,115,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112, +62,53,60,47,118,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,104,103,97,112,62,53,60,47,104,103,97,112,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114, +111,119,97,98,108,101,99,111,108,115,62,49,60,47,103,114,111,119,97,98, +108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115, +105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110, +97,109,101,61,34,115,116,76,97,110,103,117,97,103,101,34,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97, +98,101,108,62,85,115,101,114,32,108,97,110,103,117,97,103,101,60,47,108, +97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, +65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119, +120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102, +108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115, +105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, +97,115,115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109, +101,61,34,99,98,76,97,110,103,117,97,103,101,34,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116, +101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,95,82,69,65, +68,79,78,76,89,124,119,120,67,66,95,68,82,79,80,68,79,87,78,60,47,115,116, +121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69, +88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120, +82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60, +47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99, +108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, +101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101, +120,116,34,32,110,97,109,101,61,34,115,116,83,121,115,116,101,109,83,99, +104,101,109,97,115,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83,121,115,116,101,109, +32,115,99,104,101,109,97,115,60,47,108,97,98,101,108,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84, +69,82,95,86,69,82,84,73,67,65,76,124,119,120,84,79,80,124,119,120,76,69, +70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100, +101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, +101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109, +34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,84,101,120, +116,67,116,114,108,34,32,110,97,109,101,61,34,116,120,116,83,121,115,116, +101,109,83,99,104,101,109,97,115,34,47,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69, +88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120, +82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60, +47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103, +62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70, +84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47, +98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101, +114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97, +110,101,108,34,32,110,97,109,101,61,34,112,110,108,66,114,111,119,115,101, +114,68,105,115,112,108,97,121,34,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,104,105,100,100,101,110,62,49,60,47,104,105,100, +100,101,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101, +120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,62,49,60,47,99,111, +108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,118,103,97,112,62,53,60,47,118,103,97,112,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,53,60,47, +104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,62,49,60,47,103, +114,111,119,97,98,108,101,114,111,119,115,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99, +111,108,115,62,48,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98, +106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101, +109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116, +97,116,105,99,84,101,120,116,34,32,110,97,109,101,61,34,115,116,68,97,116, +97,98,97,115,101,79,98,106,101,99,116,115,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108, +62,68,105,115,112,108,97,121,32,116,104,101,32,102,111,108,108,111,119, +105,110,103,32,100,97,116,97,98,97,115,101,32,111,98,106,101,99,116,115, +58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103, -62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65, -76,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72, -84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114, -100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, -61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32, -99,108,97,115,115,61,34,119,120,84,101,120,116,67,116,114,108,34,32,110, -97,109,101,61,34,116,120,116,83,121,115,116,101,109,83,99,104,101,109,97, -115,34,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119,120,84, -79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108, -97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98, -106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70, +84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101, +114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101, +99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,104,101, +99,107,76,105,115,116,66,111,120,34,32,110,97,109,101,61,34,108,115,116, +68,105,115,112,108,97,121,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68, +124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84, +60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100, +101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124, -119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60, -47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, -97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108, -97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,97,109,101,61,34,112, -110,108,66,114,111,119,115,101,114,68,105,115,112,108,97,121,34,62,10,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,105,100,100,101, -110,62,49,60,47,104,105,100,100,101,110,62,10,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, -61,34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108, +32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61, +34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99, +108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,32,110,97,109,101, +61,34,98,116,110,68,101,102,97,117,108,116,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108, +62,38,97,109,112,59,68,101,102,97,117,108,116,60,47,108,97,98,101,108,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68, +124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84, +60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100, +101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88, +80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82, +73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101, +114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101, +99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101, +99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101, +99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,97, +109,101,61,34,112,110,108,84,114,101,101,74,83,79,78,34,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,105,100,100,101,110, +62,49,60,47,104,105,100,100,101,110,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61, +34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108, 115,62,49,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,60,118,103,97,112,62,53,60,47,118,103,97,112,62, 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103, @@ -36052,11 +36709,164 @@ static unsigned char xml_res_file_80[] = { 122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115, 115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97,109, -101,61,34,115,116,68,97,116,97,98,97,115,101,79,98,106,101,99,116,115,34, +101,61,34,115,116,84,114,101,101,74,83,79,78,34,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101, +108,62,79,112,116,105,111,110,115,32,101,120,116,101,110,100,101,100,32, +74,83,79,78,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102, +108,97,103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120, +76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, +100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98, +106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101, +109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,84,114, +101,101,67,116,114,108,34,32,110,97,109,101,61,34,116,114,101,101,74,83, +79,78,34,32,115,117,98,99,108,97,115,115,61,34,99,116,108,84,114,101,101, +74,83,79,78,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,84,82,95,72,65,83, +95,66,85,84,84,79,78,83,124,119,120,83,73,77,80,76,69,95,66,79,82,68,69, +82,124,119,120,84,82,95,69,68,73,84,95,76,65,66,69,76,83,124,119,120,84, +82,95,70,85,76,76,95,82,79,87,95,72,73,71,72,76,73,71,72,84,124,119,120, +84,82,95,78,79,95,76,73,78,69,83,124,119,120,84,82,95,72,73,68,69,95,82, +79,79,84,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108, +97,103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76, +69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, +100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, +101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80, +124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100, +101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34, +115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34, +119,120,80,97,110,101,108,34,32,110,97,109,101,61,34,112,110,108,66,114, +111,119,115,101,114,80,114,111,112,101,114,116,105,101,115,34,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,105,100,100,101, +110,62,49,60,47,104,105,100,100,101,110,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, +61,34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108, +115,62,50,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,60,118,103,97,112,62,53,60,47,118,103,97,112,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103, +97,112,62,53,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108, +115,62,49,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101, +99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34, 62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,108,97,98,101,108,62,68,105,115,112,108,97,121,32,116,104,101, -32,102,111,108,108,111,119,105,110,103,32,100,97,116,97,98,97,115,101,32, -111,98,106,101,99,116,115,58,60,47,108,97,98,101,108,62,10,32,32,32,32, +60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116, +105,99,84,101,120,116,34,32,110,97,109,101,61,34,115,116,65,117,116,111, +82,111,119,67,111,117,110,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,111,117, +110,116,32,114,111,119,115,32,105,102,32,101,115,116,105,109,97,116,101, +100,32,108,101,115,115,32,116,104,97,110,60,47,108,97,98,101,108,62,10, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47, +111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67, +69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,84,79,80,124,119, +120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111, +114,100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116, +62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111, +98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116, +101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120, +84,101,120,116,67,116,114,108,34,32,110,97,109,101,61,34,116,120,116,65, +117,116,111,82,111,119,67,111,117,110,116,34,47,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119, +120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84,124, +119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114, +62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99, +116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,104,101,99, +107,66,111,120,34,32,110,97,109,101,61,34,99,104,107,78,117,109,98,101, +114,80,114,101,116,116,121,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,66,101,97,117, +116,105,102,117,108,32,98,105,103,32,110,117,109,98,101,114,115,32,111, +110,32,116,104,101,32,115,116,97,116,105,115,116,105,99,115,32,112,97,103, +101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,99,104,101,99,107,101,100,62,48,60, +47,99,104,101,99,107,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97, +103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69, +70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100, +101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101, +99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111, +98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124, +119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101, +114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115, +105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119, +120,80,97,110,101,108,34,32,110,97,109,101,61,34,112,110,108,66,114,111, +119,115,101,114,66,105,110,80,97,116,104,34,62,10,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,60,104,105,100,100,101,110,62,49,60,47, +104,105,100,100,101,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120, +70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,62,50,60, +47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,60,118,103,97,112,62,53,60,47,118,103,97,112,62,10,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62, +53,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,62,53, +60,47,103,114,111,119,97,98,108,101,114,111,119,115,62,10,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108, +101,99,111,108,115,62,49,60,47,103,114,111,119,97,98,108,101,99,111,108, +115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60, +111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105, +116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119, +120,83,116,97,116,105,99,84,101,120,116,34,32,110,97,109,101,61,34,115, +116,83,108,111,110,121,80,97,116,104,34,62,10,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83, +108,111,110,121,45,73,32,112,97,116,104,60,47,108,97,98,101,108,62,10,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111, +98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69, +78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,84,79,80,124,119,120, +76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, +100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98, +106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101, +109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,68,105, +114,80,105,99,107,101,114,67,116,114,108,34,32,110,97,109,101,61,34,112, +105,99,107,101,114,83,108,111,110,121,80,97,116,104,34,62,10,32,32,32,32, +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,109,101, +115,115,97,103,101,62,83,101,108,101,99,116,32,100,105,114,101,99,116,111, +114,121,32,119,105,116,104,32,83,108,111,110,121,45,73,32,99,114,101,97, +116,105,111,110,32,115,99,114,105,112,116,115,60,47,109,101,115,115,97, +103,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,32,32,32,32,60,115,116,121,108,101,62,119,120,68,73,82,80,95,85,83,69, +95,84,69,88,84,67,84,82,76,60,47,115,116,121,108,101,62,10,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, 101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119,120, @@ -36068,177 +36878,13 @@ static unsigned char xml_res_file_80[] = { 32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122, 101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115, -61,34,119,120,67,104,101,99,107,76,105,115,116,66,111,120,34,32,110,97, -109,101,61,34,108,115,116,68,105,115,112,108,97,121,34,62,10,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110, -116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, -69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119, -120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52, -60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32, -99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98, -106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110, -34,32,110,97,109,101,61,34,98,116,110,68,101,102,97,117,108,116,34,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,108,97,98,101,108,62,38,97,109,112,59,68,101,102,97,117,108,116,60,47, +61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97,109,101, +61,34,115,116,80,111,115,116,103,114,101,115,113,108,80,97,116,104,34,62, +10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, +32,60,108,97,98,101,108,62,80,71,32,98,105,110,32,112,97,116,104,60,47, 108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, -69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119, -120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52, -60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99, -116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97, -103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69, -70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60, -47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101, -114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97, -110,101,108,34,32,110,97,109,101,61,34,112,110,108,66,114,111,119,115,101, -114,80,114,111,112,101,114,116,105,101,115,34,62,10,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,60,104,105,100,100,101,110,62,49,60,47, -104,105,100,100,101,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120, -70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,62,50,60, -47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,118,103,97,112,62,53,60,47,118,103,97,112,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62, -53,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,62,49, -60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32, -99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98, -106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99, -84,101,120,116,34,32,110,97,109,101,61,34,115,116,65,117,116,111,82,111, -119,67,111,117,110,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,111,117,110, -116,32,114,111,119,115,32,105,102,32,101,115,116,105,109,97,116,101,100, -32,108,101,115,115,32,116,104,97,110,60,47,108,97,98,101,108,62,10,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98, -106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78, -84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,84,79,80,124,119,120,76, -69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114, -100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62, -10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98, -106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101, -109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,84,101, -120,116,67,116,114,108,34,32,110,97,109,101,61,34,116,120,116,65,117,116, -111,82,111,119,67,111,117,110,116,34,47,62,10,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69, -88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120, -82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60, -47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99, -108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, -101,99,116,32,99,108,97,115,115,61,34,119,120,67,104,101,99,107,66,111, -120,34,32,110,97,109,101,61,34,99,104,107,78,117,109,98,101,114,80,114, -101,116,116,121,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,66,101,97,117,116,105,102, -117,108,32,98,105,103,32,110,117,109,98,101,114,115,32,111,110,32,116,104, -101,32,115,116,97,116,105,115,116,105,99,115,32,112,97,103,101,60,47,108, -97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,60,99,104,101,99,107,101,100,62,48,60,47,99,104,101, -99,107,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, -69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69,70,84,124,119, -120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52, -60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99, -116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97, -103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80,124,119,120,76,69, -70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60, -47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101, -114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97, -110,101,108,34,32,110,97,109,101,61,34,112,110,108,66,114,111,119,115,101, -114,66,105,110,80,97,116,104,34,62,10,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,60,104,105,100,100,101,110,62,49,60,47,104,105,100, -100,101,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101, -120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,62,50,60,47,99,111, -108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,118,103,97,112,62,53,60,47,118,103,97,112,62,10,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,53,60,47, -104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,62,53,60,47,103, -114,111,119,97,98,108,101,114,111,119,115,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99, -111,108,115,62,49,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62, -10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98, -106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101, -109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116, -97,116,105,99,84,101,120,116,34,32,110,97,109,101,61,34,115,116,83,108, -111,110,121,80,97,116,104,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83,108,111, -110,121,45,73,32,112,97,116,104,60,47,108,97,98,101,108,62,10,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, -101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84, -69,82,95,86,69,82,84,73,67,65,76,124,119,120,84,79,80,124,119,120,76,69, -70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,62,10,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100, -101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106, -101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109, -34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,68,105,114, -80,105,99,107,101,114,67,116,114,108,34,32,110,97,109,101,61,34,112,105, -99,107,101,114,83,108,111,110,121,80,97,116,104,34,62,10,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,109,101,115, -115,97,103,101,62,83,101,108,101,99,116,32,100,105,114,101,99,116,111,114, -121,32,119,105,116,104,32,83,108,111,110,121,45,73,32,99,114,101,97,116, -105,111,110,32,115,99,114,105,112,116,115,60,47,109,101,115,115,97,103, -101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,60,115,116,121,108,101,62,119,120,68,73,82,80,95,85,83,69,95,84, -69,88,84,67,84,82,76,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99, -116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119,120,84,79,80, -124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103, -62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106, -101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101, -114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61, -34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97,109,101,61, -34,115,116,80,111,115,116,103,114,101,115,113,108,80,97,116,104,34,62,10, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -60,108,97,98,101,108,62,80,71,32,98,105,110,32,112,97,116,104,60,47,108, -97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, -32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32, -32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120, 65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119, 120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102, 108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, @@ -38959,8 +39605,8 @@ static unsigned char xml_res_file_80[] = { 32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116, 62,10,60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_81 = 1417; -static unsigned char xml_res_file_81[] = { +static size_t xml_res_size_82 = 1417; +static unsigned char xml_res_file_82[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -39029,8 +39675,8 @@ static unsigned char xml_res_file_81[] = { 60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62, 10,60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_82 = 5273; -static unsigned char xml_res_file_82[] = { +static size_t xml_res_size_83 = 5273; +static unsigned char xml_res_file_83[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -39285,8 +39931,8 @@ static unsigned char xml_res_file_82[] = { 32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101, 99,116,62,10,60,47,114,101,115,111,117,114,99,101,62,10}; -static size_t xml_res_size_83 = 15609; -static unsigned char xml_res_file_83[] = { +static size_t xml_res_size_84 = 15609; +static unsigned char xml_res_file_84[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101, 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62, 10,60,114,101,115,111,117,114,99,101,62,10,32,32,60,111,98,106,101,99,116, @@ -40078,24 +40724,25 @@ void InitXmlResource() XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgTextSearchDictionary.xrc"), xml_res_file_63, xml_res_size_63, wxT("text/xml")); XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgTextSearchParser.xrc"), xml_res_file_64, xml_res_size_64, wxT("text/xml")); XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgTextSearchTemplate.xrc"), xml_res_file_65, xml_res_size_65, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgTrigger.xrc"), xml_res_file_66, xml_res_size_66, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgType.xrc"), xml_res_file_67, xml_res_size_67, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgUser.xrc"), xml_res_file_68, xml_res_size_68, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgUserMapping.xrc"), xml_res_file_69, xml_res_size_69, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgView.xrc"), xml_res_file_70, xml_res_size_70, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmAwr.xrc"), xml_res_file_71, xml_res_size_71, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmBackup.xrc"), xml_res_file_72, xml_res_size_72, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmBackupGlobals.xrc"), xml_res_file_73, xml_res_size_73, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmBackupServer.xrc"), xml_res_file_74, xml_res_size_74, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmExport.xrc"), xml_res_file_75, xml_res_size_75, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmGrantWizard.xrc"), xml_res_file_76, xml_res_size_76, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmHint.xrc"), xml_res_file_77, xml_res_size_77, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmImport.xrc"), xml_res_file_78, xml_res_size_78, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmMaintenance.xrc"), xml_res_file_79, xml_res_size_79, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmOptions.xrc"), xml_res_file_80, xml_res_size_80, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmPassword.xrc"), xml_res_file_81, xml_res_size_81, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmReport.xrc"), xml_res_file_82, xml_res_size_82, wxT("text/xml")); - XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmRestore.xrc"), xml_res_file_83, xml_res_size_83, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgTransformText.xrc"), xml_res_file_66, xml_res_size_66, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgTrigger.xrc"), xml_res_file_67, xml_res_size_67, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgType.xrc"), xml_res_file_68, xml_res_size_68, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgUser.xrc"), xml_res_file_69, xml_res_size_69, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgUserMapping.xrc"), xml_res_file_70, xml_res_size_70, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._dlgView.xrc"), xml_res_file_71, xml_res_size_71, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmAwr.xrc"), xml_res_file_72, xml_res_size_72, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmBackup.xrc"), xml_res_file_73, xml_res_size_73, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmBackupGlobals.xrc"), xml_res_file_74, xml_res_size_74, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmBackupServer.xrc"), xml_res_file_75, xml_res_size_75, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmExport.xrc"), xml_res_file_76, xml_res_size_76, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmGrantWizard.xrc"), xml_res_file_77, xml_res_size_77, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmHint.xrc"), xml_res_file_78, xml_res_size_78, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmImport.xrc"), xml_res_file_79, xml_res_size_79, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmMaintenance.xrc"), xml_res_file_80, xml_res_size_80, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmOptions.xrc"), xml_res_file_81, xml_res_size_81, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmPassword.xrc"), xml_res_file_82, xml_res_size_82, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmReport.xrc"), xml_res_file_83, xml_res_size_83, wxT("text/xml")); + XRC_ADD_FILE(wxT("XRC_resource/xrcDialogs.cpp$._frmRestore.xrc"), xml_res_file_84, xml_res_size_84, wxT("text/xml")); wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._ddPrecisionScaleDialog.xrc")); wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._ddTableNameDialog.xrc")); wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._dlgAddFavourite.xrc")); @@ -40162,6 +40809,7 @@ void InitXmlResource() wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._dlgTextSearchDictionary.xrc")); wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._dlgTextSearchParser.xrc")); wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._dlgTextSearchTemplate.xrc")); + wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._dlgTransformText.xrc")); wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._dlgTrigger.xrc")); wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._dlgType.xrc")); wxXmlResource::Get()->Load(wxT("memory:XRC_resource/xrcDialogs.cpp$._dlgUser.xrc")); diff --git a/utils/WaitSample.cpp b/utils/WaitSample.cpp new file mode 100644 index 0000000..428e947 --- /dev/null +++ b/utils/WaitSample.cpp @@ -0,0 +1,714 @@ +#include "pgAdmin3.h" +#include "utils/WaitSample.h" +#include "wx/stdpaths.h" +#include "utils/utffile.h" +#include "utils/json/jsonval.h" + +void WaitSample::Init() { + wxString clr = "h1 { \ + region: \"IO:DataFileRead\", #3644ff;\n\ +region: \"IO:DataFileWrite\", #790808;\n\ +region: \"IO:BufFileRead\", #16658d;\n\ +region: \"IO:BufFileWrite\", #d30a0a;\n\ +region: \"IO:DataFileExtend\", #9720ba;\n\ +region: \"IO:DataFilePrefetch\", #c03ae8;\n\ +region: \"IO:DataFileFlush\", #b609ea;\n\ +region: \"IO:DataFileSync\", #b609ea;\n\ +region: \"IO:ReplicationSlotSync\", #b609ea;\n\ +region: \"IO:WALSync\", #ff6a00;\n\ +region: \"IO:WALWrite\", #ff6a00;\n\ +region: \"IO:WALInitWrite\", #ff6a00;\n\ +region: \"IO:WALRead\", #ba550e;\n\ +region: \"IO\", #2132bd;\n\ +region: \"IPC\", #908b3b;\n\ +region: \"Lock\", #ff0000;\n\ +region: \"Client\", #0b6222;\n\ +region: \"BufferPin\", #a4a3a0;\n\ +region: \"Client:ClientWrite\", #76bb88;\n\ +region: \"IPC:ArchiveCommand\", #fff200;\n\ +region: \"IPC:MessageQueueReceive\", #aaae4f;\n\ +region: \"IPC:MessageQueueSend\", #aaae4f;\n\ +region: \"LWLock\", #87f566;\n\ +region: \"LWLock:WALWrite\", #3bf61e;\n\ +region: \"LWLock:WALInsert\", #3bf61e;\n\ +region: \"LWLock:Autovacuum\", #20bb08;\n\ +region: \"LWLock:BufferContent\", #98db19;\n\ +region: \"Timeout\", #6ce4c6;\n\ +region: \"Timeout:VacuumDelay\", #20bb08;\n\ +}"; + wxStringTokenizer tk(clr, "\n", wxTOKEN_DEFAULT); + wxString cc; + wxString cnt; + wxString ee; + wxString l; + wxJSONValue events(wxJSONType::wxJSONTYPE_ARRAY); + while (tk.HasMoreTokens()) + { + wxString l = tk.GetNextToken(); + wxString w = l.AfterFirst('"').BeforeFirst('"'); + if (w.IsEmpty()) continue; + wxString c = l.AfterFirst('#').BeforeFirst(';'); + unsigned long tmp; + wxSscanf(c, "%lx", &tmp); + wait_idx.emplace(w, tmp); + wxJSONValue e(wxJSONType::wxJSONTYPE_OBJECT); + wxColour cc3("#"+c); + e["enable"] = true; + e["color"] = "#" + c; + e["name"] = w; + events.Append(e); + } + wxJSONValue def(wxJSONType::wxJSONTYPE_OBJECT); + def["events"] = events; + //def["autoloadcache_sql"] = true; + group.push_back("BufferPin"); + group.push_back("Client"); + group.push_back("IO"); + group.push_back("IPC"); + group.push_back("Lock"); + group.push_back("Activity"); + group.push_back("LWLock"); + group.push_back("Timeout"); + settings->ReloadJsonFileIfNeed(); + settings->ReadJsonObect("WaitEvents", opt, def); + // settings->WriteJsonFile(); + if (!opt.IsNull()) { + wait_idx.clear(); + wxJSONValue r = opt["events"]; + for (int j = 0; j < r.Size(); j++) { + wxJSONValue e = r[j]; + bool enable = e["enable"].AsBool(); + wxString c= e["color"].AsString(); + unsigned long tmp; + wxSscanf(c, "#%lx", &tmp); + wxColour cc(tmp); + if (!cc.IsOk()) cc = *wxBLACK; + //wxSscanf(c, "%lx", &tmp); + wxString w = e["name"].AsString(); + wait_idx.emplace(w, tmp); + if (!enable) wait_disable.emplace(w,0); + } + } + else opt = def; + wxString tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxFileName::GetPathSeparator() + "postgresql" + wxFileName::GetPathSeparator() + "cache_sql.txt"; + wxTextFile file(tempDir); + if (file.Exists()) file.Open(); + if (file.IsOpened()) + { + wxString str; + wxString sql; + long long qid; + for (str = file.GetFirstLine(); !file.Eof(); str = file.GetNextLine()) + { + if (str.length() == 16) { + unsigned long long temp_qid = 0; + int cntbits = 0; + for (int i = str.length() - 1; i >= 0; i--, cntbits = cntbits + 4) + { + unsigned char h = str[i]; + unsigned char n09 = h - '0'; + unsigned char nAF = (h | 0x20) - 'a'; + if ((n09 <= (9 - 0)) || (nAF <= (0xf - 0xa))) { + // is hex digits + } + else break; + unsigned long long tetra = ((h & 0xf) + (h >> 6) * 9); + temp_qid |= tetra << cntbits; + } + if (cntbits == 64) { + //wxString tmp = sql.BeforeLast('\n'); + //if (tmp.IsEmpty()) tmp=sql; + if (sql.length() > 0) AddQuery(qid, sql); // previos sql + qid = temp_qid; + sql = wxEmptyString; + continue; + } + } + if (!sql.IsEmpty()) sql.Append('\n'); + sql.Append(str); + } + //file.ReadAll(&str); + file.Close(); + if (sql.length() > 0) + { + //wxString tmp = sql.BeforeLast('\n'); + //if (tmp.IsEmpty()) tmp = sql; + AddQuery(qid, sql); // previos sql + + } + + } +} +std::vector* WaitSample::GetSamples() { return &smp; } +std::vector WaitSample::GetColors() { return colors; } + +wxArrayString WaitSample::GetWaitIdNameArray(bool onlyGroup) { + typedef std::pair pair; + // sort map by value; + std::vector vec; + std::copy(wait_id.begin(), + wait_id.end(), + std::back_inserter>(vec)); + std::sort(vec.begin(), vec.end(), + [](const pair& l, const pair& r) + { + if (l.second != r.second) { + return l.second < r.second; + } + + return l.first < r.first; + }); + wxArrayString a; + for (auto const& pair : vec) { + //std::cout << '{' << pair.first << "," << pair.second << '}' << std::endl; + wxString n = pair.first; + if (onlyGroup) { + if (!n.BeforeFirst(':').IsEmpty()) n = n.BeforeFirst(':'); + } + a.Add(n); + + } + return a; +} +// return position in smp vector +int WaitSample::GetHomeInterval(int timeEnd, int AggrigateInterval) { + Sample sa; + if (timeEnd == -1) { + // end smp + sa = smp.back(); + timeEnd = sa.btime; + } + else { + + } + long long th = ((basetime + timeEnd) / AggrigateInterval) * AggrigateInterval; + int home_int = th - basetime; + if (th > (basetime + timeEnd)) { + //long long te = th - AggrigateInterval; + home_int = th - AggrigateInterval - basetime; + } + return home_int; + + //wxLongLong l(((basetime + timeEnd)/AggrigateInterval)* AggrigateInterval); + //wxDateTime t(l); +} +int WaitSample::getPositionByTime(int time) { + + int max = smp.size() - 1; + int min = 0; + int i = (max - min) / 2; + while (i != -1) { + int t = smp[i].btime; + if (t < time) { + min = i; + i = min + (max - min) / 2; + } + else if (t > time) { + max = i; + i = min + (max - min) / 2; + } + else { + while (i > 0 && smp[i - 1].btime == t) { + i--; + } + break; + } + if (max - min < 2) { + i = max; + break; + } + } + return i; + +} + +int WaitSample::wait_class(wxString wclass) { + int i = 0; + for (const auto& name : group) { + if (name == wclass) return i; + i++; + } + wxFAIL_MSG("Unknown wait class " + wclass); + return -1000; +} +// return count group +int WaitSample::GetGroupingData(int timeEnd, int needCountGroup, int groupInterval, + wxString groupRule, wxArrayString& nameGroup, + std::vector& xAxisValue, + std::vector& yAxisValue, + std::vector& Values, // массив столбцов справа на лево + std::vector& clr // цета слоёв размерностью groupRule.Count() +) +{ + int idx_grp = wait_id.size(); + std::vector filter_map(wait_id.size() + group.size()); + std::vector summary(wait_id.size() + group.size()); + for (size_t i = 0; i < filter_map.size(); i++) filter_map[i] = -1; + nameGroup.Clear(); + //std::map wait_id_name; + long long qidfilter = -1; + for (const auto& kv : wait_id) { + //std::cout << kv.first << " has value " << kv.second << std::endl; + wxString w_name = kv.first; + int w_id = kv.second; + //wait_id_name.emplace(w_id, w_name); + bool enable = true; + wxString grp_name = w_name.BeforeFirst(':'); + if (grp_name.IsEmpty()) grp_name = w_name; + int cl = wait_class(grp_name); + bool isF = false; + if (!groupRule.IsEmpty()) { + wxStringTokenizer tk(groupRule, ";", wxTOKEN_DEFAULT); + wxString l; + bool isDis = true; + bool isGrp = true; + + while (tk.HasMoreTokens()) + { + l = tk.GetNextToken(); + if (l[0] == '@') { + if (qidfilter == -1) { + int cntbits = 0; + unsigned long long temp_qid = 0; + for (int i = l.length() - 1; i > 0; i--, cntbits = cntbits + 4) + { + unsigned char h = l[i]; + unsigned char n09 = h - '0'; + unsigned char nAF = (h | 0x20) - 'a'; + if ((n09 <= (9 - 0)) || (nAF <= (0xf - 0xa))) { + // is hex digits + } + else break; + unsigned long long tetra = ((h & 0xf) + (h >> 6) * 9); + temp_qid |= tetra << cntbits; + } + qidfilter = temp_qid; + } + continue; + } + isDis = l[0] == '-'; + if (isDis) l = l.substr(1); + isGrp = l.find(':') == -1; + if (w_name == l) { + if (isDis) { + filter_map[w_id] = w_id; //disable in Grp + if (filter_map[idx_grp + cl] < 0) filter_map[idx_grp + cl] = -2; + } + else { + //filter_map[w_id] = w_id; + isF = false; //default + break; + } + isF = true; + break; + } + if (isGrp) { + + if (grp_name == l) { + if (isDis) { + // Groups equal and disable + filter_map[w_id] = w_id; // disable w_id Grp ALL disable + filter_map[idx_grp + cl] = -2; // disable group + isF = true; + break; + } + // default rule + break; + } + continue; // next rule + } + } + } + if (!isF) { + // no found in Rule + filter_map[w_id] = idx_grp + cl; // wait_id -> [idx_grp + cl] + filter_map[idx_grp + cl] = 999; // visible + //filter_map[idx_grp+cl]= + } + + + } + // nameGroup + // begin Group + wxString n, g; + clr.clear(); + clr.resize(filter_map.size()); + for (size_t i = idx_grp; i < filter_map.size(); i++) + { + int wait_id = filter_map[i]; + if (wait_id == -1) continue; + n = group[i - idx_grp]; + g = n; + clr[i] = GetColorByWaitName(n); + if (wait_id == -2) n = '-' + n; + nameGroup.Add(n); + // individual wait + for (size_t j = 0; j < idx_grp; j++) + { + int wait_id = filter_map[j]; + n = wait_id_name[j]; + wxString grp_name = n.BeforeFirst(':'); + if (grp_name.IsEmpty()) grp_name = n; + if (grp_name != g) continue; + if (!n.AfterFirst(':').IsEmpty()) n = n.AfterFirst(':'); + if (wait_id == j) n = "--" + n; else n = " " + n; + nameGroup.Add(n); + clr[j] = GetColorByWaitName(wait_id_name[j]); + } + + + } + + + int homeInt = GetHomeInterval(timeEnd, groupInterval); + Sample sa; + if (timeEnd == -1) { + sa = smp.back(); + timeEnd = sa.btime; + } + int idx = getPositionByTime(timeEnd); + for (size_t i = 0; i < summary.size(); i++) summary[i] = 0; + Values.clear(); + xAxisValue.clear(); + //for (size_t i = 0; i < maxS.size(); i++) maxS[i] = 0; + long long maxsum = 0; + int minsum = 0; + int nGrp = needCountGroup; + while (idx >= 0) { + sa = smp[idx--]; + if (sa.btime >= homeInt && idx >= 0) { + } + else { + // new interval + wxLongLong l(basetime + homeInt); + wxDateTime t(l); + xAxisValue.push_back(t); + std::vector itog(summary.size()); + int ni = idx_grp; + int Ymax = 0; + for (size_t i = 0; i < itog.size(); i++) + { + + int wait_id = filter_map[i]; + if (wait_id < 0) { itog[i] = wait_id; continue; } + int a = summary[i]; + itog[i] = a; + if (i >= idx_grp) Ymax += a; + //if (minsum > a) minsum = a; + } + if (maxsum < Ymax) maxsum = Ymax; + Values.push_back(itog); + homeInt -= groupInterval; + nGrp--; + if (nGrp == 0) break; + for (size_t i = 0; i < summary.size(); i++) summary[i] = 0; + } + if (qidfilter != -1 && sa.qid != qidfilter) continue; + int w_id = sa.wait_id; + if (filter_map[w_id] < 0) continue; + int ii = filter_map[w_id]; + // grp + int s = sa.samples * periodms; + if (ii != w_id) summary[ii] += s; + // details + summary[w_id] += s; + } + yAxisValue.clear(); + yAxisValue.push_back(wxTimeSpan(0, 0, 0, maxsum)); + return Values.size(); +} +int WaitSample::GetInterval(int posStart, int posEnd) { + Sample sa1, sa2; + if (smp.size() == 0) return 0; + if (posEnd == -1) { + sa2 = smp.back(); + } + else sa2 = smp.at(posEnd); + sa1 = smp.at(posStart); + return sa2.btime - sa1.btime; +} +bool WaitSample::AddQuery(long long qid, wxString sql) { + if (qid_sql.find(qid) == qid_sql.end()) { + qid_sql.emplace(qid, sql); + return true; + } + return false; +} +wxString WaitSample::GetQueryByQid(long long qid) { + if (qid_sql.find(qid) != qid_sql.end()) { + wxString sql = qid_sql[qid]; + return sql; + } + return wxEmptyString; + +} +void WaitSample::LoadFileSamples() { + wxString tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxFileName::GetPathSeparator() + "postgresql" + wxFileName::GetPathSeparator() + "sample.dat"; + wxTextFile file(tempDir); + file.Open(); + if (file.IsOpened()) + { + wxString str; + for (str = file.GetFirstLine() + '\n'; !file.Eof(); str += file.GetNextLine() + '\n') + { + + } + //file.ReadAll(&str); + file.Close(); + + wxStringTokenizer tk(str, "\n", wxTOKEN_DEFAULT); + wxString cc; + wxString cnt; + wxString ee; + wxString l; + int nl = 0; + while (tk.HasMoreTokens()) + { + wxString l = tk.GetNextToken(); + if (l.IsEmpty()) continue; + if (nl == 0) { + long long t; + wxSscanf(l, "%lld", &basetime); + nl++; + continue; + } + if (nl == 4) { + //smp + //wxString w_name = tk.GetNextToken(); + //wxString w_id = tk2.GetNextToken(); + int tmp = 0; + Sample sa; + if (wxSscanf(l, "%d %d %d %d %lld %d %d", &sa.btime, &sa.etime, &sa.wait_id, &sa.pid, &sa.qid, &sa.btype, &sa.samples) != 7) { + wxLogError("Invalid count parameters '%s'.", l); + } + /*wxSscanf(tk2.GetNextToken(), "%d", &sa.btime); + wxSscanf(tk2.GetNextToken(), "%d", &sa.etime); + wxSscanf(tk2.GetNextToken(), "%d", &sa.wait_id); + wxSscanf(tk2.GetNextToken(), "%d", &sa.pid); + wxSscanf(tk2.GetNextToken(), "%lld", &sa.qid); + wxSscanf(tk2.GetNextToken(), "%d", &sa.btype); + wxSscanf(tk2.GetNextToken(), "%d", &sa.samples);*/ + smp.push_back(sa); + continue; + } + + wxStringTokenizer tk2(l, " ", wxTOKEN_DEFAULT); + if (nl == 1) { + //btype + + while (tk2.HasMoreTokens()) + { + wxString b_name, b_id; + while (b_id.IsEmpty()) { + wxString str = tk2.GetNextToken(); + if (!wxIsdigit(str[0])) + b_name += b_name.IsEmpty() ? str : " " + str; + else b_id = str; + } + unsigned long tmp; + wxSscanf(b_id, "%ld", &tmp); + int i = GetBackendTypeId(b_name); + if (i != tmp) { + + } + } + nl++; + continue; + } + if (nl == 2) { + //wait_id + while (tk2.HasMoreTokens()) + { + wxString w_name, w_id; + while (w_id.IsEmpty()) { + wxString str = tk2.GetNextToken(); + if (!wxIsdigit(str[0])) + w_name += w_name.IsEmpty() ? str : " " + str; + else w_id = str; + } + unsigned long tmp; + wxSscanf(w_id, "%ld", &tmp); + wait_id.emplace(w_name, tmp); + wait_id_name.emplace(tmp, w_name); + } + nl++; + continue; + } + if (nl == 3) { + //colors + int sz = wait_id.size(); + colors.resize(sz); + int i = 0; + while (tk2.HasMoreTokens()) + { + wxString c = tk2.GetNextToken(); + unsigned long tmp; + wxSscanf(c, "%ld", &tmp); + colors[i++] = tmp; + } + nl++; + continue; + } + } + + } +} +void WaitSample::SaveFileSamples() { + wxString tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxFileName::GetPathSeparator() + "postgresql" + wxFileName::GetPathSeparator() + "sample.dat"; + wxUtfFile file(tempDir, wxFile::write, wxFONTENCODING_UTF8); + if (file.IsOpened()) + { + wxString strnl; + strnl = wxString::Format("%lld\n", basetime); + file.Write(strnl); + strnl.Clear(); + //btype + int i = 0; + for (const auto& e : btype) { + if (!strnl.IsEmpty()) strnl += ' '; + strnl += wxString::Format("%s %d", e, i); + i++; + } + strnl += '\n'; + file.Write(strnl); + // wait_id + strnl.Clear(); + for (const auto& e : wait_id) { + if (!strnl.IsEmpty()) strnl += ' '; + strnl += wxString::Format("%s %d", e.first, e.second); + } + strnl += '\n'; + file.Write(strnl); + strnl.Clear(); + for (const auto& e : colors) { + if (!strnl.IsEmpty()) strnl += ' '; + strnl += wxString::Format("%d", e); + } + strnl += '\n'; + file.Write(strnl); + strnl.Clear(); + for (const auto& e : smp) { + strnl.Append(wxString::Format("%d %d %d %d %lld %d %d\n", e.btime, e.etime, e.wait_id, e.pid, e.qid, e.btype, e.samples)); + } + file.Write(strnl); + file.Close(); + } + tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxFileName::GetPathSeparator() + "postgresql" + wxFileName::GetPathSeparator() + "cache_sql.txt"; + wxUtfFile file1(tempDir, wxFile::write, wxFONTENCODING_UTF8); + if (file1.IsOpened()) + { + wxString str; + + for (const auto& e : qid_sql) { + wxLongLong l(e.first); + + str = wxString::Format("%0x%0x\n%s\n", l.GetHi(), l.GetLo(), e.second); + file1.Write(str); + } + file1.Close(); + } +} + +void WaitSample::AddSample(int pid, bool isXidTransation, wxString& btype, const wxString& sample) { + //PidWait pw(pid, basetime);; + // поиск + int pw; + auto iter = pids.find(pid); + if (iter != pids.end()) { + //std::cout << "Found the key " << iter->first << " with the value " << iter->second << "\n"; + pw = iter->second; + } + else { + pids.emplace(pid, pw); + } + ++chkpids[pid]; + int bt = GetBackendTypeId(btype); + //pw.AddSample(sample, active, timebegiserios, timeendserios); + wxStringTokenizer tk(sample, ";", wxTOKEN_DEFAULT); + wxString cnt; + wxString w; + wxString et; + while (tk.HasMoreTokens()) + { + wxString et = tk.GetNextToken(); + wxString cnt = et.AfterLast(':'); + et = et.BeforeLast(':'); + wxString tqid = et.AfterLast(':'); + wxString w = et.BeforeLast(':'); + // ignore ClientRead out transaction + if (w == "Client:ClientRead" && !isXidTransation) + continue; + int smp_cnt; + long long qid; + wxSscanf(cnt, "%d", &smp_cnt); + wxSscanf(tqid, "%lld", &qid); + auto dis_it = wait_disable.find(w); + if (dis_it != wait_disable.end()) { + continue; + } + auto iter = wait_id.find(w); + int id; + if (iter == wait_id.end()) { + id = wait_id.size(); + wait_id.emplace(w, id); + wait_id_name.emplace(id, w); + //map color + long c = 0; + auto it2 = wait_idx.find(w); + if (it2 == wait_idx.end()) { + it2 = wait_idx.find(w.BeforeFirst(':')); + if (it2 != wait_idx.end()) { + c = it2->second; + } + } + else c = it2->second; + colors.push_back(c); + //colors + } + else id = iter->second; + + Sample sa; + sa.btime = timebegiserios; + sa.etime = timeendserios; + sa.wait_id = id; + sa.samples = smp_cnt; + sa.pid = pid; + sa.qid = qid; + sa.btype = bt; + smp.push_back(sa); + //pw.AddSample(); + } + +} +int WaitSample::GetBackendTypeId(wxString backend_type) { + int idx = 0; + auto it = std::find_if(btype.begin(), btype.end(), [&](const wxString& s) { + idx++; + return s == backend_type; + } + ); + if (it != btype.end()) return idx - 1; + btype.push_back(backend_type); + return idx; +} +std::vector tmp_idx_colors; +bool compareBySample(const Sample& a, const Sample& b) +{ + if (tmp_idx_colors[a.wait_id] < tmp_idx_colors[b.wait_id]) + return true; + if (tmp_idx_colors[b.wait_id] < tmp_idx_colors[a.wait_id]) + return false; + return a.samples < b.samples; +} + +void WaitSample::EndSeriosSample() { + int end_index = smp.size(); + if ((end_index - start_index_serios) < 2) return; + // sort + //(std::list::iterator it = C.begin(), end = C.end(); it != end; ++it) + std::vector::iterator it = smp.end(); + it = it - (end_index - start_index_serios); + tmp_idx_colors = colors; + std::sort(it, smp.end(), compareBySample); + return; +}