FileDocCategorySizeDatePackage
SnmpSession.javaAPI DocJava SE 5 API16884Fri Aug 26 14:55:06 BST 2005com.sun.jmx.snmp.daemon

SnmpSession

public class SnmpSession extends Object implements Runnable, com.sun.jmx.snmp.SnmpDefinitions
This class is used for sending INFORM REQUESTS from an agent to a manager. Creates, controls, and manages one or more inform requests. The SnmpSession maintains the list of all active inform requests and inform responses. Each SnmpSession has a dispatcher that is a thread used to service all the inform requests it creates and each SnmpSession uses a separate socket for sending/receiving inform requests/responses. An SnmpSession object is associated with an SNMP adaptor server. It is created the first time an inform request is sent by the SNMP adaptor server and is destroyed (with its associated SnmpSocket) when the SNMP adaptor server is stopped.

Fields Summary
protected transient SnmpAdaptorServer
adaptor
The SNMP adaptor associated with this SnmpSession.
protected transient SnmpSocket
informSocket
The SnmpSocket to be used to communicate with the manager by all inform requests created in this session.
private transient Hashtable
informRequestList
This table maintains the list of inform requests.
private transient Stack
informRespq
This table maintains the list of inform responses. A FIFO queue is needed here.
private transient Thread
myThread
The dispatcher that will service all inform responses to inform requests generated using this session object. An SnmpSession object creates one or more inform requests. Thus it services all inform requests, which are created by this session object, when an inform response arrives for an inform request generated by the session.
private transient SnmpInformRequest
syncInformReq
Request being synchronized from session thread. This happens when a user does sync operation from a callback.
SnmpQManager
snmpQman
String
dbgTag
private boolean
isBeingCancelled
Constructors Summary
public SnmpSession(SnmpAdaptorServer adp)
Constructor for creating a new session.

param
adp The SNMP adaptor associated with this SnmpSession.
exception
SocketException Unable to initialize the SnmpSocket.

    
    // PUBLIC CONSTRUCTORS
    //--------------------
    
                                 
         
        adaptor = adp;
	snmpQman = new SnmpQManager();
	SnmpResponseHandler snmpRespHdlr = new SnmpResponseHandler(adp, snmpQman);
        initialize(adp, snmpRespHdlr);
    
public SnmpSession()
Constructor for creating a new session. Allows subclassing.

    
Methods Summary
synchronized voidaddInformRequest(SnmpInformRequest snmpreq)
Adds an inform request.

param
snmpreq The inform request to add.
exception
SnmpStatusException SNMP adaptor is not ONLINE or session is dead.

        
        // If the adaptor is not ONLINE, stop adding requests.
        //
        if (!isSessionActive()) {
            throw new SnmpStatusException("SNMP adaptor is not ONLINE or session is dead...") ;
        }
        informRequestList.put(snmpreq, snmpreq);
    
voidaddResponse(SnmpInformRequest reqc)
Adds the inform request object which received a response to an inform request generated by the session. This is added to a private store, which will be eventually picked up by the dispatcher for processing.

param
reqc The inform request that received the response from the manager.

        
        SnmpInformRequest snmpreq = (SnmpInformRequest) reqc ;
        if (isSessionActive()) {
            synchronized(this) {
                informRespq.push(reqc) ;
                this.notifyAll() ;
            }
        } else {
            if (isDebugOn()) {
                debug("addResponse", "Adaptor not ONLINE or session thread dead. So inform response is dropped..." + reqc.getRequestId());
            }
        }
        return ;
    
private voidcancelAllRequests()
Cancels all pending inform requests in this session.

        final SnmpInformRequest[] list;
	
	synchronized(this) {
	    
	    if (informRequestList.isEmpty()) {
		return ;
	    }

	    isBeingCancelled = true;
	    
	    list = new SnmpInformRequest[informRequestList.size()];
	    java.util.Iterator it = informRequestList.values().iterator();
	    int i = 0;
	    while(it.hasNext()) {
		SnmpInformRequest req = (SnmpInformRequest)it.next();
		list[i++] = req;
		it.remove();
	    }
	    informRequestList.clear();
	}
	
	for(int i = 0; i < list.length; i++)
	    list[i].cancelRequest();
    
private synchronized voidcancelAllResponses()

        if (informRespq != null) {
            syncInformReq = null ;
            informRespq.removeAllElements() ;
            this.notifyAll() ;
        }
    
voiddebug(java.lang.String clz, java.lang.String func, java.lang.String info)

        Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
    
voiddebug(java.lang.String clz, java.lang.String func, java.lang.Throwable exception)

        Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, exception);
    
voiddebug(java.lang.String func, java.lang.String info)

        debug(dbgTag, func, info);
    
voiddebug(java.lang.String func, java.lang.Throwable exception)

        debug(dbgTag, func, exception);
    
final voiddestroySession()
Destroys any pending inform requests and then stops the session. The session will not be usable after this method returns.

        
        cancelAllRequests() ;
        cancelAllResponses() ;
        synchronized(this) {
            informSocket.close() ;
            informSocket = null ;
        }
        snmpQman.stopQThreads() ;
        snmpQman = null ;
        killSessionThread() ;
    
public voidfinalize()
Finalizer of the SnmpSession objects. This method is called by the garbage collector on an object when garbage collection determines that there are no more references to the object.

Removes all the requests for this SNMP session, closes the socket and sets all the references to the SnmpSession object to null.

        
        if (informRespq != null)
            informRespq.removeAllElements() ;
        informRespq = null ;
        if (informSocket != null)
            informSocket.close() ;
        informSocket = null ;

        if (isTraceOn()) {
            trace("finalize", "Shutting all servers");
        }
        snmpQman = null ;
    
SnmpQManagergetSnmpQManager()
Gets the SnmpQManager which will be used by inform requests created in this session.

return
The SnmpQManager which will be used in this session.

        return snmpQman;
    
SnmpSocketgetSocket()
Gets the SnmpSocket which will be used by inform requests created in this session.

return
The socket which will be used in this session.

        return informSocket;
    
protected synchronized voidinitialize(SnmpAdaptorServer adp, SnmpResponseHandler snmpRespHdlr)
Initializes the SnmpSession.

param
adp The SNMP adaptor associated with this SnmpSession.
exception
SocketException Unable to initialize the SnmpSocket.

	informSocket = new SnmpSocket(snmpRespHdlr, adp.getAddress(), adp.getBufferSize().intValue());

        myThread = new Thread(this, "SnmpSession");
        myThread.start();
    
booleanisDebugOn()

        return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
    
synchronized booleanisSessionActive()
Indicates whether the thread for this session is active and the SNMP adaptor server ONLINE.

return
true if active, false otherwise.

        //return ((myThread != null) && (myThread.isAlive()));
        return ((adaptor.isActive()) && (myThread != null) && (myThread.isAlive()));
    
booleanisTraceOn()

        return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP);
    
private synchronized voidkillSessionThread()
Make sure you are killing the thread when it is active. Instead prepare for a graceful exit.

        
        if ((myThread != null) && (myThread.isAlive())) {
            if (isTraceOn()) {
                trace("killSessionThread", "Destroying session");
            }
            if (!thisSessionContext()) {
                myThread = null ;
                this.notifyAll() ;
            } else
                myThread = null ;
        }
    
SnmpInformRequestmakeAsyncRequest(java.net.InetAddress addr, java.lang.String cs, SnmpInformHandler cb, com.sun.jmx.snmp.SnmpVarBindList vblst, int port)
Sends an inform request to the specified InetAddress destination using the specified community string.

param
addr The InetAddress destination for this inform request.
param
cs The community string to be used for the inform request.
param
cb The callback that is invoked when a request is complete.
param
vblst A list of SnmpVarBind instances or null.
exception
SnmpStatusException SNMP adaptor is not ONLINE or session is dead.

        
        if (!isSessionActive()) {
            throw new SnmpStatusException("SNMP adaptor server not ONLINE");
        }
        SnmpInformRequest snmpreq = new SnmpInformRequest(this, adaptor, addr, cs, port, cb);
        snmpreq.start(vblst);
        return snmpreq;
    
private synchronized SnmpInformRequestnextResponse()

        
        if (informRespq.isEmpty()) {
            try {
                if (isTraceOn()) {
                    trace("nextResponse", "Blocking for response");
                }
                this.wait();
            } catch(InterruptedException e) {
            }
        }
        if (informRespq.isEmpty())
            return null;
        SnmpInformRequest reqc = (SnmpInformRequest) informRespq.firstElement();
        informRespq.removeElementAt(0) ;
        return reqc ;
    
private voidprocessResponse(SnmpInformRequest reqc)

        
        while (reqc != null && myThread != null) {
            try {
                if (reqc != null) {
                    if (isTraceOn()) {
                        trace("processResponse", "Processing response to req = " + reqc.getRequestId());
                    }
                    reqc.processResponse() ;  // Handles out of memory.
                    reqc = null ;  // finished processing.
                }
				
            } catch (Exception e) {
                if (isDebugOn()) {
                    debug("processResponse", e);
                }
                reqc = null ;
            } catch (OutOfMemoryError ome) {
                if (isDebugOn()) {
                    debug("processResponse", "Out of memory error in session thread");
                    debug("processResponse", ome);
                }
                Thread.currentThread().yield();
                continue ;   // re-process the request.
            }
        }
    
synchronized voidremoveInformRequest(SnmpInformRequest snmpreq)
Deletes an inform request.

param
snmpreq The inform request to delete.

	// deleteRequest can be called from destroySnmpSession.
	//In such a case remove is done in cancelAllRequest method.
	if(!isBeingCancelled)
	    informRequestList.remove(snmpreq) ;

        if (syncInformReq != null && syncInformReq == snmpreq) {
            resetSyncMode() ;
        }
    
private synchronized voidresetSyncMode()

        if (syncInformReq == null)
            return ;
        syncInformReq = null ;
        if (thisSessionContext())
            return ;
        this.notifyAll() ;
    
public voidrun()
Dispatcher method for this session thread. This is the dispatcher method which goes in an endless-loop and waits for servicing inform requests which received a reply from the manager.

        myThread = Thread.currentThread();
        myThread.setPriority(Thread.NORM_PRIORITY);

        SnmpInformRequest reqc = null;
        while (myThread != null) {
            try {
                reqc = nextResponse();
                if (reqc != null) {
                    processResponse(reqc);
                }
            } catch (ThreadDeath d) {
                myThread = null;
                if (isDebugOn()) {
                    debug("run", "Session thread unexpectedly shutting down");
                }
                throw d ;
            }
        }
        if (isTraceOn()) {
            trace("run", "Session thread shutting down");
        }
        myThread = null ;
    
private synchronized voidsetSyncMode(SnmpInformRequest req)

        syncInformReq = req ;
    
private synchronized booleansyncInProgress()
Indicates whether this session is performing synchronous operation for an inform request.

return
true if the session is performing synchronous operation, false otherwise.

        return syncInformReq != null ;
    
booleanthisSessionContext()
Returns true if the current executing thread is this session's dispatcher. Typically used to detect whether the user is doing a sync operation from this dispatcher context. For instance, a user gives a sync command from within a request callback using its associated session.

return
true if current thread is this session's dispatcher, false otherwise.

        return (Thread.currentThread() == myThread) ;
    
voidtrace(java.lang.String clz, java.lang.String func, java.lang.String info)

        Trace.send(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
    
voidtrace(java.lang.String func, java.lang.String info)

        trace(dbgTag, func, info);
    
voidwaitForResponse(SnmpInformRequest req, long waitTime)
Performs sync operations on active requests. Any number of inform requests can be done in sync mode but only one per thread. The user can do synchronous operation using the request handle only.

        
        if (! req.inProgress())
            return ;
        setSyncMode(req) ;

        if (isTraceOn()) {
            trace("waitForResponse", "Session switching to sync mode for inform request " + req.getRequestId());
        }
        long maxTime ;
        if (waitTime <= 0)
            maxTime = System.currentTimeMillis() + 6000 * 1000 ;
        else
            maxTime = System.currentTimeMillis() + waitTime ;

        while (req.inProgress() || syncInProgress()) {
            waitTime = maxTime - System.currentTimeMillis() ;
            if (waitTime <= 0)
                break ;
            synchronized (this) {
                if (! informRespq.removeElement(req)) {
                    try {
                        this.wait(waitTime) ;
                    } catch(InterruptedException e) {
                    }
                    continue ;
                }
            }
            try {
                processResponse(req) ;
            } catch (Exception e) {
                if (isDebugOn()) {
                    debug("waitForResponse", e);
                }
            }
        }
        resetSyncMode() ;
        return ;