Java example for com.tailf.notif.Notif causes all subsequent subscriptions to fail

I am using the example code shown at the bottom of the documentation for the Java class com.tailf.notif.Notif.

As with the example, I am connecting a new socket to the ConfD port on localhost and creating a thread to read from the notifications stream, for NOTIF_AUDIT and NOTIF_USER_SESSION.

After starting this thread, none of my other CDB subscribers within the same running process get called when there is a change in the CDB.

Does reading from the notifications socket cause other events to be consumed or hidden somehow?

I’ve found that the simple act of creating a Notif object on a socket can cause all subsequent subscriptions running in the same process to fail. It doesn’t even require the starting of a thread to read the notifications from that Notif object.

All it takes to cause all subsequent subscribers to stop receiving CDB events is to execute the following code:

  Socket notif_sock = new Socket("127.0.0.1", Conf.PORT);
  // init and connect the notification socket
  final Notif notif =
      new Notif(notif_sock,
                EnumSet.of(NotificationType.NOTIF_AUDIT,
                           NotificationType.NOTIF_USER_SESSION));

Why is this?

Hello,

The snippet of code you attached shouldn’t cause other subscribers from being notified.

I guess you got this code from:
// create new notifications socket
Socket notif_sock = new Socket(“127.0.0.1”, Conf.PORT);
// init and connect the notification socket
final Notif notif =
new Notif(notif_sock,
EnumSet.of(NotificationType.NOTIF_AUDIT,
NotificationType.NOTIF_USER_SESSION));

   // read input from the notification socket
  Thread notifThread = new Thread(new Runnable() {
      public void run() {
          try {
              while (true) notif.read();
          } catch (Exception e) {
                e.printStackTrace();
                return;
          }
      }
  });
  notifThread.start();

We have a C example for notifications that shows how to process the notification and tell ConfD the processing is done and that it can go ahead with other notifications. This of course is in a single threaded manner.

Once you run this code what does “confd --status” give you under “registered cdb clients”. If it’s empty then your subscriptions failed. If it’s not, then you should check the trace after you turn on all the logs…

You can also raise a ticket with support for more debugging in case this ends up in some hidden bug somewhere…

/Nabil

Thank you Nabil. I am just now returning to this problem.

My Java code is nearly identical to what is shown in the documentation, which is what you have excerpted above. The code is taken from the example given in the Javadoc for Notif. The only differences are:
(1) I assign the return value of notif.read() to a variable and then output it to a debug log
(2) I am using additional notification types NOTIF_CONFIRMED_COMMIT, NOTIF_COMMIT_SIMPLE, NOTIF_COMMIT_FAILED.

I understand that adding a notification type NOTIF_COMMIT_DIFF will cause the transaction to hang, as described in the Javadoc. However, I am not using that notification type.

To answer your helpful questions in debugging this problem:
The output of “confd --status” is the same, regardless of whether or not the aforementioned code is included in my build. In either case, it shows the same set of registered cdb clients. However, and this is the odd part, neither the new subscriber I have written, nor the subscriber which is being blocked, is listed in the output. Also, in both cases, there is a line of text above the registered cdb clients which says “no pending subscription notifications”.

So the question remains, why does creating, listening on, and reading from a notification socket by one CDB subscriber cause other CDB subscribers to not receive their subscription callbacks, using code that is nearly identical to what is shown in the Javadoc.

Thank you.

Hi,

If you connect your non-blocking CDB subscribers before your blocking notification stream subscribers you should be fine.

Example:

$ diff -u examples.confd/cdb_subscription/iter_java/Cdbl.java Cdbl.java
--- examples.confd/cdb_subscription/iter_java/Cdbl.java	2016-01-22 19:04:25.000000000 +0100
+++ Cdbl.java	2016-05-16 17:46:55.000000000 +0200
@@ -36,9 +36,11 @@
 import com.tailf.conf.ConfBuf;
 import com.tailf.conf.ConfUInt64;
 
 import org.apache.log4j.Logger;
 
+import com.tailf.notif.Notif;
+import com.tailf.notif.NotificationType;
+
 public class Cdbl {
 
     private static Logger log = Logger.getLogger( Cdbl.class );
@@ -68,7 +70,30 @@
         boolean inuse;
     }
 
+    static class NotifClass {
+	NotifClass() throws Exception {
+	    // create new notifications socket
+	    Socket notif_sock = new Socket("127.0.0.1", confdPort);
+	    // init and connect the notification socket
+	    final Notif notif =
+		new Notif(notif_sock,
+			  EnumSet.of(NotificationType.NOTIF_COMMIT_SIMPLE,
+				     NotificationType.NOTIF_USER_SESSION));  
+	    // read input from the notification socket
+	    Thread notifThread = new Thread(new Runnable() {
+		    public void run() {
+			try {
+			    while (true) {notif.read();}
+			} catch (Exception e) {
+			    e.printStackTrace();
+			    return;
+			}
+		    }
+		});
+	    notifThread.start();
+	}
+    }
+    
     public static void
         main ( String arg[] )
 
@@ -98,12 +123,13 @@
 
         }
 
         Cdb cdb = null;
         Cdb cdb2 = null;
         CdbSubscription cdbSubscriber = null;
         try {
             cdb = new Cdb ("Subscription-Sock",  sockChannel );
+            new NotifClass();
             cdbSubscriber = cdb.newSubscription();
 
             headPoint  = cdbSubscriber

Thank you Conny. I was able to get it working by moving the Notif reader into its own process. But from what you are saying, this could still cause subscribers to fail if the Notif reader process is started before other subscribers. So it sounds like I need to ensure that this process is the last subscriber to start.

I am still not understanding where the blocking is occurring. It can’t be on the client, because the notif read() call is running in its own thread. So it shouln’t matter to anyone else if my read() blocks. Does it cause something to block on the back-end?

It is the socket creation that is causing the issue. Create the non blocking CDB subscriber socket first and then the notification socket. Or as you did, create the notification socket in its own thread.

Thank you. That matches what I’ve experienced – creating the socket, even without reading from it, causes the bug.

I’ll suggest that the JavaDoc be updated to explain that the socket must be created on its own thread in order to avoid this problem. Because it’s not apparent from looking at the code that the socket creation is what causes the problem.

Thanks again for all your help.