Java and Postgres95
You must store the value returned by makeCString in a variable. If you pass the return value directly to a function, the garbage collector may free it at any time. The same is not true of makeJavaString.) Lines 30-34 in Listing 2 show the use of makeCString and we use makeJavaString first at line 51. Lines 41-42 in Listing 2 show our call into the libpq library. It is called exactly as normal, and the resulting pointer is stored in the variable tmpConn. You may notice that we don't do any error-checking here: we do that in the Java code for our constructor, where it is easier to throw exceptions.
As I mentioned above, PGConnection needs to keep the PGconn pointer around, so that it can use it in later calls—all later calls, in fact. In order to do this, we will store the 32 bit pointer in a data member with Java type int after casting it to a C long to avoid warnings (see Table 1 for a list of type conversions).
To access this member, we must use Java's “handles”. Handles are used to access data in a Java object. When you want to access a data member, you simply use unhand(ptr)->member rather than ptr->member (where ptr is the handle). We do this on line 42 of PGConnectionNative.c (Listing 2) to save the pointer returned by setDB in a Java int (note: if you forget the unhand() macro, you will get a warning about incompatible pointer types).
This function has covered almost all you need to know to call C functions from Java (calling Java methods from C is possible, but the interface is clumsy at best at this point, and where possible, I'd avoid it). Most of the rest of the methods (host, options, port, etc.) simply convert the data and make the C call. We'll just take a look at one of these, PGConnection.db().
The only significant portion of the C function PGConnection_db() is its first line (Listing 2, line 46). It needs a PGconn to pass to PQdb(), so it must get it out of the PGConnection member, PGconnRep. It uses cw[unhand() to get the pointer as a long, then casts that to a (PGconn *). Since this line is so messy (and is starting to look like lisp!) I created a macro, thisPGconn, to clean up the code a little. It is used in the remainder of the file, and its definition is at the top of the file (don't put it in PGConnection.h, since that is machine-generated).
All of the native methods in the Java class PGResult follow the same basic structure, and there is no reason to go over them.
There are some places where Java and C just don't get along. The rest of this section will touch on the few I found, and how I avoided them.
The exec() method (see, I told you I'd get to it) needs to return a PGResult object. This is in keeping with libpq's structure, and the OO nature of Java. However, returning an object from a native method can get pretty hairy. The “official” way to do it is to call the function:
HObject *execute_java_constructor(ExecEnv *, char *classname, ClassClass *cb, char *signature, ...);
and return the HObject * it returns. Personally, I find this interface extremely clumsy, and have managed to avoid it. However, for completeness, the actual call in our case would be:
return execute_java_constructor(EE(), "classPGResult", 0, "(I)LclassPGResult;", (long)tmpResult);
I found it far easier to create a buffer between the call to exec() and the call to PQexec() that could call the constructor from Java. This is where the nativeExec() method comes from. exec() simply passes the string to nativeExec(), which returns an int (the PGresult pointer that PQexec() returned). Then it calls PGResult's constructor with that int.
The extra layer will also come in handy when we add the asynchronous notification system.
PQgetline() expects the user to continually call it while it fills in a static buffer. This is simply not needed in Java. A much nicer interface is to just have getline() return a String. However, building the String (appending each return value from PQgetline()) required calling Java methods from C—which, as we saw in Hoop #1, is very messy. By using a StringBuffer (a String that can grow) and doing the work in the Java code, it's much easier to understand, if a little slower.
The flip side of this is that the return value is now the String, so there must be another way to tell if an error has occurred or an EOF has been reached. One solution (I'm looking for a better one), and the one we use, is to set a data member flag. If the flag has been set to EOF, we simply return a Java null String. So once again, an extra layer saves us from a lot of truly gross code!
Fast/Flexible Linux OS Recovery
On Demand Now
In this live one-hour webinar, learn how to enhance your existing backup strategies for complete disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible full-system recovery solution for UNIX and Linux systems.
Join Linux Journal's Shawn Powers and David Huffman, President/CEO, Storix, Inc.
Free to Linux Journal readers.Register Now!
- Download "Linux Management with Red Hat Satellite: Measuring Business Impact and ROI"
- Profiles and RC Files
- Astronomy for KDE
- Maru OS Brings Debian to Your Phone
- Understanding Ceph and Its Place in the Market
- Git 2.9 Released
- OpenSwitch Finds a New Home
- Snappy Moves to New Platforms
- What's Our Next Fight?
- The Giant Zero, Part 0.x
With all the industry talk about the benefits of Linux on Power and all the performance advantages offered by its open architecture, you may be considering a move in that direction. If you are thinking about analytics, big data and cloud computing, you would be right to evaluate Power. The idea of using commodity x86 hardware and replacing it every three years is an outdated cost model. It doesn’t consider the total cost of ownership, and it doesn’t consider the advantage of real processing power, high-availability and multithreading like a demon.
This ebook takes a look at some of the practical applications of the Linux on Power platform and ways you might bring all the performance power of this open architecture to bear for your organization. There are no smoke and mirrors here—just hard, cold, empirical evidence provided by independent sources. I also consider some innovative ways Linux on Power will be used in the future.Get the Guide