All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.joseki.processors.ProcessorBase Maven / Gradle / Ivy

/*
 * (c) Copyright 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP
 * All rights reserved.
 * [See end of file]
 */

package org.joseki.processors;


import org.cogchar.joswrap.ModJosDatasetDesc;
import java.lang.reflect.Method;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.joseki.*;

import com.hp.hpl.jena.rdf.model.Model;

import com.hp.hpl.jena.shared.JenaException;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.shared.LockMutex;

import com.hp.hpl.jena.query.Dataset;


public abstract class ProcessorBase implements Processor
{
	public static boolean stusLockingEnabledFlag = true;
	public static boolean stusTransactEnabledFlag = true;
	
    private static final Logger log = LoggerFactory.getLogger(ProcessorBase.class) ; 
    Lock lock = new LockMutex() ;   // Default and safe choice
    
    /** Execute a operation, providing a lock */ 
    public void exec(Request request, Response response, final ModJosDatasetDesc datasetDesc) throws ExecutionException
    {
        Lock thisLock = lock ;
        boolean transactions = false ;
        Model defaultModel = null ;
        
        final Dataset dataset = buildDataset(datasetDesc, request, response)  ;
		boolean dsetXactOpen = false;
        if ( dataset != null )
        {
            ResponseCallback cbLock = new ResponseCallback() {
                public void callback(boolean successfulOperation)
                {
                    log.debug("ResponseCallback: return dataset to pool") ;
                    datasetDesc.returnDataset(dataset) ;
                }} ;
            response.addCallback(cbLock) ;
			// Begin Stu's Xact patch:
			
			if (dataset.supportsTransactions()) {
				log.info("Opening WRITE transaction against our dataset");
				dataset.begin(com.hp.hpl.jena.query.ReadWrite.WRITE);
				dsetXactOpen = true;
			}
			
			thisLock = dataset.getLock() ; // Stu sez - this call to getLock() was throwing before the patch
            // Transactions - if and only if there is a default model supporting transactions
            defaultModel = dataset.getDefaultModel() ;
            transactions = defaultModel.supportsTransactions() && stusTransactEnabledFlag ;
        }
        
//        if ( datasetDesc != null && datasetDesc.getDataset() != null )
//            thisLock = datasetDesc.getDataset().getLock() ;
        
        final Lock operationLock = thisLock ;
        
        String op = request.getParam(Joseki.OPERATION) ;
        boolean lockType = Lock.READ ;
        if ( op.equals(Joseki.OP_UPDATE) )
            lockType = Lock.WRITE ;
        
        boolean needAbort = false ;     // Need to clear up?
        
        // -- Add callbacks
		if (stusLockingEnabledFlag) {
	        operationLock.enterCriticalSection(lockType) ;		
		}
        ResponseCallback cbLock = new ResponseCallback() {
            public void callback(boolean successfulOperation)
            {
                log.debug("ResponseCallback: criticalSection") ;
				if (stusLockingEnabledFlag) {
	                operationLock.leaveCriticalSection() ;
				}
            }} ;
        response.addCallback(cbLock) ;
        final boolean dsetXactionActive = dsetXactOpen;
        // Always add - TDB supports .commit.
        if ( transactions )
        {
            needAbort = true ;
            try { defaultModel.begin(); } catch (UnsupportedOperationException ex) { needAbort = false ; }
            final Model m = defaultModel ;
			
			
            ResponseCallback cb = new ResponseCallback() {
                public void callback(boolean successfulOperation)
                {
                    log.debug("ResponseCallback: transaction") ;
                    if ( successfulOperation )
                        try { 
							m.commit(); 
							if (dsetXactionActive) {
								log.info("Commiting dataset xact");
								dataset.commit();
								dataset.end();
							}
						} catch (Exception ex) { log.info("Exception on commit: "+ex.getMessage()) ; }
                    else
                        try {
							m.abort(); 
							if (dsetXactionActive) {
								log.info("Aborting dataset xact");
								dataset.abort();
								dataset.end();
							}
						}  catch (Exception ex) { log.info("Exception on abort: "+ex.getMessage()) ; }
                }} ;
            response.addCallback(cb) ;
        } else {
            // --------
            // Long term - migrate Sync to ARQ and Commit or Sync on datasets
            // For now (to avoid a version bump), do a reflection call.
            if ( dataset != null )
            {
                ResponseCallback cb = new ResponseCallback() {
                    public void callback(boolean successfulOperation)
                    {
						if (dsetXactionActive) {
							if (successfulOperation) {
								log.info("Commiting dataset xact - Stu notest that this is where commit happens with TDB-in Mem as of 2014-06-28");
								dataset.commit();
								dataset.end();
							} else {
								log.info("Aborting dataset xact");
								dataset.abort();
								dataset.end();
							}
						}
                        log.debug("ResponseCallback: sync") ;
                        if ( attemptSync(dataset.asDatasetGraph()) )
                            log.debug("ResponseCallback: sync/done") ;
                        else
                            log.debug("ResponseCallback: sync (no action)") ;
                    }} ;
                response.addCallback(cb) ;
            }
            // --------
        }

        try {
            execOperation(request, response, dataset) ;
        } catch (ExecutionException ex)
        {
            // Callbacks should handle this.
//            // Looking bad - abort the transaction, release the lock.
//            if ( needAbort && transactions )
//                defaultModel.abort();
			
			// 2012-11-17   Stu uncommented this, since it appears that exceptions above leave Joseki hung
			// on next update attempt.
			log.warn("*********************** Leaving critical section from exception handler, using code uncommented by Stu!");
			if (stusLockingEnabledFlag) {
		          operationLock.leaveCriticalSection() ;
			}
            throw ex ; 
        }
        // These should have been caught.
        catch (JenaException ex)
        {
//            // Looking bad - abort the transaction, release the lock.
//            if ( needAbort && transactions )
//                defaultModel.abort();
			
			
			// 2012-11-17   Stu uncommented this, since it appears that exceptions above leave Joseki hung
			// on next update attempt.
			log.warn("*********************** Leaving critical section from exception handler, using code uncommented by Stu!");
			operationLock.leaveCriticalSection() ;
            log.warn("Internal error - unexpected exception: ", ex) ;
            throw ex ; 
        }
        
    }
    
    private Dataset buildDataset(ModJosDatasetDesc datasetDesc, Request request, Response response)
    {
        return (datasetDesc==null) ? null : datasetDesc.acquireDataset(request, response) ;
    }

    private static boolean attemptSync(Object object)
    {
        // Attempt "sync(boolean)"
        try
        {
            Method syncMethod = object.getClass().getMethod("sync", new Class[]{Boolean.TYPE}) ;
            if ( syncMethod != null )
            {
                syncMethod.invoke(object, true) ;
                return true ;
            }
            return false;
        } catch (NoSuchMethodException ex) { return false ; }
        catch (Exception ex)
        {
            log.warn("Failed to call 'sync'", ex) ;
            return false ;
        }
    }

    public void setLock(Lock lock)
    {
        this.lock = lock ;
    }
    
    /** Execute an operation within a lock and/or a transaction (on the default model) */ 
    public abstract void execOperation(Request request, Response response, Dataset defaultDataset)
    throws ExecutionException ;
}

/*
 * (c) Copyright 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */




© 2015 - 2025 Weber Informatics LLC | Privacy Policy