Package org.apache.clerezza.rdf.jena.tdb.storage

Source Code of org.apache.clerezza.rdf.jena.tdb.storage.TdbTcProvider$SyncThread

/*
* 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.clerezza.rdf.jena.tdb.storage;

import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.tdb.TDB;
import com.hp.hpl.jena.tdb.TDBFactory;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.clerezza.rdf.core.Graph;
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.TripleCollection;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.access.EntityAlreadyExistsException;
import org.apache.clerezza.rdf.core.access.EntityUndeletableException;
import org.apache.clerezza.rdf.core.access.LockableMGraph;
import org.apache.clerezza.rdf.core.access.LockableMGraphWrapper;
import org.apache.clerezza.rdf.core.access.NoSuchEntityException;
import org.apache.clerezza.rdf.core.access.WeightedTcProvider;
import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
import org.apache.clerezza.rdf.core.impl.util.PrivilegedMGraphWrapper;
import org.apache.clerezza.rdf.jena.storage.JenaGraphAdaptor;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;

/**
* A {@link org.apache.clerezza.rdf.core.access.WeightedTcProvider} based on Jena TDB.
*
* @see <a href="http://jena.hpl.hp.com/wiki/TDB/JavaAPI">
* TDB/JavaAPI</a>
*
* @author reto, hasan
*
* @scr.component immediate="true"
* @scr.service interface="org.apache.clerezza.rdf.core.access.WeightedTcProvider"
* @scr.property name="weight" type="Integer" value="105"
*
*/
@Component(metatype=true, immediate=true)
@Service(WeightedTcProvider.class)
@Property(name="weight", intValue=105)
public class TdbTcProvider implements WeightedTcProvider {

  @Property(intValue=6, description="Specifies the number of seconds to wait "
  + "between synchronizations of the TDB datasets to the filesystem")
  public static final String SYNC_INTERVAL = "sync-interval";
  private int syncInterval = 6;

  /**
   *  directory where all graphs are stored
   */
  private static final String DATA_PATH_NAME = "tdb-data/";
  private String dataPathString = DATA_PATH_NAME;
  private Map<UriRef, LockableMGraph> mGraphMap = new HashMap<UriRef, LockableMGraph>();
  private Map<UriRef, Graph> graphMap = new HashMap<UriRef, Graph>();
  private Map<File, com.hp.hpl.jena.graph.Graph> dir2JenaGraphMap =
      new HashMap<File, com.hp.hpl.jena.graph.Graph>();
  private final Map<File, Dataset> dir2Dataset = new HashMap<File, Dataset>();
  private static final Logger log = LoggerFactory.getLogger(TdbTcProvider.class);
  private int weight = 105;

  class SyncThread extends Thread {
    private boolean stopRequested = false;

    @Override
    public void run() {
      while (!stopRequested) {
        try {
          Thread.sleep(syncInterval*1000);
        } catch (InterruptedException ex) {
          interrupt();
        }
        if (!stopRequested) {
          syncWithFileSystem();
        }
      }
    }
   
    public void requestStop() {
      stopRequested = true;
    }
  }

  private SyncThread syncThread;

  public TdbTcProvider() {
  }

  TdbTcProvider(File directory) {
    dataPathString = directory.getAbsolutePath();
    loadMGraphs();
    loadGraphs();
  }

  public void activate(ComponentContext cCtx) {
    log.info("Activating TDB provider");
    if (cCtx != null) {
      weight = (Integer) cCtx.getProperties().get("weight");
      dataPathString = cCtx.getBundleContext().
          getDataFile(DATA_PATH_NAME).getAbsolutePath();
      syncInterval = Integer.parseInt(cCtx.getProperties().get(SYNC_INTERVAL).toString());
    }
    loadMGraphs();
    loadGraphs();
    syncThread = new SyncThread();
    syncThread.start();
  }

  public void deactivate(ComponentContext cCtx) {
    syncThread.requestStop();
    syncThread = null;
    for (com.hp.hpl.jena.graph.Graph jenaGraph : dir2JenaGraphMap.values()) {
      jenaGraph.close();
    }
    synchronized(dir2Dataset) {
      for (Dataset dataset : dir2Dataset.values()) {
        dataset.close();
      }
    }
  }

  @Override
  public int getWeight() {
    return weight;
  }

  @Override
  public Graph getGraph(UriRef name) throws NoSuchEntityException {
    if (!graphMap.containsKey(name)) {
      throw new NoSuchEntityException(name);
    }
    return graphMap.get(name);
  }

  @Override
  public synchronized MGraph getMGraph(UriRef name) throws NoSuchEntityException {
    if (!mGraphMap.containsKey(name)) {
      throw new NoSuchEntityException(name);
    }
    return mGraphMap.get(name);
  }

  @Override
  public TripleCollection getTriples(UriRef name) throws NoSuchEntityException {
    try {
      return getMGraph(name);
    } catch (NoSuchEntityException e) {
      return getGraph(name);
    }
  }

  @Override
  public synchronized MGraph createMGraph(UriRef name)
      throws UnsupportedOperationException, EntityAlreadyExistsException {
    File tcDir = getMGraphDir(name);
    if (tcDir.exists()) {
      throw new EntityAlreadyExistsException(name);
    }
    tcDir.mkdirs();
    File otimizationIndicator = new File(tcDir, "fixed.opt");
    try {
      otimizationIndicator.createNewFile();
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    }
    LockableMGraph result = new LockableMGraphWrapper(getMGraph(tcDir));
    mGraphMap.put(name, result);
    return result;
  }

  @Override
  public Graph createGraph(UriRef name, TripleCollection triples)
      throws UnsupportedOperationException, EntityAlreadyExistsException {
    File tcDir = getGraphDir(name);
    if (tcDir.exists()) {
      throw new EntityAlreadyExistsException(name);
    }

    if (triples == null) {
      triples = new SimpleMGraph();
    }
    tcDir.mkdirs();
    File otimizationIndicator = new File(tcDir, "fixed.opt");
    try {
      otimizationIndicator.createNewFile();
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    }
    MGraph mGraph = getMGraph(tcDir);
    mGraph.addAll(triples);
    Graph result = mGraph.getGraph();
   
    graphMap.put(name, result);
    return result;
  }

  @Override
  public void deleteTripleCollection(UriRef name)
      throws UnsupportedOperationException, NoSuchEntityException,
      EntityUndeletableException {
    if (deleteTcDir(getGraphDir(name))) {
      graphMap.remove(name);
      return;
    }
    if (deleteTcDir(getMGraphDir(name))) {
      mGraphMap.remove(name);
      return;
    }
    throw new NoSuchEntityException(name);
  }

  private boolean deleteTcDir(File tcDir) {
    if (tcDir.exists()) {
      dir2JenaGraphMap.get(tcDir).close();
      dir2JenaGraphMap.remove(tcDir);
      synchronized(dir2Dataset) {
        dir2Dataset.get(tcDir).close();
        dir2Dataset.remove(tcDir);
      }
      delete(tcDir);
      return true;
    }
    return false;
  }
 
  /**
   * Cleans the content of the specified directory recursively.
   * @param dir  Abstract path denoting the directory to clean.
   */
  private static void cleanDirectory(File dir) {
    File[] files = dir.listFiles();
    if (files != null && files.length > 0) {
      for (File file : files) {
        delete(file);
      }
    }
  }

  /**
   * Deletes the specified file or directory.
   * @param file  Abstract path denoting the file or directory to clean.
   */
  protected static void delete(File file) {
    if (file.isDirectory()) {
      cleanDirectory(file);
    }
    file.delete();
  }

  @Override
  public Set<UriRef> getNames(Graph graph) {
    //this could be done more efficiently with an index, could be done with
    //a MultiBidiMap (BidiMap allowing multiple keys for the same value)
    Set<UriRef> result = new HashSet<UriRef>();
    for (UriRef name : listGraphs()) {
      if (getGraph(name).equals(graph)) {
        result.add(name);
      }
    }
    return result;
  }

  @Override
  public Set<UriRef> listTripleCollections() {
    Set<UriRef> result = new HashSet<UriRef>();
    result.addAll(listGraphs());
    result.addAll(listMGraphs());
    return result;
  }

  @Override
  public Set<UriRef> listGraphs() {
    return graphMap.keySet();
  }

  @Override
  public Set<UriRef> listMGraphs() {
    return mGraphMap.keySet();
  }

  private Graph getGraph(File tcDir) {
    return getMGraph(tcDir).getGraph();
  }

  private File getGraphDir(UriRef name) {
    File base = new File(dataPathString);
    return getTcDir(new File(base, "graph"), name);
  }

  private MGraph getMGraph(File tcDir) {
    Dataset dataset = TDBFactory.createDataset(tcDir.getAbsolutePath());
    Model model = dataset.getDefaultModel();
    //Model model = TDBFactory.createModel(tcDir.getAbsolutePath());
    final com.hp.hpl.jena.graph.Graph jenaGraph = model.getGraph();
    dir2JenaGraphMap.put(tcDir, jenaGraph);
    synchronized(dir2Dataset) {
      dir2Dataset.put(tcDir, dataset);
    }
    return new PrivilegedMGraphWrapper(new JenaGraphAdaptor(jenaGraph));
  }

  private File getMGraphDir(UriRef name) {
    File base = new File(dataPathString);
    return getTcDir(new File(base, "mgraph"), name);
  }

  private File getTcDir(File directory, UriRef name) {
    try {
      String subDirName = URLEncoder.encode(name.getUnicodeString(), "utf-8");
      return new File(directory, subDirName);
    } catch (UnsupportedEncodingException ex) {
      throw new RuntimeException("utf-8 not supported", ex);
    }
  }


  private void loadGraphs() {
    File graphsDir = new File(new File(dataPathString), "graph");
    if (graphsDir.exists()) {
      for (String graphDirName : graphsDir.list()) {
        try {
          UriRef uri = new UriRef(URLDecoder.decode(graphDirName, "utf-8"));
          log.info("loading: "+graphDirName);
          graphMap.put(uri, getGraph(new File(graphsDir, graphDirName)));
        } catch (UnsupportedEncodingException ex) {
          throw new RuntimeException("utf-8 not supported", ex);
        } catch (Exception e) {
          log.error("Could not load tdb graph in "+graphDirName, e);
        }
      }
    }
  }

  private void loadMGraphs() {
    File mGraphsDir = new File(new File(dataPathString), "mgraph");
    if (mGraphsDir.exists()) {
      for (String mGraphDirName : mGraphsDir.list()) {
        try {
          UriRef uri = new UriRef(URLDecoder.decode(mGraphDirName, "utf-8"));
          log.info("loading: "+mGraphDirName);
          mGraphMap.put(uri, new LockableMGraphWrapper(getMGraph(new File(mGraphsDir, mGraphDirName))));
        } catch (UnsupportedEncodingException ex) {
          throw new RuntimeException("utf-8 not supported", ex);
        } catch (Exception e) {
          log.error("Could not load tdb graph in "+mGraphDirName, e);
        }
      }
    }
  }
 
  public void syncWithFileSystem() {
    synchronized(dir2Dataset) {
      for (Dataset dataset : dir2Dataset.values()) {
        TDB.sync(dataset);
      }
    }
  }
}
TOP

Related Classes of org.apache.clerezza.rdf.jena.tdb.storage.TdbTcProvider$SyncThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.