costin 02/04/15 17:04:20 Modified: jk/java/org/apache/jk/common ChannelJni.java Log: Refactored ChannelJni - it uses AprImpl to talk with the dark side. This will allow us to use the optimizations in channel_jni for other C->java calls ( basically avoid creating byte[] or objects per request and minimizing the number of JNI calls in the critical path ) It seems the JNI worker is back ( of course, in single-process mode - the multip-process depends on shmem and autoconfiguration ) Revision Changes Path 1.5 +83 -107 jakarta-tomcat-connectors/jk/java/org/apache/jk/common/ChannelJni.java Index: ChannelJni.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/jk/java/org/apache/jk/common/ChannelJni.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- ChannelJni.java 6 Feb 2002 17:43:08 -0000 1.4 +++ ChannelJni.java 16 Apr 2002 00:04:20 -0000 1.5 @@ -77,35 +77,31 @@ * * @author Costin Manolache */ -public class ChannelJni extends Channel { +public class ChannelJni extends Channel implements AprImpl.JniContextFactory { + private static org.apache.commons.logging.Log log= + org.apache.commons.logging.LogFactory.getLog( ChannelJni.class ); int receivedNote=1; + AprImpl apr=AprImpl.getAprImpl(); + + public ChannelJni() { // we use static for now, it's easier on the C side. // Easy to change after we get everything working - chJni=this; + log.info("Created channel jni "); } public void init() throws IOException { // static field init, temp - wEnvStatic=wEnv; + log.info("init "); + apr.addJniContextFactory( "channelJni", this ); } - + + // XXX Not used public int receive( Msg msg, MsgContext ep ) throws IOException { Msg sentResponse=(Msg)ep.getNote( receivedNote ); - // same buffer is used, no need to copy - if( msg==sentResponse ) { - if( dL > 0 ) d("Returned previously received message "); - return 0; - } - - if( dL > 0 ) d("XXX Copy previously received message "); - // send will alter the msg and insert the response. - // copy... - // XXX TODO - return 0; } @@ -117,59 +113,40 @@ throws IOException { byte buf[]=msg.getBuffer(); - EpData epData=(EpData)ep.getNote( epDataNote ); + + JniEndpoint epData=(JniEndpoint)ep; // send and get the response - if( dL > 0 ) d( "Sending packet "); + if( log.isInfoEnabled() ) log.info( "Sending packet "); msg.end(); - // msg.dump("Outgoing: "); - - int status=sendPacket( epData.jkEnvP, epData.jkEndpointP, - epData.jkServiceP, buf, msg.getLen() ); - ep.setNote( receivedNote, msg ); - - if( dL > 0 ) d( "Sending packet - done "); - return 0; - } - static int epDataNote=-1; + // Assert: apr initialized + // Will process the message in the current thread. + // No wait needed to receive the response + // + int status=apr.sendPacket( epData.xEnv, epData.jkEndpointP, + buf, msg.getLen() ); - public MsgContext createEndpoint(long env, long epP) { - MsgContext ep=new MsgContext(); - if( epDataNote==-1) - epDataNote=wEnv.getNoteId(WorkerEnv.ENDPOINT_NOTE, "epData"); - - if( dL > 0 ) d("createEndpointStatic() " + env + " " + epP); + ep.setNote( receivedNote, msg ); - EpData epData=new EpData(); - epData.jkEnvP=env; - epData.jkEndpointP=epP; - ep.setNote( epDataNote, epData ); - ep.setWorkerEnv( wEnv ); - - ep.setChannel( this ); - return ep; + if( log.isInfoEnabled() ) log.info( "Sending packet - done "); + return 0; } - public int receive( long env, long rP, MsgContext ep, - MsgAjp msg) + public int receive( MsgContext ep, MsgAjp msg, long xEnv, long cEndpointP) { try { // first, we need to get an endpoint. It should be // per/thread - and probably stored by the C side. - if( dL > 0 ) d("Received request " + rP); + if( log.isInfoEnabled() ) log.info("Received request " + xEnv); + // The endpoint will store the message pt. - msg.processHeader(); - if( dL > 5 ) msg.dump("Incoming msg "); + if( log.isInfoEnabled() ) msg.dump("Incoming msg "); - EpData epData=(EpData)ep.getNote( epDataNote ); - - epData.jkServiceP=rP; - int status= this.invoke( msg, ep ); - if(dL > 0 ) d("after processCallbacks " + status); + if( log.isInfoEnabled() ) log.info("after processCallbacks " + status); return status; } catch( Exception ex ) { @@ -177,68 +154,67 @@ } return 0; } - - /* ==================== ==================== */ - static WorkerEnv wEnvStatic=null; - static ChannelJni chJni=new ChannelJni(); + /* ==================== Native liaison ==================== */ - static class EpData { - public long jkEnvP; - public long jkEndpointP; - public long jkServiceP; - } - - public static MsgContext createEndpointStatic(long env, long epP) { - return chJni.createEndpoint( env, epP ); - } + static class JniEndpoint extends MsgContext implements AprImpl.JniContext { + // c Context + long jkEndpointP; + long xEnv; + ChannelJni chJni; + MsgAjp msgAjp=new MsgAjp(); + + public byte[] getBuffer( int id ) { + // We use a single buffer right now. + return msgAjp.getBuffer(); + } + + + /** Receive a packet from the C side. This is called from the C + * code using invocation, but only for the first packet - to avoid + * recursivity and thread problems. + * + * This may look strange, but seems the best solution for the + * problem ( the problem is that we don't have 'continuation' ). + * + * sendPacket will move the thread execution on the C side, and + * return when another packet is available. For packets that + * are one way it'll return after it is processed too ( having + * 2 threads is far more expensive ). + * + * Again, the goal is to be efficient and behave like all other + * Channels ( so the rest of the code can be shared ). Playing with + * java objects on C is extremely difficult to optimize and do + * right ( IMHO ), so we'll try to keep it simple - byte[] passing, + * the conversion done in java ( after we know the encoding and + * if anyone asks for it - same lazy behavior as in 3.3 ). + */ + /** Invoke a java hook. The xEnv is the representation of the current execution + * environment ( the jni_env_t * ) + */ + public int jniInvoke( long xEnv ) { + this.xEnv=xEnv; + int status=chJni.receive( this, msgAjp, xEnv, jkEndpointP ); + this.xEnv=0; + return status; + } - public static MsgAjp createMessage() { - return new MsgAjp(); } - public static byte[] getBuffer(MsgAjp msg) { - //if( dL > 0 ) d("XXX getBuffer " + msg.getBuffer() + " " - // + msg.getBuffer().length); - return msg.getBuffer(); - } - - /** Receive a packet from the C side. This is called from the C - * code using invocation, but only for the first packet - to avoid - * recursivity and thread problems. - * - * This may look strange, but seems the best solution for the - * problem ( the problem is that we don't have 'continuation' ). - * - * sendPacket will move the thread execution on the C side, and - * return when another packet is available. For packets that - * are one way it'll return after it is processed too ( having - * 2 threads is far more expensive ). - * - * Again, the goal is to be efficient and behave like all other - * Channels ( so the rest of the code can be shared ). Playing with - * java objects on C is extremely difficult to optimize and do - * right ( IMHO ), so we'll try to keep it simple - byte[] passing, - * the conversion done in java ( after we know the encoding and - * if anyone asks for it - same lazy behavior as in 3.3 ). - */ - public static int receiveRequest( long env, long rP, MsgContext ep, - MsgAjp msg) - { - return chJni.receive(env, rP, ep, msg ); - } - - /** Send the packet to the C side. On return it contains the response - * or indication there is no response. Asymetrical because we can't - * do things like continuations. - */ - public static native int sendPacket(long env, long e, long s, - byte data[], int len); - - private static final int dL=0; - private static void d(String s ) { - System.err.println( "ChannelJni: " + s ); + public AprImpl.JniContext createJniContext( String type, long cContext ) { + if( log.isInfoEnabled() ) log.info("createJniEndpoint() " + cContext ); + JniEndpoint ep=new JniEndpoint(); + + ep.chJni=this; + ep.jkEndpointP=cContext; + + ep.setWorkerEnv( wEnv ); + ep.setChannel( this ); + + return ep; } + + }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>