001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.transaction.gui; 020 021import org.jpos.transaction.TransactionStatusListener; 022import org.jpos.transaction.TransactionStatusEvent; 023import org.jpos.transaction.TransactionManager; 024import org.jpos.ui.UI; 025import org.jpos.util.TPS; 026 027import javax.swing.*; 028import javax.swing.event.AncestorEvent; 029import javax.swing.event.AncestorListener; 030import javax.swing.table.TableModel; 031import javax.swing.table.AbstractTableModel; 032import javax.swing.table.TableColumnModel; 033import javax.swing.table.DefaultTableCellRenderer; 034import java.awt.*; 035import java.awt.event.ActionEvent; 036import java.awt.event.ActionListener; 037 038public class TMMonitor extends JPanel 039 implements TransactionStatusListener, SwingConstants, ActionListener, AncestorListener 040{ 041 UI ui; 042 TransactionManager txnmgr; 043 JTable table; 044 AbstractTableModel model; 045 TransactionStatusEvent[] events; 046 JLabel tps = new JLabel("0"); 047 JLabel tpsAvg = new JLabel("0.00"); 048 JLabel tpsPeak = new JLabel("0"); 049 JLabel inTransit = new JLabel("0"); 050 JLabel outstanding = new JLabel("0"); 051 Timer timer; 052 053 static final Font SMALL = Font.decode ("terminal-plain-8"); 054 static final Font LARGE = Font.decode ("terminal-plain-18"); 055 056 Color[] color = new Color[] { 057 /* READY */ Color.white, 058 /* PREPARING */ new Color (0xb3, 0xb3, 0xff), // blue 059 /* PREPARING_FOR_ABORT */ new Color (0xff, 0xa3, 0xa3), // red 060 /* COMMITTING */ new Color (0xd1, 0xff, 0xd1), // green 061 /* ABORTING */ new Color (0xff, 0xa3, 0xa3), // red 062 /* DONE */ Color.white, 063 /* PAUSED */ new Color (0xff, 0x7f, 0x50) // orange 064 }; 065 066 public TMMonitor (UI ui, TransactionManager tmmgr) { 067 super(); 068 this.ui = ui; 069 this.txnmgr = tmmgr; 070 setLayout(new BorderLayout()); 071 setBorder(BorderFactory.createRaisedBevelBorder()); 072 model = createModel (); 073 074 table = createTable (model); 075 JScrollPane scrollPane = new JScrollPane(table); 076 077 add(createTPSPanel(), BorderLayout.EAST); 078 add(scrollPane, BorderLayout.CENTER); 079 tmmgr.addListener(this); 080 addAncestorListener(this); 081 } 082 public void update(TransactionStatusEvent e) { 083 if (ui.isDestroyed()) { 084 return; 085 } 086 int row = e.getSession(); 087 events[row] = e; 088 model.fireTableRowsUpdated(row, row); 089 // table.getSelectionModel().setSelectionInterval(row, row); 090 setBackgroundColor (row, color[e.getState().intValue()]); 091 inTransit.setText (Long.toString (txnmgr.getInTransit())); 092 outstanding.setText (Long.toString (txnmgr.getOutstandingTransactions())); 093 } 094 private void setBackgroundColor (int row, Color color) { 095 for (int i=0; i<model.getColumnCount(); i++) { 096 ((DefaultTableCellRenderer)table.getCellRenderer(row, i)).setBackground(color); 097 } 098 } 099 private JTable createTable (TableModel model) { 100 JTable table = new JTable (model); 101 table.setSurrendersFocusOnKeystroke(true); 102 table.setFillsViewportHeight(true); 103 table.setShowVerticalLines(true); 104 table.setCellSelectionEnabled(false); 105 table.setDoubleBuffered(true); 106 TableColumnModel tcm = table.getColumnModel(); 107 108 tcm.getColumn(0).setPreferredWidth(10); 109 tcm.getColumn(1).setPreferredWidth(25); 110 tcm.getColumn(2).setPreferredWidth(100); 111 tcm.getColumn(3).setPreferredWidth(600); 112 return table; 113 } 114 private JComponent createTPSPanel () { 115 JPanel outer = new JPanel (new BorderLayout()); 116 117 JPanel p = new JPanel (new GridLayout (5,2)); 118 119 add (p, tps, "TPS"); 120 add (p, tpsPeak, "Peak TPS"); 121 add (p, tpsAvg, "Avg TPS"); 122 add (p, inTransit, "InTransit"); 123 add (p, outstanding, "Queue"); 124 125 JPanel blackFiller = new JPanel(); 126 outer.add (p, BorderLayout.NORTH); 127 blackFiller.setBackground(Color.black); 128 outer.add (blackFiller, BorderLayout.CENTER); 129 outer.setPreferredSize(new Dimension (170, 0)); 130 return outer; 131 } 132 133 private void add (JPanel p, JLabel l, String description) { 134 setLabelStyle (l, LARGE, RIGHT); 135 p.add (l); 136 p.add (setLabelStyle (new JLabel (description), SMALL, LEFT)); 137 } 138 private JLabel setLabelStyle (JLabel l, Font f, int alignment) { 139 l.setBorder (BorderFactory.createLoweredBevelBorder ()); 140 l.setFont (f); 141 l.setOpaque (true); 142 l.setForeground(Color.green); 143 l.setBackground(Color.black); 144 // l.setAlignment(alignment); 145 l.setHorizontalAlignment(alignment); 146 l.setVerticalAlignment(BOTTOM); 147 return l; 148 } 149 private AbstractTableModel createModel () { 150 events = new TransactionStatusEvent[txnmgr.getActiveSessions()]; 151 return new AbstractTableModel() { 152 String[] columnName = new String[] { 153 "#", "id", "State", "Info" 154 }; 155 Class[] columnClass = new Class[] { 156 Integer.class, Long.class, String.class, String.class 157 }; 158 public int getColumnCount() { 159 return 4; 160 } 161 public int getRowCount() { 162 return txnmgr.getActiveSessions(); 163 } 164 @Override 165 public String getColumnName(int columnIndex) { 166 return columnName[columnIndex]; 167 } 168 public Class getColumnClass(int columnIndex) { 169 return columnClass[columnIndex]; 170 } 171 public Object getValueAt(int row, int col) { 172 if (events[row] != null) { 173 switch (col) { 174 case 0: 175 return row; 176 case 1: 177 return events[row].getId(); 178 case 2: 179 return events[row].getStateAsString(); 180 case 3: 181 return events[row].getInfo(); 182 } 183 } 184 return ""; 185 } 186 }; 187 } 188 189 public void actionPerformed(ActionEvent e) { 190 TPS t = txnmgr.getTPS(); 191 tps.setText (Integer.toString (t.intValue())); 192 tpsAvg.setText (String.format ("%.2f", t.getAvg())); 193 tpsPeak.setText (Integer.toString (t.getPeak())); 194 } 195 196 public void ancestorAdded(AncestorEvent event) { 197 if (timer == null) { 198 timer = new Timer (1000, this); 199 timer.start(); 200 } 201 } 202 203 public void ancestorRemoved(AncestorEvent event) { 204 if (timer != null) { 205 timer.stop(); 206 timer = null; 207 } 208 } 209 210 public void ancestorMoved(AncestorEvent event) { } 211}