Skip to content

Commit

Permalink
Introduce protocol documentation
Browse files Browse the repository at this point in the history
- Also resolve minor bugs found while testing docs
- Binary examples of all primitive values, handshake and chunking
- Examples section with human-readable and binary representations of
  common scenarios
  • Loading branch information
jakewins committed Apr 23, 2015
1 parent 6e8796c commit 262cc69
Show file tree
Hide file tree
Showing 75 changed files with 4,181 additions and 641 deletions.
Expand Up @@ -294,6 +294,7 @@ private boolean dumpRecord( STORE store, int size, StoreChannel fileChannel, Byt
out.print( record ); out.print( record );
buffer.clear(); buffer.clear();
fileChannel.read( buffer, id * size ); fileChannel.read( buffer, id * size );
buffer.flip();
dumpHex( record, buffer, id, size ); dumpHex( record, buffer, id, size );
} }


Expand All @@ -320,7 +321,7 @@ else if ( allZero( buffer ) )


private boolean allZero( ByteBuffer buffer ) private boolean allZero( ByteBuffer buffer )
{ {
for ( int i = 0; i < buffer.position(); i++ ) for ( int i = 0; i < buffer.limit(); i++ )
{ {
if ( buffer.get( i ) != 0 ) if ( buffer.get( i ) != 0 )
{ {
Expand Down
Expand Up @@ -214,14 +214,14 @@ public HexPrinter append( ByteBuffer bytes, int offset, int length )
} }


/** /**
* Append the bytes in the byte buffer, starting from position 0, ending at the buffer's current position, * Append the bytes in the byte buffer, from its current position to its limit into print stream. This operation
* into print stream * will not move the buffers current position.
* @param bytes * @param bytes
* @return * @return
*/ */
public HexPrinter append( ByteBuffer bytes ) public HexPrinter append( ByteBuffer bytes )
{ {
return append( bytes, 0, bytes.position() ); return append( bytes, bytes.position(), bytes.remaining() );
} }


/** /**
Expand Down Expand Up @@ -307,7 +307,7 @@ public static String hex( ByteBuffer bytes, int offset, int length )
*/ */
public static String hex( ByteBuffer bytes ) public static String hex( ByteBuffer bytes )
{ {
return hex( bytes, 0, bytes.position() ); return hex( bytes, bytes.position(), bytes.limit() );
} }


/** /**
Expand Down
Expand Up @@ -19,12 +19,12 @@
*/ */
package org.neo4j.kernel.impl.store; package org.neo4j.kernel.impl.store;


import org.junit.Test;

import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;


import org.junit.Test;

import org.neo4j.kernel.impl.store.record.AbstractBaseRecord; import org.neo4j.kernel.impl.store.record.AbstractBaseRecord;


import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
Expand All @@ -44,6 +44,8 @@ public void dumpStoreShouldPrintBufferWithContent() throws Exception
{ {
buffer.put( i ); buffer.put( i );
} }
buffer.flip();

AbstractBaseRecord record = mock( AbstractBaseRecord.class ); AbstractBaseRecord record = mock( AbstractBaseRecord.class );


// When // When
Expand Down
Expand Up @@ -19,14 +19,13 @@
*/ */
package org.neo4j.kernel.impl.util; package org.neo4j.kernel.impl.util;


import org.junit.Test;

import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;


import org.junit.Test;

import static java.lang.String.format; import static java.lang.String.format;

import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;


public class HexPrinterTest public class HexPrinterTest
Expand Down Expand Up @@ -165,12 +164,18 @@ public void shouldPrintPartOfByteBuffer() throws Exception
@Test @Test
public void shouldOnlyPrintBytesWrittenToBuffer() throws Exception public void shouldOnlyPrintBytesWrittenToBuffer() throws Exception
{ {
// Given
ByteBuffer bytes = ByteBuffer.allocate( 1024 ); ByteBuffer bytes = ByteBuffer.allocate( 1024 );
for ( byte value = 0; value < 10; value++ ) for ( byte value = 0; value < 10; value++ )
{ {
bytes.put( value ); bytes.put( value );
} }
bytes.flip();

// When
String hexString = HexPrinter.hex( bytes ); String hexString = HexPrinter.hex( bytes );

// Then
assertEquals( format( "00 01 02 03 04 05 06 07 08 09" ), hexString ); assertEquals( format( "00 01 02 03 04 05 06 07 08 09" ), hexString );
} }
} }
24 changes: 12 additions & 12 deletions community/ndp/kernelextension/pom.xml
Expand Up @@ -29,17 +29,17 @@
<name>GNU General Public License, Version 3</name> <name>GNU General Public License, Version 3</name>
<url>http://www.gnu.org/licenses/gpl-3.0-standalone.html</url> <url>http://www.gnu.org/licenses/gpl-3.0-standalone.html</url>
<comments>The software ("Software") developed and owned by Network Engine for <comments>The software ("Software") developed and owned by Network Engine for
Objects in Lund AB (referred to in this notice as "Neo Technology") is Objects in Lund AB (referred to in this notice as "Neo Technology") is
licensed under the GNU GENERAL PUBLIC LICENSE Version 3 to all third licensed under the GNU GENERAL PUBLIC LICENSE Version 3 to all third
parties and that license is included below. parties and that license is included below.


However, if you have executed an End User Software License and Services However, if you have executed an End User Software License and Services
Agreement or an OEM Software License and Support Services Agreement, or Agreement or an OEM Software License and Support Services Agreement, or
another commercial license agreement with Neo Technology or one of its another commercial license agreement with Neo Technology or one of its
affiliates (each, a "Commercial Agreement"), the terms of the license in affiliates (each, a "Commercial Agreement"), the terms of the license in
such Commercial Agreement will supersede the GNU GENERAL PUBLIC LICENSE such Commercial Agreement will supersede the GNU GENERAL PUBLIC LICENSE
Version 3 and you may use the Software solely pursuant to the terms of Version 3 and you may use the Software solely pursuant to the terms of
the relevant Commercial Agreement. the relevant Commercial Agreement.
</comments> </comments>
</license> </license>
</licenses> </licenses>
Expand Down Expand Up @@ -113,8 +113,8 @@ the relevant Commercial Agreement.
<!-- Disable the ComponentVersion generation --> <!-- Disable the ComponentVersion generation -->
<plugin> <plugin>
<artifactId>maven-antrun-plugin</artifactId> <artifactId>maven-antrun-plugin</artifactId>
<executions> <executions>
<execution> <execution>
<id>generate-version</id> <id>generate-version</id>
<phase>none</phase> <phase>none</phase>
</execution> </execution>
Expand Down
Expand Up @@ -47,19 +47,21 @@ public class NDPKernelExtension extends KernelExtensionFactory<NDPKernelExtensio
{ {
public static class Settings public static class Settings
{ {
@Description( "Max time that sessions can be idle, after this interval a session will get closed." ) @Description("Max time that sessions can be idle, after this interval a session will get closed.")
public static final Setting<Boolean> ndp_enabled = setting("experimental.ndp.enabled", BOOLEAN, public static final Setting<Boolean> ndp_enabled = setting( "experimental.ndp.enabled", BOOLEAN,
"false" ); "false" );


@Description( "Host and port for the Neo4j Data Protocol http transport" ) @Description("Host and port for the Neo4j Data Protocol http transport")
public static final Setting<HostnamePort> ndp_address = public static final Setting<HostnamePort> ndp_address =
setting("dbms.ndp.address", HOSTNAME_PORT, "localhost:7687" ); setting( "dbms.ndp.address", HOSTNAME_PORT, "localhost:7687" );
} }


public interface Dependencies public interface Dependencies
{ {
LogService logService(); LogService logService();

Config config(); Config config();

GraphDatabaseService db(); GraphDatabaseService db();
} }


Expand All @@ -78,7 +80,7 @@ public Lifecycle newKernelExtension( Dependencies dependencies ) throws Throwabl
final HostnamePort address = config.get( Settings.ndp_address ); final HostnamePort address = config.get( Settings.ndp_address );
final LifeSupport life = new LifeSupport(); final LifeSupport life = new LifeSupport();


if(config.get( Settings.ndp_enabled )) if ( config.get( Settings.ndp_enabled ) )
{ {
final Sessions env = life.add( new StandardSessions( api, log ) ); final Sessions env = life.add( new StandardSessions( api, log ) );


Expand Down
Expand Up @@ -51,7 +51,7 @@ public void shouldLaunchNDP() throws Throwable
.newGraphDatabase(); .newGraphDatabase();


// Then // Then
assertEventuallyServerResponds("localhost", 7687); assertEventuallyServerResponds( "localhost", 7687 );
} }


@Test @Test
Expand All @@ -65,25 +65,25 @@ public void shouldBeAbleToSpecifyHostAndPort() throws Throwable
.newGraphDatabase(); .newGraphDatabase();


// Then // Then
assertEventuallyServerResponds("localhost", 8776); assertEventuallyServerResponds( "localhost", 8776 );
} }


private void assertEventuallyServerResponds(String host, int port) throws IOException, InterruptedException private void assertEventuallyServerResponds( String host, int port ) throws IOException, InterruptedException
{ {
long timeout = System.currentTimeMillis() + 1000 * 30; long timeout = System.currentTimeMillis() + 1000 * 30;
for(;;) for (; ; )
{ {
if ( serverResponds(host, port) ) if ( serverResponds( host, port ) )
{ {
return; return;
} }
else else
{ {
Thread.sleep(100); Thread.sleep( 100 );
} }


// Make sure process still is alive // Make sure process still is alive
if(System.currentTimeMillis() > timeout) if ( System.currentTimeMillis() > timeout )
{ {
throw new RuntimeException( "Waited for 30 seconds for server to respond to HTTP calls, " + throw new RuntimeException( "Waited for 30 seconds for server to respond to HTTP calls, " +
"but no response, timing out to avoid blocking forever." ); "but no response, timing out to avoid blocking forever." );
Expand All @@ -95,23 +95,23 @@ private boolean serverResponds( String host, int port ) throws IOException, Inte
{ {
try try
{ {
try(Socket socket = new Socket()) try ( Socket socket = new Socket() )
{ {
// Ok, we can connect - can we perform the version handshake? // Ok, we can connect - can we perform the version handshake?
socket.connect( new InetSocketAddress( host, port ) ); socket.connect( new InetSocketAddress( host, port ) );
OutputStream out = socket.getOutputStream(); OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream(); InputStream in = socket.getInputStream();


// Hard-coded handshake, a general "test client" would be useful further on. // Hard-coded handshake, a general "test client" would be useful further on.
out.write( new byte[]{ 0,0,0,1, 0,0,0,0, 0,0,0,0, 0,0,0,0 } ); out.write( new byte[]{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} );


byte[] accepted = new byte[4]; byte[] accepted = new byte[4];
in.read( accepted ); in.read( accepted );


return Arrays.equals( accepted, new byte[]{0,0,0,1} ); return Arrays.equals( accepted, new byte[]{0, 0, 0, 1} );
} }
} }
catch(ConnectException e) catch ( ConnectException e )
{ {
return false; return false;
} }
Expand All @@ -120,7 +120,7 @@ private boolean serverResponds( String host, int port ) throws IOException, Inte
@After @After
public void cleanup() public void cleanup()
{ {
if(db != null) if ( db != null )
{ {
db.shutdown(); db.shutdown();
} }
Expand Down
48 changes: 43 additions & 5 deletions community/ndp/messaging-v1/pom.xml
Expand Up @@ -49,19 +49,30 @@
<dependency> <dependency>
<groupId>org.hamcrest</groupId> <groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId> <artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId> <artifactId>mockito-all</artifactId>
<version>1.10.19</version> <scope>test</scope>
</dependency>

<!-- Used to validate docs -->
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.8.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
Expand All @@ -70,7 +81,6 @@
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration> <configuration>
<source>1.7</source> <source>1.7</source>
<target>1.7</target> <target>1.7</target>
Expand All @@ -79,7 +89,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
Expand All @@ -98,6 +107,35 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>

<!-- Temporary asciidoc generation, pending plugging into manual. -->
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.2</version>
<executions>
<execution>
<id>generate-compliance-manual</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
</configuration>
</execution>
</executions>
<configuration>
<sourceDirectory>../v1-docs/src/docs/dev</sourceDirectory>
<outputDirectory>${basedir}/target/messaging-manual/html</outputDirectory>
<backend>html</backend>
<attributes>
<toc/>
<source-highlighter>coderay</source-highlighter>
</attributes>
</configuration>
</plugin>

</plugins> </plugins>
</build> </build>


Expand Down
Expand Up @@ -36,6 +36,7 @@
import org.neo4j.graphdb.PropertyContainer; import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.Relationship;
import org.neo4j.helpers.collection.Iterables; import org.neo4j.helpers.collection.Iterables;
import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.ndp.messaging.v1.infrastructure.ValueNode; import org.neo4j.ndp.messaging.v1.infrastructure.ValueNode;
import org.neo4j.ndp.messaging.v1.infrastructure.ValuePath; import org.neo4j.ndp.messaging.v1.infrastructure.ValuePath;
import org.neo4j.ndp.messaging.v1.infrastructure.ValueRelationship; import org.neo4j.ndp.messaging.v1.infrastructure.ValueRelationship;
Expand Down Expand Up @@ -114,8 +115,13 @@ public void run()
*/ */
public Writer( PackOutput output, Runnable onMessageComplete ) public Writer( PackOutput output, Runnable onMessageComplete )
{ {
this( new PackStream.Packer( output ), onMessageComplete );
}

public Writer( PackStream.Packer packer, Runnable onMessageComplete )
{
this.packer = packer;
this.onMessageComplete = onMessageComplete; this.onMessageComplete = onMessageComplete;
packer = new PackStream.Packer( output );
} }


@Override @Override
Expand Down Expand Up @@ -480,8 +486,13 @@ private <E extends Exception> void unpackFailureMessage( MessageHandler<E> outpu
{ {
Map<String,Object> map = unpackRawMap(); Map<String,Object> map = unpackRawMap();


String codeStr = (String) map.get( "code" ); String codeStr = map.containsKey( "code" ) ?
String msg = (String) map.get( "message" ); (String) map.get( "code" ) :
Status.General.UnknownFailure.name();

String msg = map.containsKey( "message" ) ?
(String) map.get( "message" ) :
"<No message supplied>";


output.handleFailureMessage( new Neo4jError( codeFromString( codeStr ), msg ) ); output.handleFailureMessage( new Neo4jError( codeFromString( codeStr ), msg ) );
} }
Expand Down

0 comments on commit 262cc69

Please sign in to comment.