that seems to work. So the lock attribute is useless now. I am not 
entirely sure why this fixes things since I cannot see anyone else 
synchronizing on sConn, but I assume that happens somewhere outside.

I added a comment to https://issues.apache.org/jira/browse/JENA-252



From:
Simon Helsen/Toronto/IBM@IBMCA
To:
[email protected]
Cc:
Andy Seaborne <[email protected]>, [email protected]
Date:
06/08/2012 05:01 PM
Subject:
Re: Release 2.7.1



I'll try the proposed fix. 

If you can tell me what you're looking for, I can debug this further. What 

exactly do you mean by "It's hard to tell without how the 
DatasetGraphTransaction's get made"? 

As for the style, I followed the documentation on multiple threads, so I 
create a dataset for each transaction and close it. A transaction is 
unique per thread, i.e. not shared as recommended. You saw the model 
already in the test I provide for 250, so we have something like this

        private <E> E storeOperation(String query, QueryActivity<E> 
queryActivity) {
                Dataset dataset = TDBFactory.createDataset(this.location);
                QueryExecution qe = null;
                try {
                        dataset.begin(ReadWrite.READ) ;
                        qe = QueryExecutionFactory.create(query, dataset);
                        E e = queryActivity.run(qe);
                        dataset.commit();
                        return e;
                } catch (Throwable e) {
                        dataset.abort();
                        throw new RuntimeException(e);
                } finally {
                        try {
                                if (qe != null) {
                                        qe.close();
                                }
                        } finally {
                                dataset.end();
                        }
                }
        }

for a query - and FYI, we do not allow update queries. There are some 
other variations of this for type of reads, but in my test case it looks 
like this is the one being used by the read transactions. Then we use this 

one for writes:

private <E> E storeOperation(String graphName, ModelWriteActivity<E> 
modelWriteActivity) {
                Dataset dataset = TDBFactory.createDataset(this.location);
                try {
                        dataset.begin(ReadWrite.WRITE);
                        Model m = dataset.getNamedModel(graphName);
                        E e = modelWriteActivity.run(m);
                        dataset.commit();
                        return e;
                } catch (Throwable e) {
                        dataset.abort();
                        throw new RuntimeException(e);
                } finally {
                        dataset.end();
                }
        }

and we have one for multiple models per transaction. Each of these are 
executed within their own thread. The dataset is (obviously) never shared

Simon






From:
Andy Seaborne <[email protected]>
To:
[email protected]
Date:
06/08/2012 04:07 PM
Subject:
Re: Release 2.7.1



On 08/06/12 19:55, Simon Helsen wrote:
> hi again,
>
> k, so, it is tricky to distill a test case out of our framework because
> this one is based on multiple threads, but I am debugging it myself
> instead.
>
> So, I put the breakpoint in DatasetControlMRSW.policyError where the cme
> is thrown. When I do that and rerun the test suite, I get into a 
scenario
> where 4 threads hang on the breakpoint. 3 of these are 'read' threads 
and
> 1 is a 'write' thread. Now, the writeCounter says it has 4 (and the
> readCounter is 0), which is why the cme is thrown. So, the question is 
why
> the writeCounter says 4.
>
> In order to find that out, I set a different breakpoint at startUpdate 
in
> DatasetControlMRSW. I notice that it came from a query, i.e. a READ
> transaction. The violating code is this:
>
>
>    @Override
>      protected void _begin(ReadWrite readWrite)
>      {
>          synchronized(lock)
>          {
>              if ( ! haveUsedInTransaction )
>                  getBaseDatasetGraph().sync() ;
>              haveUsedInTransaction = true ;
>              DatasetGraphTxn dsgTxn = sConn.begin(readWrite) ;
>              txn.set(dsgTxn) ;
>              inTransaction.set(true) ;
>          }
>      }
>
>
> The bit
>
>      if ( ! haveUsedInTransaction )
>                  getBaseDatasetGraph().sync() ;
>
> is the problem. It calls prefixes.sync() which calls 
nodeTupleTable.sync()
> which calls  startWrite() ;
>
> any ideas how to fix this?
>
> Simon


sync's are writes.

It's making sure that any non-transactional changes are put to disk 
before the whole thing swicths into transactional mode.  Not a usage to 
be encouraged but the code needs to be safe.


It's hard to tell without how the DatasetGraphTransaction's get made but 
try changing

     synchronized(lock)

to

     synchronized(sConn)

(the test suite passes - not surprising as it is a more conservative 
choice than the built code.)

It's late here - but that might be the cause.  Otherwise, how are the 
dataset being made?  There seem to be several about - that should be OK, 
as should multiple threads per DatasetGraphTransaction (transactions are 
per thread).  Which style are you using?

                 Andy






Reply via email to