/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.fuseki.server;
import java.util.* ;
import java.util.concurrent.atomic.AtomicLong ;
import org.apache.jena.fuseki.Fuseki ;
import org.apache.jena.query.ReadWrite ;
import org.apache.jena.sparql.core.DatasetGraph ;
public class DatasetRef implements DatasetMXBean, Counters
{
public String name = null ;
public DatasetGraph dataset = null ;
public ServiceRef query = new ServiceRef("query") ;
public ServiceRef update = new ServiceRef("update") ;
public ServiceRef upload = new ServiceRef("upload") ;
public ServiceRef readGraphStore = new ServiceRef("gspRead") ;
public ServiceRef readWriteGraphStore = new ServiceRef("gspReadWrite") ;
// Dataset-level counters.
private final CounterSet counters = new CounterSet() ;
@Override
public CounterSet getCounters() { return counters ; }
private Map<String, ServiceRef> endpoints = new HashMap<String, ServiceRef>() ;
private List<ServiceRef> serviceRefs = new ArrayList<ServiceRef>() ;
private boolean initialized = false ;
// Two step initiation (c.f. Builder pattern)
// Create object - incrementally set state - call init to calculate internal datastructures.
public DatasetRef() {}
public void init() {
if ( initialized )
Fuseki.serverLog.warn("Already initialized: dataset = "+name) ;
initialized = true ;
initServices() ;
}
@Override public String toString() { return "DatasetRef:'"+name+"'" ; }
private void initServices() {
add(query) ;
add(update) ;
add(upload) ;
add(readGraphStore) ;
add(readWriteGraphStore) ;
addCounters() ;
}
private void add(ServiceRef srvRef) {
serviceRefs.add(srvRef) ;
for ( String ep : srvRef.endpoints )
endpoints.put(ep, srvRef) ;
}
public ServiceRef getServiceRef(String service) {
if ( ! initialized )
Fuseki.serverLog.error("Not initialized: dataset = "+name) ;
if ( service.startsWith("/") )
service = service.substring(1, service.length()) ;
return endpoints.get(service) ;
}
public Collection<ServiceRef> getServiceRefs() {
return serviceRefs ;
}
/** Counter of active read transactions */
public AtomicLong activeReadTxn = new AtomicLong(0) ;
/** Counter of active write transactions */
public AtomicLong activeWriteTxn = new AtomicLong(0) ;
/** Cumulative counter of read transactions */
public AtomicLong totalReadTxn = new AtomicLong(0) ;
/** Cumulative counter of writer transactions */
public AtomicLong totalWriteTxn = new AtomicLong(0) ;
// /** Count of requests received - anyzservice */
// public AtomicLong countServiceRequests = new AtomicLong(0) ;
// /** Count of requests received that fail in some way */
// public AtomicLong countServiceRequestsBad = new AtomicLong(0) ;
// /** Count of requests received that fail in some way */
// public AtomicLong countServiceRequestsOK = new AtomicLong(0) ;
//
// // SPARQL Query
//
// /** Count of SPARQL Queries successfully executed */
// public AtomicLong countQueryOK = new AtomicLong(0) ;
// /** Count of SPARQL Queries with syntax errors */
// public AtomicLong countQueryBadSyntax = new AtomicLong(0) ;
// /** Count of SPARQL Queries with timeout on execution */
// public AtomicLong countQueryTimeout = new AtomicLong(0) ;
// /** Count of SPARQL Queries with execution errors (not timeouts) */
// public AtomicLong countQueryBadExecution = new AtomicLong(0) ;
public void startTxn(ReadWrite mode)
{
switch(mode)
{
case READ:
activeReadTxn.getAndIncrement() ;
totalReadTxn.getAndIncrement() ;
break ;
case WRITE:
activeWriteTxn.getAndIncrement() ;
totalWriteTxn.getAndIncrement() ;
break ;
}
}
public void finishTxn(ReadWrite mode)
{
switch(mode)
{
case READ:
activeReadTxn.decrementAndGet() ;
break ;
case WRITE:
activeWriteTxn.decrementAndGet() ;
break ;
}
}
//TODO Need to be able to set this from the config file.
public boolean allowDatasetUpdate = false;
public boolean allowTimeoutOverride = false;
public long maximumTimeoutOverride = Long.MAX_VALUE;
public boolean isReadOnly()
{
return ! allowDatasetUpdate &&
! update.isActive() &&
! upload.isActive() &&
! readWriteGraphStore.isActive()
;
}
// MBean
@Override
public String getName() { return name ; }
@Override public long getRequests() {
return counters.value(CounterName.Requests) ;
}
@Override
public long getRequestsGood() {
return counters.value(CounterName.RequestsGood) ;
}
@Override
public long getRequestsBad() {
return counters.value(CounterName.RequestsBad) ;
}
private void addCounters() {
getCounters().add(CounterName.Requests) ;
getCounters().add(CounterName.RequestsGood) ;
getCounters().add(CounterName.RequestsBad) ;
query.getCounters().add(CounterName.Requests) ;
query.getCounters().add(CounterName.RequestsGood) ;
query.getCounters().add(CounterName.RequestsBad) ;
query.getCounters().add(CounterName.QueryTimeouts) ;
query.getCounters().add(CounterName.QueryExecErrors) ;
update.getCounters().add(CounterName.Requests) ;
update.getCounters().add(CounterName.RequestsGood) ;
update.getCounters().add(CounterName.RequestsBad) ;
update.getCounters().add(CounterName.UpdateExecErrors) ;
upload.getCounters().add(CounterName.Requests) ;
upload.getCounters().add(CounterName.RequestsGood) ;
upload.getCounters().add(CounterName.RequestsBad) ;
addCountersForGSP(readWriteGraphStore.getCounters(), false) ;
if ( readGraphStore != readWriteGraphStore )
addCountersForGSP(readGraphStore.getCounters(), true) ;
}
private void addCountersForGSP(CounterSet cs, boolean readWrite) {
cs.add(CounterName.Requests) ;
cs.add(CounterName.RequestsGood) ;
cs.add(CounterName.RequestsBad) ;
cs.add(CounterName.GSPget) ;
cs.add(CounterName.GSPgetGood) ;
cs.add(CounterName.GSPgetBad) ;
cs.add(CounterName.GSPhead) ;
cs.add(CounterName.GSPheadGood) ;
cs.add(CounterName.GSPheadBad) ;
// Add anyway.
// if ( ! readWrite )
// return ;
cs.add(CounterName.GSPput) ;
cs.add(CounterName.GSPputGood) ;
cs.add(CounterName.GSPputBad) ;
cs.add(CounterName.GSPpost) ;
cs.add(CounterName.GSPpostGood) ;
cs.add(CounterName.GSPpostBad) ;
cs.add(CounterName.GSPdelete) ;
cs.add(CounterName.GSPdeleteGood) ;
cs.add(CounterName.GSPdeleteBad) ;
cs.add(CounterName.GSPpatch) ;
cs.add(CounterName.GSPpatchGood) ;
cs.add(CounterName.GSPpatchBad) ;
cs.add(CounterName.GSPoptions) ;
cs.add(CounterName.GSPoptionsGood) ;
cs.add(CounterName.GSPoptionsBad) ;
}
}