Java Ninja Chronicles By Norris Shelton

Things I learned in the pursuit of code

I was working on a piece of code and noticed that it was using an older method to write a file. A fileWriter was used to to write the file. That was wrapped with a bufferedWriter. Here is what the original code looked like.

        BufferedWriter outputWriter = null;
        outputWriter = new BufferedWriter(new FileWriter(filename));
        for (int i = 0; i < x.length; i++) {
            if (i == x.length -1) {
                outputWriter.write(Integer.toString(x[i]));
            } else {
                outputWriter.write(Integer.toString(x[i]) + ",");
            }

            outputWriter.newLine();
        }
        outputWriter.flush();
        outputWriter.close();

I changed it to a NIO Files implementation.

Files.write(Paths.get("/igs/rng/test/" + provider + ".csv"), stringBuilder.toString().getBytes());

It doesn’t get any easier than that.

January 23rd, 2015

Posted In: Java

Tags: , , , ,

Leave a Comment

I had some Java code that was being code reviewed and it was discovered that a buffered reader did not close the reader. That was the perfect time to use the try-with-resources.

The original code looked like:

/**
     * Retrieves the diagnostic information from the Comscire device.
     * @return String containing the "Status" and "DeviceID" information
     * @throws IOException
     */
    public String getDiagnostics() throws IOException {
        StringBuilder output = new StringBuilder();
        try {
            Process process =
                new ProcessBuilder("/usr/local/bin/diagnostics").start();

            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String data = null;
            boolean done = false;
            while ((data = br.readLine()) != null && !done) {
                if (StringUtils.startsWith(data, "Status") ||
                    StringUtils.startsWith(data, "DeviceID")) {
                    output.append("\t").append(data).append("\n");
                } else if (StringUtils.startsWith(data, "Get 128 Raw Bytes")) {
                    done = true;
                }
            }
        } catch (IOException e) {
            setErrors(true);
            logger.error("Unable to get diagnostics from Comscire process", e);
            throw e;
        }

        return output.toString();
    }

The new code takes advantage of the try-with-resources.

    /**
     * Retrieves the diagnostic information from the Comscire device.
     * @return String containing the "Status" and "DeviceID" information
     * @throws IOException
     */
    public String getDiagnostics() throws IOException {
        StringBuilder output = new StringBuilder();
        try {
            Process process =
                new ProcessBuilder("/usr/local/bin/diagnostics").start();

            try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String data = null;
                boolean done = false;
                while ((data = br.readLine()) != null && !done) {
                    if (StringUtils.startsWith(data, "Status") ||
                        StringUtils.startsWith(data, "DeviceID")) {
                        output.append("\t").append(data).append("\n");
                    } else if (StringUtils.startsWith(data, "Get 128 Raw Bytes")) {
                        done = true;
                    }
                }
            }
        } catch (IOException e) {
            setErrors(true);
            logger.error("Unable to get diagnostics from Comscire process", e);
            throw e;
        }

        return output.toString();
    }

Another case that I had was where an exception was being thrown from within the try-with-resources. Here is what a try-with-resources looks like with an exception.

    /**
     * Fills the integer queue with integers.  Opens the process that calls the USB device, reads the data, splits the
     * CSV into integers and adds them to the queue.  Sets the RNG device to available as it writes integers to the
     * queue.
     * @throws InterruptedException throws if the put operation is interrupted by a timeout
     */
    public void getRandomIntegerData() throws IOException, InterruptedException {
        int queueSize = integerQueue.size();
        try {
            logger.info("Retrieving {} integers from Comscire by calling randint32...",
                        DESIRED_QUEUE_LENGTH - queueSize);
            Process process =
                    new ProcessBuilder("/usr/local/bin/randint32",
                                       Integer.toString(DESIRED_QUEUE_LENGTH - queueSize)).start();

            try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String data = br.readLine();
                for (String stringInt : data.split(",")) {
                    integerQueue.put(Integer.valueOf(stringInt));
                    // check it to ensure that it hasn't been emptied as fast as it could be filled
                    if (integerQueue.size() > 0) {
                        setAvailable(true);
                        setErrors(false);
                    }
                }
            } catch (InterruptedException e) {
                logger.error("Unable to add integers to the Comscire queue", e);
                throw e;
            }
        } catch (IOException e) {
            setErrors(true);
            logger.error("Unable to get integers from Comscire process", e);
            throw e;
        }
    }

January 22nd, 2015

Posted In: Java

Tags: , , ,

Leave a Comment

It had been a long time since I had a need to call a system process from inside Java. The last time I needed to do this, I used Runtime.exec(). Now there is a new sheriff in town… ProcessBuilder. ProcessBuilder was introduced in JDK 5 and makes it super simple to call native processes.

I had two separate cases that I needed to solve. One was a call to a C program with a parameter that returned one line of objects that I needed to parse. The other was a call to a C and it returned multiple lines to me. I only cared about some of the lines of output from the program.

Here is the first example. It calls a C program with one parameter and parses the single line of output. I can call the C program from the command line via:

/usr/local/bin/randint32  5

The output is similar to:

2048211571,-446295626,-1826753911,773673606,-163405466,

Here is the Java method that I used to call the C program and parse the data:

  • Line 11 – 12 – The ProcessBuilder is instantiated with the command as the first parameter and the parameter to the command as the second parameter.
  • Line 13 – This is where the process is returned from calling start() on the ProcessBuilder object.
  • Line 15 – The input stream is retrieved from the process object.

Beyond the Process/ProcessBuilder processing is normal Java code. The process returns me one line, which contains comma-separated integers. I split the string into a bunch of strings containing integer data. I convert them to integers and add them to the Queue. I also set a couple of flags that are related to the application, but are beyond the scope of this article.

    /**
     * Fills the integer queue with integers.  Opens the process that calls the USB device, reads the data, splits the
     * CSV into integers and adds them to the queue.  Sets the RNG device to available as it writes integers to the
     * queue.
     * @throws InterruptedException throws if the put operation is interrupted by a timeout
     */
    public void getRandomIntegerData() throws IOException, InterruptedException {
        int integersToGenerate = DESIRED_QUEUE_LENGTH - integerQueue.size();
        try {
            logger.info("Retrieving {} integers from Comscire by calling randint32...", integersToGenerate);
            ProcessBuilder processBuilder = new ProcessBuilder("/usr/local/bin/randint32",
                                                               Integer.toString(integersToGenerate));
            Process process = processBuilder.start();

            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String data = br.readLine();
            for (String stringInt : data.split(",")) {
                integerQueue.put(Integer.valueOf(stringInt));
                // check it to ensure that it hasn't been emptied as fast as it could be filled
                if (integerQueue.size() > 0) {
                    setAvailable(true);
                    setErrors(false);
                }
            }
        } catch (IOException e) {
            setErrors(true);
            logger.error("Unable to get integers from Comscire process", e);
            throw e;
        }
    }

The next C program that I had to call returned diagnostic information from a Comscire hardware random number generator. The command that I used to retrieve the data is:

/usr/local/bin/diagnostics

The data is returned as a series of lines containing the following data. I was only concerned with two of the lines from the output:

  • Status: QNG device reports success.
  • DeviceID QWR40026

 
Start Device...

Status: QNG device reports success.

DeviceID QWR40026


Get 128 Raw Bytes - Level 2, Stream 3 (hex)

76 6D 02 B6 BC 05 1D B1 7C 92 BC D7 69 2D 86 27 CC 5D EE 16 4F 17 97 EA B9 BA 32 AE E4 FC FA 57 4B 9C 74 48 0C 51 79 5B 47 82 3C 4B 66 EE 5A EA 83 C2 12 10 AF F2 8F 7B E2 D0 CD 84 40 96 94 A3 30 2D C3 AD 7F FD 06 9C 1F 2A 20 26 41 73 B9 EA 4B 82 DE AB 31 D8 FA 5D 20 1E EA 0F F2 D6 5A BB 4A 82 67 70 C4 C8 40 6E CA 7B 84 DA B4 3D 99 0A A6 BC 36 C3 94 D9 84 D9 F9 5B 00 95 01 4C 64 E2

EXIT...
  • Line 9 – The ProcessBuilder is instantiated with the command.
  • Line 10 – The process is assigned from calling processBuilder.start().
  • Line 12 – The input stream is retrieved from the process object.

I loop over the individual lines of data looking for the 2 lines of data that I need to retrieve. I add those to a StringBuilder. Just for efficiency’s sake, I look for a line that tells me that I am done. There is no data that I am concerned with after this line.

    /**
     * Retrieves the diagnostic information from the Comscire device.
     * @return String containing the "Status" and "DeviceID" information
     * @throws IOException
     */
    public String getDiagnostics() throws IOException {
        StringBuilder output = new StringBuilder();
        try {
            ProcessBuilder processBuilder = new ProcessBuilder("/usr/local/bin/diagnostics");
            Process process = processBuilder.start();

            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String data = null;
            boolean done = false;
            while ((data = br.readLine()) != null && !done) {
                if (StringUtils.startsWith(data, "Status") ||
                    StringUtils.startsWith(data, "DeviceID")) {
                    output.append("\t").append(data).append("\n");
                } else if (StringUtils.startsWith(data, "Get 128 Raw Bytes")) {
                    done = true;
                }
            }
        } catch (IOException e) {
            setErrors(true);
            logger.error("Unable to get diagnostics from Comscire process", e);
            throw e;
        }

        return output.toString();
    }

There you have it. Two examples showing how easy it is to use ProcessBuilder to execute native processes from a Java application.

January 9th, 2015

Posted In: Java

Tags: , , , , ,

Leave a Comment

It’s been almost 2 decades since I did any C programming. Rust doesn’t even begin to describe the difficulties. We had a small programmed that wrapped the Comscire provided C API that needed to be protected from multiple processes accessing the hardware at the same time. Enter the C Named Semaphore. I found several examples, but none of them was a complete example. That’s a shame. The incomplete examples made it that much harder to get working.

Semaphores in Linux was an invaluable resource.

  • Line 4 and 5 are the headers necessary. Semaphore and file control.
  • Line 8 – the name of the named semaphore
  • Line 9– declared the semaphore
  • Line 33 – The semaphore is opened. O_CREATE specifies that the semaphore is created if it doesn’t already exist. The name of the semaphore is specified here.
  • Line 39 – locks the semaphore. This prevents other processes from accessing the code while another process is accessing the protected section.
  • Line 45 – unlocks the semaphore
  • Line 47 – closes the named semaphore
  • Line 49 – deletes the named semaphore. Without this, only you will be able to run the program. The name of the semaphore is specified here.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <semaphore.h>
#include <fcntl.h>
#include <qwqng.hpp>

char semaphoreName[] = "rng_semaphore";
sem_t *namedSemaphore;

/**
 Performs the call to retrieve a random integer.
 returnCount - the number of random integers to return
 */
void doRandCall(int returnCount)
{
  // omitted for brevity
}


/**
 Returns a specified number of random integers from the Comscire hardware RNG.
 argc - count of arguments
 argv - process parameters
 [0] - number of random integers to generate
 */
int main(int argc, char *argv[])
{
    if (argc == 2)
    {
        int returnCount = atoi(argv[1]);
        
        if ((namedSemaphore = sem_open(semaphoreName, O_CREAT, 0644, 1)) == SEM_FAILED)
        {
            perror("named semaphore initialization error");
            exit(1);
        }
        
        sem_wait(namedSemaphore);
        
        /*******************************************************************************/
        doRandCall(returnCount);
        /*******************************************************************************/
        
        sem_post(namedSemaphore);
        
        sem_close(namedSemaphore);
        
        sem_unlink(semaphoreName);
        
        return EXIT_SUCCESS;
    }
}

January 7th, 2015

Posted In: Javaninja

Tags: , , ,

Leave a Comment

LinkedIn Auto Publish Powered By : XYZScripts.com