Skip to content

Commit

Permalink
Initial commit from http://www.mcobject.com/perst
Browse files Browse the repository at this point in the history
  • Loading branch information
The-Alchemist authored and tsl-karlp committed Mar 8, 2018
0 parents commit 3632b67
Show file tree
Hide file tree
Showing 1,617 changed files with 383,630 additions and 0 deletions.
858 changes: 858 additions & 0 deletions CHANGES

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions assoc/build.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<!--
************************************************************
targets: makejar - compile & jar
compiletests - compile test
************************************************************
-->


<project name="AssocDB" default="all" basedir=".">
<property name="lucene.jar" value="c:/lucene-2.4.1/lucene-core-2.4.1.jar" />
<target name="makedocs">
<javadoc
sourcepath="src"
destdir="doc"
nodeprecated="true"
nodeprecatedlist="true"
public="true"
packagenames="org.garret.perst.assoc">
<classpath location="../lib/perst.jar" />
<classpath location="${lucene.jar}" />
</javadoc>
</target>


<target name="init" depends="clear" >
<mkdir dir="classes"/>
</target>


<target name="clear">
<delete dir="classes" />
</target>

<target name="compile" depends="init">
<javac srcdir="src" source="1.5" destdir="classes" deprecation="off" debug="on" optimize="on">
<classpath location="../lib/perst.jar" />
<classpath location="${lucene.jar}" />
</javac>
</target>


<target name="compiletests" depends="compile" >
<delete dir="classes/tst" />
<mkdir dir="classes/tst" />

<javac srcdir="tst" source="1.5" destdir="classes/tst" deprecation="off" debug="on" optimize="on">
<classpath location="../lib/perst.jar" />
<classpath location="../lib/assocdb.jar" />
</javac>
</target>


<target name="makejar" depends="compile">
<jar jarfile="../lib/assocdb.jar" basedir="classes" includes="**" />
</target>


<target name="all" depends="makejar,makedocs,compiletests">
</target>
</project>

171 changes: 171 additions & 0 deletions assoc/doc/assocdb.html

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions assoc/src/compile.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
javac -classpath ../../lib/perst.jar -g org/garret/perst/assoc/*.java
jar cvf ../../lib/assocdb.jar org/garret/perst/assoc/*.class
1 change: 1 addition & 0 deletions assoc/src/makedoc.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
javadoc -d ../doc -classpath ../../lib/perst.jar -nodeprecated -nosince -public org/garret/perst/assoc/*.java
100 changes: 100 additions & 0 deletions assoc/src/org/garret/perst/assoc/Array.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package org.garret.perst.assoc;

/**
* Helper class for manipulations with arrays
*/
public class Array
{
public static int[] remove(int[] arr, int i) {
return remove(arr, i, 1);
}

public static int[] remove(int[] arr, int i, int count) {
int n = arr.length;
int[] newArr = new int[n-count];
System.arraycopy(arr, 0, newArr, 0, i);
System.arraycopy(arr, i+count, newArr, i, n-i-count);
return newArr;
}

public static String[] remove(String[] arr, int i) {
return remove(arr, i, 1);
}

public static String[] remove(String[] arr, int i, int count) {
int n = arr.length;
String[] newArr = new String[n-count];
System.arraycopy(arr, 0, newArr, 0, i);
System.arraycopy(arr, i+count, newArr, i, n-i-count);
return newArr;
}

public static double[] remove(double[] arr, int i) {
return remove(arr, i, 1);
}

public static double[] remove(double[] arr, int i, int count) {
int n = arr.length;
double[] newArr = new double[n-count];
System.arraycopy(arr, 0, newArr, 0, i);
System.arraycopy(arr, i+count, newArr, i, n-i-count);
return newArr;
}

public static String[] insert(String[] arr, int i, String value) {
int n = arr.length;
String[] newArr = new String[n+1];
System.arraycopy(arr, 0, newArr, 0, i);
newArr[i] = value;
System.arraycopy(arr, i, newArr, i+1, n-i);
return newArr;
}

public static double[] insert(double[] arr, int i, double value) {
int n = arr.length;
double[] newArr = new double[n+1];
System.arraycopy(arr, 0, newArr, 0, i);
newArr[i] = value;
System.arraycopy(arr, i, newArr, i+1, n-i);
return newArr;
}

public static int[] insert(int[] arr, int i, int value) {
return insert(arr, i, value, 1);
}

public static int[] insert(int[] arr, int i, int value, int count) {
int n = arr.length;
int[] newArr = new int[n+count];
System.arraycopy(arr, 0, newArr, 0, i);
for (int j = 0; j < count; j++) {
newArr[i+j] = value;
}
System.arraycopy(arr, i, newArr, i+count, n-i);
return newArr;
}

public static String[] insert(String[] arr, int i, String[] values) {
int n = arr.length;
String[] newArr = new String[n+values.length];
System.arraycopy(arr, 0, newArr, 0, i);
System.arraycopy(values, 0, newArr, i, values.length);
System.arraycopy(arr, i, newArr, i+values.length, n-i);
return newArr;
}

public static double[] insert(double[] arr, int i, double[] values) {
int n = arr.length;
double[] newArr = new double[n+values.length];
System.arraycopy(arr, 0, newArr, 0, i);
System.arraycopy(values, 0, newArr, i, values.length);
System.arraycopy(arr, i, newArr, i+values.length, n-i);
return newArr;
}

public static int[] truncate(int[] arr, int size) {
int[] newArr = new int[size];
System.arraycopy(arr, 0, newArr, 0, size);
return newArr;
}
}
195 changes: 195 additions & 0 deletions assoc/src/org/garret/perst/assoc/AssocDB.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package org.garret.perst.assoc;

import org.garret.perst.*;
import org.garret.perst.fulltext.*;
import java.util.*;

/**
* Main class of this package. Emulation of associative database on top of Perst.
* Strictly speaking AssocDB doesn't implement pure associative data model, although
* it provides some notions of this model (items, links,...)
* The main goal of this database is to efficient storage for object with statically known format and complex relations between
* them. It can be used to store XML data, objects with user-defined fields, ...
* AssocDB allows to fetch all attributes of an objects in one read operation without some kind of joins.
* It automatically index all object attributes to provide fast search (simple query language is used).
* All kind of relation between objects ore provided: one-to-one, one-to-many, many-to-many.
* AssocDB supports small relations (tens of members) as well as very large relation (millions of members).
* Small relations are embedded inside object to reduce storage overhead and their increase access time.
* Large relations are implemented using B-Tree. AssocDB automatically choose proper representation.
* Inverse links are automatically maintained, enforcing consistency of references.
* AssocDB provides MURSIW (multiple readers single writer) isolation model.
* It means that only one transaction can update the database at each moment of time, but multiple transactions
* can concurrently read it.
*/
public class AssocDB
{
/**
* Start read-only transactions. All access to the database (read or write) should be performed within transaction body.
* For write access it is enforced by placing all update methods in ReadWriteTransaction class.
* But for convenience reasons read-only access methods are left in Item class. It is responsibility of programmer to check that
* them are not invoked outside transaction body.
* @return transaction object
*/
public ReadOnlyTransaction startReadOnlyTransaction()
{
root.sharedLock();
return new ReadOnlyTransaction(this);
}

/**
* Start read write transaction
* @return transaction object
*/
public ReadWriteTransaction startReadWriteTransaction()
{
root.exclusiveLock();
return new ReadWriteTransaction(this);
}

/**
* Set threshold for embedded relations.
* AssocDB supports small relations (tens of members) as well as very large relation (millions of members).
* Small relation are embedded inside object to reduce storage overhead and their increase access time.
* Large relations are implemented using B-Tree. AssocDB automatically choose proper representation.
* Initially relations are stored inside object.
* When number of links from an object exceeds this threshold value, AssocDB
* removes links from the object and store it in external B-Tree index.
* @param newTreshold new threshold value
* @return old threshold value
*/
public int setEmbeddedRelationThreshold(int newTreshold) {
int oldThreshold = embeddedRelationThreshold;
embeddedRelationThreshold = newTreshold;
return oldThreshold;
}

/**
* AssocDB constructor. You should open and close storage yourself. You are free to set some storage properties,
* storage listener and use some other storage administrative methods like backup.
* But you should <b>not</b>: <ol>
* <li>specify your own root object for the storage</li>
* <li>use Storage commit or rollback methods directly</li>
* <li>modify storage using Perst classes not belonging to this package</li>
* </ol>
* @param storage opened Perst storage
*/
public AssocDB(Storage storage)
{
this.storage = storage;
embeddedRelationThreshold = DEFAULT_EMBEDDED_RELATION_THRESHOLD;
language = DEFAULT_DOCUMENT_LANGUAGE;
root = (Root)storage.getRoot();
name2id = new HashMap<String,Integer>();
id2name = new HashMap<Integer,String>();
if (root == null) {
root = createRoot();
storage.setRoot(root);
storage.commit();
} else {
root.db = this;
for (Map.Entry<Object,Index<Item>> e : root.attributes.entryIterator()) {
Integer id = new Integer(e.getValue().getOid());
String name = ((String)e.getKey()).intern();
name2id.put(name, id);
id2name.put(id, name);
}
}
}

/**
* Set document's languages: used in full text search index
* @param newLanguage new document's language
* @return previously set language
*/
public String setLanguage(String newLanguage)
{
String prevLanguage = language;
language = newLanguage;
return prevLanguage;
}


void unlock()
{
root.unlock();
}

/**
* Storage root class - used internally by AssocDB.
* You can provide your own root class derived from Root by overriding AssocDB.createRoot method
*/
public static class Root extends PersistentResource
{
protected Index<Item> relations;
protected Index<Index<Item>> attributes;
protected FullTextIndex fullTextIndex;

protected transient AssocDB db;

protected Root() {}

protected Root(AssocDB db) {
super(db.storage);
this.db = db;
attributes = db.storage.<Index<Item>>createIndex(String.class, true);
relations = db.storage.<Item>createIndex(Long.class, false);
fullTextIndex = db.createFullTextIndex();
}
}

/**
* Create index for the particular attribute. Override this method to create some custom indices..
* @param name attribute name
* @param type attribute type
* @return new index
*/
protected Index<Item> createIndex(String name, Class type)
{
return storage.<Item>createThickIndex(type);
}

/**
* Create root object. Override this method to create your own root derived from Root class.
* @return created root
*/
protected Root createRoot()
{
return new Root(this);
}

/**
* Create full text index. Override this method to customize full text search.
* @return created full text index
*/
protected FullTextIndex createFullTextIndex()
{
return storage.createFullTextIndex();
}

/**
* Create item. Override this method to create instance of your own class derived from Item. In such way
* you can statically add some application specific fields to each class.
* @return created full text index
*/
protected Item createItem()
{
return new Item(this);
}

/**
* Default value for embedded relations threshold
*/
public static int DEFAULT_EMBEDDED_RELATION_THRESHOLD = 100;

/**
* Default document's language (used for full text search)
*/
public static String DEFAULT_DOCUMENT_LANGUAGE = "en";

protected Storage storage;
protected Root root;
protected Map<String,Integer> name2id;
protected Map<Integer,String> id2name;
protected int embeddedRelationThreshold;
protected String language;
}
Loading

0 comments on commit 3632b67

Please sign in to comment.