Skip to content

DavePearce/JBuildStore

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Table of Contents
  1. Overview
  2. Content
    1. Sources
    2. Queries
    3. Sinks
    4. Roots
  3. Ledgers

Overview

JBuildStore is a library for implementing key-value stores that supports specific features for building compilers. Content is stored in a binary form, and is read into corresponding in-memory structures (e.g. an Abstract Syntax Tree). For example, content might be stored on disk or in an archive file and might also be versioned (or not). Roughly speaking a content source provides a way to read content, whilst a sink provides a way of writing content. Furthermore, content can be stored in journal-like structures called ledgers.

Content

All managed content implements the Content interface, and is associated with an instance of Content.Type. In particular, given an InputStream and a Content.Type one can attempt to instantiate an instance of Content (though this might fail in the InputStream is corrupted, etc). The following illustrates a minimal example:

interface Shape extends Content {}

class Point implements Shape {
  public static Content.Type<Point> ContentType = new Content.Type<Point>() {

    @Override
    public Point read(InputStream input) throws IOException {
      try (ObjectInputStream ois = new ObjectInputStream(input)) {
        int x = ois.readInt();
        int y = ois.readInt();
        return new Point(x, y);
      }
    }

    @Override
    public void write(OutputStream output, Point value) throws IOException {
      try (ObjectOutputStream ois = new ObjectOutputStream(output)) {
        ois.writeInt(value.x);
        ois.writeInt(value.y);
      }
    }

    @Override
    public String suffix() {
     return "point";
    }
  };

  public final int x;
  public final int y;

  public Point(int x, int y) {
    this.x = x;
    this.y = y;
  }

  @Override
  public Type<Point> contentType() {
    return ContentType;
  }
}

This defines a class of structured content, Point, associated with Point.ContentType. Through Point.ContentType we can serialise / deserialise our structured content (e.g. read it from disk into an instance of Point, or write an instance of Point back into its binary form).

Sources

A content source is an instance of Content.Source<K>, and provides an API for reading structured content out of a store. Content sources (and sinks) are hierarchically structured into a tree-like organisation (roughly similar to that of a file system). The following illustrates a simple method for reading a Point out of an arbitrary source:

Point read(Source<String>> source) throws IOException {
    Key<String, Point> k = new Key<>("test", Point.ContentType);
    return source.get(k);
}

This reads an instance of Point from the key test in the given source.

Queries

Sources can be queried arbitrarily using instances of Predicate as follows:

List<Point> select(Source<String> source, Predicate<Key<String,?>> query) throws IOException {
    return source.getAll(query);
}

This method returns a list of all matching Point instances in the given source.

Sinks

A content sink is an instance of Content.Sink<K,V>, and provides an API for writing structured content into the store. The following illustrates writing a piece of structured content into the store:

void write(Sink<String,Shape> sink, Point pt) throws IOException {
    sink.put("test", pt);
}

Again, this writes our Point instance into the store. Observe that if Point were mutable, then any changes to point after the write would not be visible in the store. Generally speaking, we encourage the use of immutable classes for implementing structure content.

Stores

A content store is an instance of Content.Store<K,V> which means it is both a Content.Source<K,V> and Content.Sink<K,V>. In other words, its an end-point for our structured content (such as a filesystem or database). Perhaps the simplest example of a root is DirectoryStore which allows one to treat a file system directory as a store for structured content.

Another interesting example of a store is a ZipFile which is both an item of structure content, and a store for the structured content it contains.

Ledgers

A content ledger is an instance of Content.Ledger. Unlike a Content.Source a ledger provides a versioned history of our content (roughly similar to the idea of a journaling filesystem). This means, for example, we can compare content between versions to see what has changed. This is useful, for example, in the context of incremental compilers where it provides a key piece of the underlying functionality.

About

A compiler framework

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages