Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
20 changes: 20 additions & 0 deletions .github/workflows/formatting-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Formatting CI

on:
push:
pull_request:

jobs:
formatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "25"
cache: maven

- name: Check formatting
run: mvn spotless:check
23 changes: 23 additions & 0 deletions .github/workflows/test-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Test CI

on:
push:
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "8"
cache: maven

- name: Install test-data tools
run: sudo apt-get update && sudo apt-get install -y wget zstd

- name: Build and test estore
run: mvn -pl estore clean test -Dmaven.compiler.release=8
44 changes: 28 additions & 16 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Untracked Files
*.txt
*.sh
*.so
*.o
*.class
*~
**/poetry.lock

# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Untracked Folder
target
**/__pycache__/
estore/src/main/c/build/
eval/libs/*.jar

# data
data/

# Codegen files
Transformed*Test.java

# Local agent instructions (not committed)
AGENTS.md
.cursor/
.DS_Store
.vscode/settings.json
scratch/
.envrc
.direnv/
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 by the ϵStore team.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
181 changes: 180 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,180 @@
# eStore
# In-memory Object Graph Stores

Implementation of an in-memory object graph store, dubbed ϵStore. Our
key innovation is a storage model -- epsilon store -- that equates an
object on the heap to a node in a graph store. Thus any object on the
heap (without changes) can be a part of one, or multiple, graph
stores, and vice versa, any node in a graph store can be accessed like
any other object on the heap. ϵStore uses a subset of the Cypher query
language to query the graph store. By design, the result of any query
is a table of references to objects on the heap, which users can
manipulate the same way as any other object on the heap in their
programs.

## Examples

1. Capturing a Java object graph and querying it with Cypher-like syntax.

```java
Person charlie = new Person("Charlie", 25);
Person bob = new Person("Bob", 30, charlie);
Person alice = new Person("Alice", 28, bob);

Estore db = new Estore("exampleDb", new EstoreOptions().useUnsafe(false));
db.captureAll(alice);
Table result = db.query("MATCH (p:`org.estore.example.Person`) RETURN p");
```

`alice` is an ordinary Java `Person` object (name `"Alice"`, age 28). Its
`friend` field points to Bob, and Bob's `friend` field points to Charlie, so
the in-memory graph is Alice → Bob → Charlie. `captureAll(alice)` walks that
graph from Alice and stores every reachable object; the query then returns
the captured `Person` nodes.

2. Querying object relationships.

```java
Table friends =
db.query("MATCH (a:`org.estore.example.Person`)-[:friend]->(b:`org.estore.example.Person`) RETURN a, b");
```

This query follows `friend` references between captured `Person` objects and
returns each matched pair.

## Using ϵStore in a Maven Project

After packaging (see the next section), ϵStore can be used in a Maven
project.

The client jar can be added as a dependency to a third-party project
by adding the following to its pom.

```xml
<dependency>
<groupId>org.estore</groupId>
<artifactId>estore</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath><!-- ENTER full path to client jar including jar name --></systemPath>
</dependency>
```

## Getting Started (with Development)

### Prerequisites

The project requires the following dependencies:

- **Java 8**
- **Maven**
- **wget**
- **zstd**
- **tar**
- **gzip**
- **nc** for the quick query test

### Installation

#### 1. Install Dependencies

Run the installation script to automatically install all required dependencies:

```bash
./s install_deps
```

This will check for and install any missing dependencies on your system.

Alternatively, verify your dependencies are correctly installed:

```bash
./s check_deps
```

On Debian/Ubuntu, run `install_deps` with `sudo`. On macOS, use Homebrew
instead (`brew install openjdk@8 maven wget zstd`).

#### 2. Build the Project

Compile the estore project:

```bash
./s compile_estore
```

#### 3. Full Installation

To compile and install the complete project:

```bash
./s install_estore
```

### Running the Project

#### Run Tests

Execute the test suite:

```bash
mvn -pl estore test verify
```

The JaCoCo code coverage report is generated at `estore/target/site/jacoco/index.html`.

#### Run the Application

Start the estore server and query it over the network:

```bash
./s exec_estore
```

In another terminal, send a Cypher-like query over TCP (default port 1234):

```bash
echo 'MATCH (n) RETURN n' | nc localhost 1234
```

Example output:

```
╔═════════╗
║ n ║
╠═════════╣
║ (empty) ║
╚═════════╝
```

Send `q` to stop the server.

#### Format Code

Auto-format Java code according to project standards:

```bash
mvn spotless:apply
mvn verify
```

#### End-to-End Setup

Perform a complete setup with dependency checks and full installation:

```bash
./s end_to_end
```

## Citation

This repository contains code related to the following publication:

```bibtex
@inproceedings{ThimmaiahETAL25eStore,
author = {Thimmaiah, Aditya and Yi, Zijian and Kenis, Joseph and Rossbach, Christopher J. and Gligoric, Milos},
title = {In-memory Object Graph Stores},
booktitle = {European Conference on Object-Oriented Programming},
pages = {30:1--30:30},
year = {2025},
}
```
17 changes: 17 additions & 0 deletions checkstyle.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="tabWidth" value="4"/>
<module name="TreeWalker">
<module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="4"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="8"/>
<property name="arrayInitIndent" value="4"/>
</module>
</module>
</module>
22 changes: 22 additions & 0 deletions descriptor-client.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.1 http://maven.apache.org/xsd/assembly-2.1.1.xsd">
<id>client</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${basedir}/target/classes</directory>
<includes>
<include>estore.properties</include>
<include>org/estore/client/*.class</include>
<include>org/estore/util/*.class</include>
<include>org/estore/bridge/*.class</include>
<include>org/estore/*.class</include>
<include>org/estore/*.class</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
Loading
Loading