Skip to content

Commit ef37adb

Browse files
committed
PVA search monitor command line tool
1 parent c483e0b commit ef37adb

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed

core/pva/pvasearchmonitor

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh
2+
3+
JAR=`echo target/core-pva*.jar`
4+
if [ -r "$JAR" ]
5+
then
6+
# Echo use jar file
7+
java -jar $JAR "$@"
8+
else
9+
# Use build output
10+
java -cp target/classes org.epics.pva.server.PVASearchMonitorMain "$@"
11+
fi
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2022 Oak Ridge National Laboratory.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
******************************************************************************/
8+
package org.epics.pva.server;
9+
10+
import java.net.InetSocketAddress;
11+
import java.time.Instant;
12+
import java.util.concurrent.ConcurrentHashMap;
13+
import java.util.concurrent.CountDownLatch;
14+
import java.util.concurrent.TimeUnit;
15+
import java.util.concurrent.atomic.AtomicLong;
16+
import java.util.logging.Level;
17+
import java.util.logging.LogManager;
18+
19+
import org.epics.pva.PVASettings;
20+
21+
/** PVA Search monitor
22+
*
23+
* May be called as
24+
* java -cp core-pva.jar org.epics.pva.server.PVASearchMonitorMain
25+
* or from Phoebus product via
26+
* phoebus.sh -main org.epics.pva.server.PVASearchMonitorMain
27+
*
28+
* @author Kay Kasemir
29+
*/
30+
@SuppressWarnings("nls")
31+
public class PVASearchMonitorMain
32+
{
33+
/** Recent search */
34+
private static class SearchInfo implements Comparable<SearchInfo>
35+
{
36+
/** PV Name */
37+
final String name;
38+
39+
/** How often some client has searched for it */
40+
final AtomicLong count = new AtomicLong();
41+
42+
/** Client that searched most recently */
43+
volatile InetSocketAddress client;
44+
45+
/** Time of last search */
46+
volatile Instant last = null;
47+
48+
SearchInfo(final String name)
49+
{
50+
this.name = name;
51+
}
52+
53+
@Override
54+
public int compareTo(final SearchInfo other)
55+
{
56+
final long diff = other.count.get() - count.get();
57+
if (diff < 0)
58+
return -1;
59+
if (diff > 0)
60+
return 1;
61+
return 0;
62+
}
63+
}
64+
65+
/** Map of PV name to search info */
66+
private static final ConcurrentHashMap<String, SearchInfo> searches = new ConcurrentHashMap<>();
67+
68+
private static void help()
69+
{
70+
System.out.println("USAGE: pvasearchmonitor [options]");
71+
System.out.println();
72+
System.out.println("Options:");
73+
System.out.println(" -h Help");
74+
System.out.println(" -p <seconds> Update period (default 10 seconds)");
75+
System.out.println(" -1 Update once, then quit");
76+
System.out.println(" -v <level> Verbosity, level 0-5");
77+
System.out.println();
78+
System.out.println("Waits for the specified period,");
79+
System.out.println("then prints information about received search requests.");
80+
}
81+
82+
private static void setLogLevel(final Level level)
83+
{
84+
PVASettings.logger.setLevel(level);
85+
}
86+
87+
/** Command line entry point
88+
* @param args Arguments
89+
* @throws Exception on error
90+
*/
91+
public static void main(String[] args) throws Exception
92+
{
93+
LogManager.getLogManager().readConfiguration(PVASettings.class.getResourceAsStream("/pva_logging.properties"));
94+
setLogLevel(Level.WARNING);
95+
long update_period = 10;
96+
boolean once = false;
97+
98+
for (int i=0; i<args.length; ++i)
99+
{
100+
final String arg = args[i];
101+
if (arg.startsWith("-h"))
102+
{
103+
help();
104+
return;
105+
}
106+
if (arg.startsWith("-1"))
107+
once = true;
108+
else if (arg.startsWith("-p") && (i+1) < args.length)
109+
update_period = Long.parseLong(args[i+1]);
110+
else if (arg.startsWith("-v") && (i+1) < args.length)
111+
{
112+
switch (Integer.parseInt(args[i+1]))
113+
{
114+
case 0:
115+
setLogLevel(Level.WARNING);
116+
break;
117+
case 1:
118+
setLogLevel(Level.CONFIG);
119+
break;
120+
case 2:
121+
setLogLevel(Level.INFO);
122+
break;
123+
case 3:
124+
setLogLevel(Level.FINE);
125+
break;
126+
case 4:
127+
setLogLevel(Level.FINER);
128+
break;
129+
case 5:
130+
default:
131+
setLogLevel(Level.ALL);
132+
}
133+
++i;
134+
}
135+
}
136+
137+
final CountDownLatch done = new CountDownLatch(1);
138+
139+
final SearchHandler search_handler = (seq, cid, name, addr, reply_sender) ->
140+
{
141+
// Quit when receiving search for name "QUIT"
142+
if (name.equals("QUIT"))
143+
done.countDown();
144+
145+
final SearchInfo search = searches.computeIfAbsent(name, n -> new SearchInfo(name));
146+
search.count.incrementAndGet();
147+
search.last = Instant.now();
148+
search.client = addr;
149+
150+
// Done, don't proceed with default search handler
151+
return true;
152+
};
153+
154+
try
155+
( final PVAServer server = new PVAServer(search_handler) )
156+
{
157+
System.out.println("Monitoring search requests for " + update_period + " seconds...");
158+
if (! once)
159+
System.out.println("Run 'pvget QUIT' to stop");
160+
while (! done.await(update_period, TimeUnit.SECONDS))
161+
{
162+
System.out.println("\nCount Name Last Client Age");
163+
final Instant now = Instant.now();
164+
searches.values()
165+
.stream()
166+
.sorted()
167+
.forEach(info ->
168+
{
169+
System.out.format("%5d %-20s %-35s %6d sec\n",
170+
info.count.get(),
171+
info.name,
172+
info.client.toString(),
173+
now.getEpochSecond() - info.last.getEpochSecond());
174+
});
175+
if (once)
176+
break;
177+
}
178+
}
179+
180+
System.out.println("Done.");
181+
}
182+
}

0 commit comments

Comments
 (0)