JedisMovedDataException (When using sadd with pipeline) - redis

I have a 3 node EC2 redis cluster setup and I am trying to add records to redis (using sadd) with pipeline mode.
I get the following error after adding about 70/82 and 81 keys in 3 nodes:
Exception in thread "main" redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 1539 172.31.59.103:6379
at redis.clients.jedis.Protocol.processError(Protocol.java:93)
at redis.clients.jedis.Protocol.process(Protocol.java:122)
at redis.clients.jedis.Protocol.read(Protocol.java:191)
at redis.clients.jedis.Connection.getOne(Connection.java:258)
at redis.clients.jedis.ShardedJedisPipeline.sync(ShardedJedisPipeline.java:44)
at org.hu.e63.MovieLens21MPipeline.push(MovieLens21MPipeline.java:47)
at org.hu.e63.MovieLens21MPipeline.main(MovieLens21MPipeline.java:53
I have looked at this thread, my code pretty much looks like that:
Input file is from here(ratings.csv): http://files.grouplens.org/datasets/movielens/ml-latest-small.zip
Here's the code:
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPipeline;
public class MovieLens21MPipeline {
ShardedJedis jedis;
public MovieLens21MPipeline() {
JedisShardInfo si = new JedisShardInfo("172.31.59.103", 6379, 5000);
List<JedisShardInfo> list = new ArrayList<JedisShardInfo>();
list.add(si);
list.add(new JedisShardInfo("172.31.59.104", 6379, 5000));
list.add(new JedisShardInfo("172.31.59.105", 6379, 5000));
jedis = new ShardedJedis(list);
}
public void push() {
ShardedJedisPipeline pipeline = jedis.pipelined();
Scanner s;
try {
s = new Scanner(new File("input/ratings.csv"));
StringBuilder key = new StringBuilder();
String s1 = s.nextLine(); // Skip first line
while (s.hasNextLine()) {
s1 = s.nextLine();
String[] spl = s1.split(",");
// key="u:"+spl[0]+":m";
key.append("u:").append(spl[0]).append(":m");
pipeline.sadd(key.toString(), spl[1]);
key.setLength(0);
}
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("bye" + e.getMessage());
}
pipeline.sync();
}
public static void main(String[] args) {
MovieLens21MPipeline obj = new MovieLens21MPipeline();
long startTime = System.currentTimeMillis();
obj.push();
long endTime = System.currentTimeMillis();
double d = 0.0;
d = (double) (endTime - startTime);
System.out.println("Throughput: " + d);
}
}
Any help appreciated.

MOVED indicates that you're using Redis Cluster. ShardedJedis is not for Redis Cluster, so you should use JedisCluster instead.
Please note that JedisCluster doesn't have pipeline mode, so you may want to send your operation one by one.
Hope this helps.

Just like Lim said, you are using Redis in cluster mode. Use JedisCluster can solve this problem. In addition, as a supplement, why JedisCluster works?
We can known that from JedisCluster source code.
private T runWithRetries(byte[] key, int attempts, boolean tryRandomNode, boolean asking) {
if (attempts <= 0) {
throw new JedisClusterMaxRedirectionsException("Too many Cluster redirections?");
}
Jedis connection = null;
try {
// omit ... get connection
return execute(connection);
} catch (JedisNoReachableClusterNodeException jnrcne) {
throw jnrcne;
} catch (JedisConnectionException jce) {
// release current connection before recursion
// omit
return runWithRetries(key, attempts - 1, tryRandomNode, asking);
} catch (JedisRedirectionException jre) {
// if MOVED redirection occurred,
if (jre instanceof JedisMovedDataException) {
// here is the key point
// it rebuilds cluster's slot cache
// recommended by Redis cluster specification
// Jedis or ShardedJedis won't run this code
this.connectionHandler.renewSlotCache(connection);
}
// omit ...
return runWithRetries(key, attempts - 1, false, asking);
} finally {
releaseConnection(connection);
}
}

Related

pcap4j+winpcap should I run rpcapd.exe manually?

Hi I have downloaded pcap4j and winpcap and all jar (jna, pcap4j-core-1.8.2, slf4j-api-1.7.25, slf4j-simple-1.7.25) dependency manually. Added to the project and all compile well.
BUT:
when I began to sniff packet.getHeader() and packet.getPayload() returns null!
if I run manually rpcapd.exe then it works...
why?
package sniffer;
import java.io.IOException;
import org.pcap4j.core.BpfProgram.BpfCompileMode;
import org.pcap4j.core.NotOpenException;
import org.pcap4j.core.PacketListener;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.core.PcapNetworkInterface.PromiscuousMode;
import org.pcap4j.packet.Packet;
import org.pcap4j.util.NifSelector;
public class App {
static PcapNetworkInterface getNetworkDevice() {
PcapNetworkInterface device = null;
try {
device = new NifSelector().selectNetworkInterface();
} catch (IOException e) {
e.printStackTrace();
}
return device;
}
public static void main(String[] args) throws PcapNativeException, NotOpenException {
// The code we had before
PcapNetworkInterface device = getNetworkDevice();
System.out.println("You chose: " + device);
// New code below here
if (device == null) {
System.out.println("No device chosen.");
System.exit(1);
}
// Open the device and get a handle
int snapshotLength = 65536; // in bytes
int readTimeout = 50; // in milliseconds
final PcapHandle handle;
handle = device.openLive(snapshotLength, PromiscuousMode.PROMISCUOUS, readTimeout);
String filter = "tcp port 80";
handle.setFilter(filter, BpfCompileMode.OPTIMIZE);
// Create a listener that defines what to do with the received packets
PacketListener listener = new PacketListener() {
#Override
public void gotPacket(Packet packet) {
// Override the default gotPacket() function and process packet
System.out.println(handle.getTimestamp());
System.out.println(packet);
System.out.println(packet.getHeader());///////////////<<<<<<<<<<<------------
}
};
// Tell the handle to loop using the listener we created
try {
int maxPackets = 50;
handle.loop(maxPackets, listener);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Cleanup when complete
handle.close();
}
}
You need to add a packet factory (e.g. pcap4j-packetfactory-static.jar) to your classpath, or Pcap4J creates UnknownPacket instances, getPayload() and getHeader() of which return null, for all packets.

How to solve a FolderClosedIOException?

So I am new to Apache Camel. I know that most of this code is probably not the most efficient way to do this, but I have made a code that uses Apache Camel to access my gmail, grab the new messages and if they have attachments save the attachments in a specified directory. My route saves the body data as a file in that directory. Everytime the DataHandler tries to use the getContent() method, whether its saving a file or trying to print the body to System.out, I get either a FolderClosedIOException or a FolderClosed Exception. I have not clue how to fix it. The catch reopens the folder but it just closes again after getting another message.
import org.apache.camel.*;
import java.io.*;
import java.util.*;
import javax.activation.DataHandler;
import javax.mail.Folder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import com.sun.mail.util.FolderClosedIOException;
public class Imap {
public static void main(String[] args) throws Exception {
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {
public void configure() {
from("imaps://imap.gmail.com?username=********#gmail.com&password=******"
+ "&debugMode=false&closeFolder=false&mapMailMessage=false"
+ "&connectionTimeout=0").to("file:\\EMAIL");
}
});
Map<String,String> props = new HashMap<String,String>();
props.put("mail.imap.socketFactory.class","javax.net.ssl.SSLSocketFactory");
props.put("mail.imap.auth", "true");
props.put("mail.imap.host","imap.gmail.com");
props.put("mail.store.protocol", "imaps");
context.setProperties(props);
Folder inbox = null;
ConsumerTemplate template = context.createConsumerTemplate();
context.start();
while(true) {
try {
Exchange e = template.receive("imaps://imap.gmail.com?username=*********#gmail.com&password=***********", 60000);
if(e == null) break;
Message m = e.getIn();
Map<String, Object> s = m.getHeaders();
Iterator it = s.entrySet().iterator();
while(it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println(pairs.getKey()+" === "+pairs.getValue()+"\n\n");
it.remove();
}
if(m.hasAttachments()) {
Map<String,DataHandler> att = m.getAttachments();
for(String s1 : att.keySet()) {
DataHandler dh = att.get(s1);
String filename = dh.getName();
ByteArrayOutputStream o = new ByteArrayOutputStream();
dh.writeTo(o);
byte[] by = o.toByteArray();
FileOutputStream out = new FileOutputStream("C:/EMAIL/"+filename);
out.write(by);
out.flush();
out.close();
}
}
} catch(FolderClosedIOException ex) {
inbox = ex.getFolder();
inbox.open(Folder.READ_ONLY);
}
}
context.stop();
}
}
Please somebody tell me whats wrong!!
The error occurs here:
dh.writeTo(o);
We were was solving a similar problem in akka-camel
The solution i believe was to use manual acknowledgement and send an acknowledgement after we were done with the message.

JGroups not forming a cluster with UDP

I am trying to create a leader election protocol using JGroups so that N instances of my program can elect a master and all clients get the ip of this master.
More or less the current implementation relies on each instance trying to acquire a lock on lock-channel and when it successfully acquires this channel it becomes master and all others switch to clients.
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;
import org.jgroups.*;
import org.jgroups.blocks.locking.LockService;
public class AutoDiscovery
{
static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(AutoDiscovery.class); //used for logging purposes (see log4j library)
/* this variable indicates whether I have become the master or I'm just a client*/
public volatile AtomicBoolean becomeMaster = new AtomicBoolean(false);
/* The address of the server if we are a client or of ourself if we are
* server */
public String serverAddress;
/* A channel on which to acquire a lock, so that only one can become server */
private JChannel lockChannel;
/* A shared channel ffor communication between client and master*/
private JChannel communicationChannel;
private LockService lockService;
/* A thread which tries to acquire a lock */
private Thread acquiringThread;
/* A thread which listens for the server ip which may change */
private Thread listeningThread;
/* A thread which lists the status and initializes the acquiring thread*/
private Thread statusThread;
private String name;
/* If we pass from being a client to being a server we must stop the listening
* thread however we cannot call listeningThread.stop() but instead we change
* the stopListening boolean to true */
private boolean stopListening = false;
/* This lock communicates I have finally become either master or client so
* the serverAddress and becomeMaster variables are correctly set */
public final Object finishedLock = new Object();
public static void main(String[] args) throws Exception
{
Thread.currentThread().setName("MyMainThread");
Random rand = new Random();
AutoDiscovery master = new AutoDiscovery("Node" + rand.nextInt(10));
master.lockChannel = new JChannel(AutoDiscovery.class.getResource("/resource/udp.xml"));
master.lockChannel.connect("lock-channel");
master.communicationChannel = new JChannel(AutoDiscovery.class.getResource("/resource/udp.xml"));
master.communicationChannel.connect("communication-channel");
master.lockService = new LockService(master.lockChannel);
master.startStatusPrinterThread();
}
public AutoDiscovery(String name)
{
this.name = name;
}
public AutoDiscovery()
{
try
{
Thread.currentThread().setName("MyMainThread");
Random rand = new Random();
this.name = ("Node" + rand.nextInt(10));
lockChannel = new JChannel(AutoDiscovery.class.getResource("/resource/udp.xml"));
lockChannel.connect("lock-channel");
communicationChannel = new JChannel(AutoDiscovery.class.getResource("/resource/udp.xml"));
communicationChannel.connect("communication-channel");
lockService = new LockService(lockChannel);
startStatusPrinterThread();
}
catch (Exception ex)
{
Logger.getLogger(AutoDiscovery.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void startAcquiringThread()
{
acquiringThread = new Thread()
{
#Override
public void run()
{
while (true)
{
//if you have become Master send your ip every now and then
if (becomeMaster.get())
{
try
{
communicationChannel.send(new Message(null, null, "serverip " + serverAddress));
}
catch (Exception ex)
{
Logger.getLogger(AutoDiscovery.class.getName()).log(Level.SEVERE, null, ex);
}
}
else
{
try
{
Thread.currentThread().setName(name + "AcquiringThread");
Lock lock = lockService.getLock("serverLock");
if (lock.tryLock(4, TimeUnit.SECONDS))
{
becomeMaster.set(true);
stopListening = true;
/* Now that I'm server I must find out my own ip address on which to listen */
Enumeration<NetworkInterface> networkInterfaces;
try
{
networkInterfaces = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netint : Collections.list(networkInterfaces))
{
Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
for (InetAddress inetAddress : Collections.list(inetAddresses))
{
if (isIPAddress(inetAddress.getHostAddress())
&& !inetAddress.getHostAddress().equals("127.0.0.1"))
{
serverAddress = inetAddress.getHostAddress();
}
}
}
/* I notify to the rest of the program I have correctly initialized
* becomeMaster and serverAddress */
synchronized (finishedLock)
{
finishedLock.notify();
}
}
catch (Exception e)
{
Logger.getLogger(AutoDiscovery.class.getName()).log(Level.SEVERE, null, e);
System.exit(0);
}
log.info(Thread.currentThread().getName() + ": I acquired lock! will become master! my ip is " + serverAddress);
}
else
{
becomeMaster.set(false);
stopListening = false;
if (listeningThread == null || !listeningThread.isAlive())
{
if (!stopListening) //??? this codnition might be useless
{
startListeningThread();
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
try
{
sleep(5000L);
}
catch (InterruptedException ex)
{
Logger.getLogger(AutoDiscovery.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
acquiringThread.setDaemon(true);
acquiringThread.start();
}
public void startListeningThread()
{
listeningThread = new Thread()
{
#Override
public void run()
{
try
{
while (true)
{
Thread.currentThread().setName(name + "ListeningThread");
communicationChannel.setReceiver(new ReceiverAdapter()
{
#Override
public void receive(Message msg)
{
if (msg.getObject() != null)
{
String leaderServerAddress = (msg.getObject().toString().substring(9));
if (isIPAddress(leaderServerAddress))
{
serverAddress = leaderServerAddress;
log.info(name + " Master server has ip" + serverAddress);
/* I notify to the rest of the program I have correctly initialized
* becomeMaster and serverAddress */
synchronized (finishedLock)
{
finishedLock.notify();
}
}
else
{
log.info(name + ": discarded message " + msg.getObject().toString());
}
}
}
});
sleep(10000L);
if (stopListening)
{
return;
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
listeningThread.setDaemon(true);
listeningThread.start();
}
private void startStatusPrinterThread()
{
statusThread = new Thread()
{
#Override
public void run()
{
Thread.currentThread().setName(name + "StatusPrinterThread");
startAcquiringThread();
while (true)
{
try
{
if (becomeMaster.get())
{
log.info(name + " startStatusPrinterThread(): I am happily a Master!");
}
else
{
if (!acquiringThread.isAlive())
{
startAcquiringThread();
}
}
sleep(5000L);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
};
statusThread.setDaemon(true);
statusThread.start();
}
private static boolean isIPAddress(String str)
{
Pattern ipPattern = Pattern.compile("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
return ipPattern.matcher(str).matches();
}
}
now my current udp.xml is
<config xmlns="urn:org:jgroups"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/JGroups-3.0.xsd">
<UDP
mcast_port="${jgroups.udp.mcast_port:45588}"
tos="8"
ucast_recv_buf_size="20M"
ucast_send_buf_size="640K"
mcast_recv_buf_size="25M"
mcast_send_buf_size="640K"
loopback="true"
level="WARN"
log_discard_msgs="false"
max_bundle_size="64K"
max_bundle_timeout="30"
ip_ttl="${jgroups.udp.ip_ttl:8}"
enable_diagnostics="true"
thread_naming_pattern="cl"
timer_type="new"
timer.min_threads="4"
timer.max_threads="10"
timer.keep_alive_time="3000"
timer.queue_max_size="500"
thread_pool.enabled="true"
thread_pool.min_threads="2"
thread_pool.max_threads="8"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="true"
thread_pool.queue_max_size="10000"
thread_pool.rejection_policy="discard"
oob_thread_pool.enabled="true"
oob_thread_pool.min_threads="1"
oob_thread_pool.max_threads="8"
oob_thread_pool.keep_alive_time="5000"
oob_thread_pool.queue_enabled="false"
oob_thread_pool.queue_max_size="100"
oob_thread_pool.rejection_policy="Run"/>
<PING timeout="2000"
num_initial_members="3"/>
<MERGE2 max_interval="30000"
min_interval="10000"/>
<FD_SOCK/>
<FD_ALL/>
<VERIFY_SUSPECT timeout="1500" />
<BARRIER />
<pbcast.NAKACK exponential_backoff="300"
xmit_stagger_timeout="200"
use_mcast_xmit="false"
discard_delivered_msgs="true"/>
<UNICAST />
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
max_bytes="4M"/>
<pbcast.GMS print_local_addr="true" join_timeout="3000"
view_bundling="true"/>
<UFC max_credits="2M"
min_threshold="0.4"/>
<MFC max_credits="2M"
min_threshold="0.4"/>
<FRAG2 frag_size="60K" />
<pbcast.STATE_TRANSFER />
<CENTRAL_LOCK />
<!-- pbcast.FLUSH /-->
</config>
Now the above works when I run N instances of the program on the same machine (with N-1 members becoming client and 1 becoming master).
When run on two different machines both connected to the same LAN, apparently after calling JChannel.connect() with the same clustername in each member, each member creates its channel and no common cluster is created. The result is that when sending messages to the clients the other master sees a different physical address for the same cluster name and all messages are dropped.
So I get warnings like:
7683 [Incoming-1,communication-channel,pc-home-41714] WARN org.jgroups.protocols.pbcast.NAKACK - [JGRP00011] pc-home-41714: dropped message 293 from non-member cf8b4ea6-8cc8-cb21-538f-b03f3fa7413d (view=[pc-home-41714|0] [pc-home-41714])
1207996 [TransferQueueBundler,communication-channel,pc-home-5280] WARN org.jgroups.protocols.UDP - pc-home-5280: no physical address for cf8b4ea6-8cc8-cb21-538f-b03f3fa7413d, dropping message
1209526 [TransferQueueBundler,lock-channel,pc-home-59082] WARN org.jgroups.protocols.UDP - pc-home-59082: no physical address for efbe6408-0e21-d119-e2b8-f1d5762d9b45, dropping message
If I change udp.xml loopback="true" to loopback="false" what happens is that they both connect to the same cluster but then they give an error like:
55539 [Node0StatusPrinterThread] INFO plarz.net.planningig.autodiscovery.AutoDiscovery - Node0 startStatusPrinterThread(): I am happily a Master!
59077 [TransferQueueBundler,lock-channel,pc-test-6919] ERROR org.jgroups.protocols.UDP - pc-test-6919: exception sending bundled msgs: java.lang.Exception: dest=/fe80:0:0:0:226:18ff:fece:6ccc%2:43109 (130 bytes):, cause: java.io.IOException: Network is unreachable
59505 [TransferQueueBundler,communication-channel,pc-test-35303] ERROR org.jgroups.protocols.UDP - pc-test-35303: exception sending bundled msgs: java.lang.Exception: dest=/fe80:0:0:0:226:18ff:fece:6ccc%2:55053 (139 bytes):, cause: java.io.IOException: Network is unreachable
Error:
[Server:ha-server-3] 13:59:13,122 WARNING [org.jgroups.protocols.UDP]
(OOB-15,null) null: no physical address for
766de5c9-8ac2-6d30-89ef-78d39aa5f7eb, dropping message
In My case, it was due to having multiple jboss clusters at a same
network and each of the clusters were having same name. For example
ha-server-1 and ha-server-2 existed at two different clusters in
different machines.
Cluster-1(10.10.10.10): |
+- ha-server-1
+- ha-server-2
Cluster-2(10.10.10.20): |
+- ha-server-1
+- ha-server-2
I have resolved this problem by changing the ha-server names. Note:
Both were independent cluster. I assume it happened due to the
multicast issue of JGroups. Any further explanation from an expert
like you will be nice.
refer to http://icfun.blogspot.com/2013/10/no-physical-address-for-766de5c9-8ac2.html

Hadoop RPC server doesn't stop

I was trying to create a simple parent child process with IPC between them using Hadoop IPC. It turns out that program executes and prints the results but it doesn't exit. Here is the code for it.
interface Protocol extends VersionedProtocol{
public static final long versionID = 1L;
IntWritable getInput();
}
public final class JavaProcess implements Protocol{
Server server;
public JavaProcess() {
String rpcAddr = "localhost";
int rpcPort = 8989;
Configuration conf = new Configuration();
try {
server = RPC.getServer(this, rpcAddr, rpcPort, conf);
server.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public int exec(Class klass) throws IOException,InterruptedException {
String javaHome = System.getProperty("java.home");
String javaBin = javaHome +
File.separator + "bin" +
File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = klass.getCanonicalName();
ProcessBuilder builder = new ProcessBuilder(
javaBin, "-cp", classpath, className);
Process process = builder.start();
int exit_code = process.waitFor();
server.stop();
System.out.println("completed process");
return exit_code;
}
public static void main(String...args) throws IOException, InterruptedException{
int status = new JavaProcess().exec(JavaProcessChild.class);
System.out.println(status);
}
#Override
public IntWritable getInput() {
return new IntWritable(10);
}
#Override
public long getProtocolVersion(String paramString, long paramLong)
throws IOException {
return Protocol.versionID;
}
}
Here is the child process class. However I have realized that it is due to RPC.getServer() on the server side that it the culprit. Is it some known hadoop bug, or I am missing something?
public class JavaProcessChild{
public static void main(String...args){
Protocol umbilical = null;
try {
Configuration defaultConf = new Configuration();
InetSocketAddress addr = new InetSocketAddress("localhost", 8989);
umbilical = (Protocol) RPC.waitForProxy(Protocol.class, Protocol.versionID,
addr, defaultConf);
IntWritable input = umbilical.getInput();
JavaProcessChild my = new JavaProcessChild();
if(input!=null && input.equals(new IntWritable(10))){
Thread.sleep(10000);
}
else{
Thread.sleep(1000);
}
} catch (Throwable e) {
e.printStackTrace();
} finally{
if(umbilical != null){
RPC.stopProxy(umbilical);
}
}
}
}
We sorted that out via mail. But I just want to give my two cents here for the public:
So the thread that is not dying there (thus not letting the main thread finish) is the org.apache.hadoop.ipc.Server$Reader.
The reason is, that the implementation of readSelector.select(); is not interruptable. If you look closely in a debugger or threaddump, it is waiting on that call forever, even if the main thread is already cleaned up.
Two possible fixes:
make the reader thread a deamon (not so cool, because the selector
won't be cleaned up properly, but the process will end)
explicitly close the "readSelector" from outside when interrupting the threadpool
However, this is a bug in Hadoop and I have no time to look through the JIRAs. Maybe this is already fixed, in YARN the old IPC is replaced by protobuf and thrift anyways.
BTW also this is platform dependend on the implementation of the selectors, I observed these zombies on debian/windows systems, but not on redhat/solaris.
If anyone is interested in a patch for Hadoop 1.0, email me. I will sort out the JIRA bug in the near future and edit this here with more information. (Maybe this is fixed in the meanwhile anyways).

Starting bbcomm in Java v3 Bloomberg API

When I use the Java Bloomber V3 API it usually works. However, sometimes, especially after a reboot, bbcomm.exe is not running in the background. I can start it manually by running blp.exe, but I wondered if there was a way of doing this via the API?
After talking to the help desk, it turns out that on 64 bit Windows, running under a 64bit JVM bbcomm is not automatically started. This does not happen under 32bit Java - under 32 bit bbcomm automatically runs.
So my solutions are either to wait for the problem to be fixed by Bloomberg (now I understand it) or to check this specific case.
To check the specific case:
if running under a 64 bit windows (System property os.arch)
and if running under a 64bit JVM (System property java.vm.name)
then try and start a session
If this fails, assume bbcomm.exe is not running. Try to run bbcomm.exe using Runtime.exec()
I haven't tested the above yet. It may have exactly the same issues as Bloomberg have with 64bit VMs.
After spending some time with Help Help, it seems that bbcomm gets started either when you use the Excel API or run the API demo. But it does not get started automatically when called from the Java API. Possible ways to start it are:
adding an entry in the registry to automatically start bbcomm on startup: in HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run add a String value called bbcomm with value C:\blp\API\bbcomm.exe - but that opens a command window which remains visible, so not really an option (and if you close that window it terminates the bbcomm process)
create a batch file START /MIN C:\blp\API\bbcomm.exe and replace the entry in the registry with that (not tested) to call bbcomm silently
manually launch bbcomm from your java code as already suggested. As a reference, I post below the code that I'm using.
private final static Logger logger = LoggerFactory.getLogger(BloombergUtils.class);
private final static String BBCOMM_PROCESS = "bbcomm.exe";
private final static String BBCOMM_FOLDER = "C:/blp/API";
/**
*
* #return true if the bbcomm process is running
*/
public static boolean isBloombergProcessRunning() {
return ShellUtils.isProcessRunning(BBCOMM_PROCESS);
}
/**
* Starts the bbcomm process, which is required to connect to the Bloomberg data feed
* #return true if bbcomm was started successfully, false otherwise
*/
public static boolean startBloombergProcessIfNecessary() {
if (isBloombergProcessRunning()) {
logger.info(BBCOMM_PROCESS + " is started");
return true;
}
Callable<Boolean> startBloombergProcess = getStartingCallable();
return getResultWithTimeout(startBloombergProcess, 1, TimeUnit.SECONDS);
}
private static Callable<Boolean> getStartingCallable() {
return new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
logger.info("Starting " + BBCOMM_PROCESS + " manually");
ProcessBuilder pb = new ProcessBuilder(BBCOMM_PROCESS);
pb.directory(new File(BBCOMM_FOLDER));
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
if (line.toLowerCase().contains("started")) {
logger.info(BBCOMM_PROCESS + " is started");
return true;
}
}
return false;
}
};
}
private static boolean getResultWithTimeout(Callable<Boolean> startBloombergProcess, int timeout, TimeUnit timeUnit) {
ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "Bloomberg - bbcomm starter thread");
t.setDaemon(true);
return t;
}
});
Future<Boolean> future = executor.submit(startBloombergProcess);
try {
return future.get(timeout, timeUnit);
} catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
return false;
} catch (ExecutionException | TimeoutException e) {
logger.error("Could not start bbcomm", e);
return false;
} finally {
executor.shutdownNow();
try {
if (!executor.awaitTermination(100, TimeUnit.MILLISECONDS)) {
logger.warn("bbcomm starter thread still running");
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
ShellUtils.java
public class ShellUtils {
private final static Logger logger = LoggerFactory.getLogger(ShellUtils.class);
/**
* #return a list of processes currently running
* #throws RuntimeException if the request sent to the OS to get the list of running processes fails
*/
public static List<String> getRunningProcesses() {
List<String> processes = new ArrayList<>();
try {
Process p = Runtime.getRuntime().exec(System.getenv("windir") + "\\system32\\" + "tasklist.exe");
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
int i = 0;
while ((line = input.readLine()) != null) {
if (!line.isEmpty()) {
String process = line.split(" ")[0];
if (process.contains("exe")) {
processes.add(process);
}
}
}
} catch (IOException e) {
throw new RuntimeException("Could not retrieve the list of running processes from the OS");
}
return processes;
}
/**
*
* #param processName the name of the process, for example "explorer.exe"
* #return true if the process is currently running
* #throws RuntimeException if the request sent to the OS to get the list of running processes fails
*/
public static boolean isProcessRunning(String processName) {
List<String> processes = getRunningProcesses();
return processes.contains(processName);
}
}
In case someone needs help checking/starting bbcomm.exe process from the code hiding console window, this snippet is written in C#; I hope you can easily translate it to Java.
void Main()
{
var processes = Process.GetProcessesByName("bbcomm");
if (processes.Any())
{
Console.WriteLine(processes.First().ProcessName + " already running");
return;
}
var exePath = #"C:\blp\DAPI\bbcomm.exe";
var processStart = new ProcessStartInfo(exePath);
processStart.UseShellExecute = false;
processStart.CreateNoWindow = true;
processStart.RedirectStandardError = true;
processStart.RedirectStandardOutput = true;
processStart.RedirectStandardInput = true;
var process = Process.Start(processStart);
Console.WriteLine(process.ProcessName + " started");
}
bbcomm.exe is automatically started by the V3 API.