opencog/relex — pull request #118 by ceefour (2014-07-12 13:45:07+00:00)
Title: Multi-threaded NIO socket-based parse server using Netty

Multi-threaded [NIO socket-based](https://en.wikipedia.org/wiki/Non-blocking_I/O_(Java)) parse server using [Netty](http://netty.io/)

It will listen for plain-text input sentences on port 4444, and will generate OpenCog output.

It is intended that this server be used by OpenCog agents to process text; the text is sent from OpenCog to this server, and the returned parses are then further processed by OpenCog.

Alternative for https://github.com/opencog/relex/pull/116#issuecomment-48801827

Summary of features:

1. Multi-threaded. TODO: Hendy's not sure yet whether `RelationExtractor` and others are thread-safe.
If not then an instance should be created per channel.
2. Faster and better CPU utilization, probably due to multi-threading (assuming all used objects already thread-safe). Hendy's naive 1000 sentence-test finished 22.2s, it's ~60% faster than 35.6s using Java5 Server.

Java5 Server:
![relexoldtime](https://cloud.githubusercontent.com/assets/24123/3561536/ccc2218c-09c9-11e4-95dc-b82b8477cc5a.png)

Server2:
![relexnewtime](https://cloud.githubusercontent.com/assets/24123/3561537/d0e39e80-09c9-11e4-9a6d-a7583bff296d.png)

3. Input is decoded using `UTF-8` encoding, as well as output to same channel or to Cog server.

![arabic](https://cloud.githubusercontent.com/assets/24123/3561550/5a7fda6e-09ca-11e4-955d-baa5db46f157.png)

4. Logs via SLF4J API to Logback. Setting verbose simply `ch.qos.logback.classic.Logger.setLevel(Level)` to `Level.DEBUG`.
5. Can be embedded, construct with `Server2(int, URI, int, boolean, boolean, boolean, boolean, boolean, String)` then call `run()`.
6. No `System.gc()` call. If still leaks, then the cause is probably in other parts of RelEx.
7. JRebel (optional) can be used for rapid development at runtime without restarting server.
8. Not that big ~380 LoC, still in the range of Java5 Server's.
9. Clear separation of responsibility, should be doable to refactor this to implement `PlainTextServer` if desired.

Build with Maven to use this, it's ignored when building in Ant. Scripts:

1. `target/relex/bin/relexd`, which runs `java relex.Server2 ...`
2. `target/relex/bin/relexd-relex`, which runs `java relex.Server2 --relex --anaphora ...`
3. `target/relex/bin/relexd-link`, which runs `relex.Server2 --link --relex --anaphora --verbose ...`
4. `target/relex/bin/relexd-logic`, which runs `java relex.Server2 --logic ...`

I hope the class structure is easy to learn:

1. `SentenceDecoder` decodes lines to sentences using `DocSplitter` for `free_text` mode.
2. `SentenceInputHandler` calls `processSentence(Object, String, PrintWriter)` then sends output to Cog server or same channel.
3. `parseArgs(String [])` parses command line arguments using [JCommander](http://beust.com/jcommander/) (similar to `getopt` but better API).
4. `run()` configures `RelationExtractor`, `OpenCogScheme`, and `LogicView` then `startServer()`.
5. `startServer()` starts a Netty client (if OpenCog host is given) then starts the RelEx Netty server.
6. `processSentence(Object, String, PrintWriter)` passes the sentence to `RelationExtractor` then prints the output to provided `PrintWriter`.

@dhart Please let me know if you find bugs.