JniHandlerpublic class JniHandler extends org.apache.jk.core.JkHandler Base class for components using native code ( libjkjni.so ).
It allows to access the jk_env and wrap ( 'box' ? ) a native
jk component, and call it's methods.
Note that get/setAttribute are expensive ( Strings, etc ),
invoke() is were all optimizations are done. We do recycle
all memory on both C and java sides ( the only exception is
when we attempt pinning but the VM doesn't support it ). The
low level optimizations from ByteBuffer, etc are used to
reduce the overhead of passing strings. |
Fields Summary |
---|
protected org.apache.jk.apr.AprImpl | apr | protected long | nativeJkHandlerP | protected String | jkHome | public static final int | JK_HANDLE_JNI_DISPATCH | public static final int | JK_HANDLE_SHM_DISPATCH | public static final int | MSG_NOTE | public static final int | MB_NOTE | private boolean | paused | private static org.apache.juli.logging.Log | log |
Constructors Summary |
---|
public JniHandler()
|
Methods Summary |
---|
public void | appendString(org.apache.jk.core.Msg msg, java.lang.String s, org.apache.tomcat.util.buf.C2BConverter charsetDecoder)
ByteChunk bc=charsetDecoder.getByteChunk();
charsetDecoder.recycle();
charsetDecoder.convert( s );
charsetDecoder.flushBuffer();
msg.appendByteChunk( bc );
| public org.apache.jk.core.MsgContext | createMsgContext()Create a msg context to be used with the shm channel
if( nativeJkHandlerP==0 || apr==null )
return null;
synchronized(this) {
try{
while(paused) {
wait();
}
}catch(InterruptedException ie) {
// Ignore, since it can't happen
}
}
try {
MsgContext msgCtx=new MsgContext();
MsgAjp msg=new MsgAjp();
msgCtx.setSource( (JkChannel)this );
msgCtx.setWorkerEnv( wEnv );
msgCtx.setNext( this );
msgCtx.setMsg( MSG_NOTE, msg); // XXX Use noteId
C2BConverter c2b=new C2BConverter( "iso-8859-1" );
msgCtx.setConverter( c2b );
MessageBytes tmpMB= MessageBytes.newInstance();
msgCtx.setNote( MB_NOTE, tmpMB );
return msgCtx;
} catch( Exception ex ) {
log.error("Can't create endpoint", ex);
return null;
}
| public void | destroyJkComponent()
if( apr==null ) return;
if( nativeJkHandlerP == 0 ) {
log.error( "Unitialized component " );
return;
}
long xEnv=apr.getJkEnv();
apr.jkDestroy( xEnv, nativeJkHandlerP );
apr.releaseJkEnv( xEnv );
| public java.lang.String | getJkHome()
return jkHome;
| public void | init()You must call initNative() inside the component init()
// static field init, temp
| public void | initJkComponent()
if( apr==null ) return;
if( nativeJkHandlerP == 0 ) {
log.error( "Unitialized component " );
return;
}
long xEnv=apr.getJkEnv();
apr.jkInit( xEnv, nativeJkHandlerP );
apr.releaseJkEnv( xEnv );
| protected void | initNative(java.lang.String nativeComponentName)
apr=(AprImpl)wEnv.getHandler("apr");
if( apr==null ) {
// In most cases we can just load it automatically.
// that requires all libs to be installed in standard places
// ( LD_LIBRARY_PATH, /usr/lib
try {
apr=new AprImpl();
wEnv.addHandler("apr", apr);
apr.init();
if( oname != null ) {
ObjectName aprname=new ObjectName(oname.getDomain() +
":type=JkHandler, name=apr");
Registry.getRegistry(null, null).registerComponent(apr, aprname, null);
}
} catch( Throwable t ) {
log.debug("Can't load apr", t);
apr=null;
}
}
if( apr==null || ! apr.isLoaded() ) {
if( log.isDebugEnabled() )
log.debug("No apr, disabling jni proxy ");
apr=null;
return;
}
try {
long xEnv=apr.getJkEnv();
nativeJkHandlerP=apr.getJkHandler(xEnv, nativeComponentName );
if( nativeJkHandlerP==0 ) {
log.debug("Component not found, creating it " + nativeComponentName );
nativeJkHandlerP=apr.createJkHandler(xEnv, nativeComponentName);
}
log.debug("Native proxy " + nativeJkHandlerP );
apr.releaseJkEnv(xEnv);
} catch( Throwable t ) {
apr=null;
log.info("Error calling apr ", t);
}
| public int | invoke(org.apache.jk.core.Msg msg, org.apache.jk.core.MsgContext ep)Base implementation for invoke. Dispatch the action to the native
code, where invoke() is called on the wrapped jk_bean.
long xEnv=ep.getJniEnv();
int type=ep.getType();
int status=nativeDispatch(msg, ep, type, 0 );
apr.jkRecycle(xEnv, ep.getJniContext());
apr.releaseJkEnv( xEnv );
return status;
| protected int | nativeDispatch(org.apache.jk.core.Msg msg, org.apache.jk.core.MsgContext ep, int code, int raw)send and get the response in the same buffer. This calls the
method on the wrapped jk_bean object.
if( log.isDebugEnabled() )
log.debug( "Sending packet " + code + " " + raw);
if( raw == 0 ) {
msg.end();
if( log.isTraceEnabled() ) msg.dump("OUT:" );
}
// Create ( or reuse ) the jk_endpoint ( the native pair of
// MsgContext )
long xEnv=ep.getJniEnv();
long nativeContext=ep.getJniContext();
if( nativeContext==0 || xEnv==0 ) {
setNativeEndpoint( ep );
xEnv=ep.getJniEnv();
nativeContext=ep.getJniContext();
}
if( xEnv==0 || nativeContext==0 || nativeJkHandlerP==0 ) {
log.error("invokeNative: Null pointer ");
return -1;
}
// Will process the message in the current thread.
// No wait needed to receive the response, if any
int status=AprImpl.jkInvoke( xEnv,
nativeJkHandlerP,
nativeContext,
code, msg.getBuffer(), 0, msg.getLen(), raw );
if( status != 0 && status != 2 ) {
log.error( "nativeDispatch: error " + status, new Throwable() );
}
if( log.isDebugEnabled() ) log.debug( "Sending packet - done " + status);
return status;
| public void | pause()
synchronized(this) {
paused = true;
}
| protected void | recycleNative(org.apache.jk.core.MsgContext ep)
apr.jkRecycle(ep.getJniEnv(), ep.getJniContext());
| public void | resume()
synchronized(this) {
paused = false;
notifyAll();
}
| public void | setJkHome(java.lang.String s)
jkHome=s;
| public void | setNativeAttribute(java.lang.String name, java.lang.String val)
if( apr==null ) return;
if( nativeJkHandlerP == 0 ) {
log.error( "Unitialized component " + name+ " " + val );
return;
}
long xEnv=apr.getJkEnv();
apr.jkSetAttribute( xEnv, nativeJkHandlerP, name, val );
apr.releaseJkEnv( xEnv );
| protected void | setNativeEndpoint(org.apache.jk.core.MsgContext msgCtx)
long xEnv=apr.getJkEnv();
msgCtx.setJniEnv( xEnv );
long epP=apr.createJkHandler(xEnv, "endpoint");
log.debug("create ep " + epP );
if( epP == 0 ) return;
apr.jkInit( xEnv, epP );
msgCtx.setJniContext( epP );
|
|