Skip to content

teragrep/rlp_03

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Java RELP Server Library (rlp_03)

rlp_03 implements RELP server in Java

License

AGPLv3 with additional permissions granted in the license.

Features

Current

  • Fast (~100 000 transactions in a second per thread)

  • Secure (TLS)

Usage

Setting dependencies

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <dependencies>
        <!-- this library -->
        <dependency>
            <groupId>com.teragrep</groupId>
            <artifactId>rlp_03</artifactId>
            <version>${see_latest_at_github}</version>
        </dependency>
    </dependencies>
</project>
Note
See rlp_01 for relp relpClient
Note
See rlo_06 for syslog decoding

Examples

Dependencies for examples

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <dependencies>
        <!-- this library -->
        <dependency>
            <groupId>com.teragrep</groupId>
            <artifactId>rlp_03</artifactId>
            <version>${see_latest_at_github}</version>
        </dependency>
        <!-- rlp_01 for relp-relpClient -->
        <dependency>
            <groupId>com.teragrep</groupId>
            <artifactId>rlp_01</artifactId>
            <version>${see_latest_at_github}</version>
        </dependency>
    </dependencies>
</project>

Server with shared handler for all connections. See ExampleRelpClient.java for relpClient.

package com.teragrep.rlp_03.readme;

import com.teragrep.net_01.eventloop.EventLoop;
import com.teragrep.net_01.eventloop.EventLoopFactory;
import com.teragrep.rlp_03.frame.delegate.DefaultFrameDelegate;
import com.teragrep.rlp_03.frame.delegate.FrameContext;
import com.teragrep.rlp_03.frame.delegate.FrameDelegate;
import com.teragrep.net_01.server.ServerFactory;
import com.teragrep.net_01.channel.socket.PlainFactory;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * For use cases in the README.adoc
 */
public class ReadmeTest {

    @Test
    public void testServerSetup() {
        int listenPort = 10601;
        int threads = 1; // processing threads shared across the connections
        ExecutorService executorService = Executors.newFixedThreadPool(threads);

        /*
         * System.out.println is used to print the frame payload
         */
        Consumer<FrameContext> syslogConsumer = new Consumer<FrameContext>() {

            // NOTE: synchronized because frameDelegateSupplier returns this instance for all the parallel connections
            @Override
            public synchronized void accept(FrameContext frameContext) {
                System.out.println(frameContext.relpFrame().payload().toString());
            }
        };

        /*
         * New instance of the frameDelegate is provided for every connection
         */
        Supplier<FrameDelegate> frameDelegateSupplier = new Supplier<FrameDelegate>() {

            @Override
            public FrameDelegate get() {
                System.out.println("Providing frameDelegate for a connection");
                return new DefaultFrameDelegate(syslogConsumer);
            }
        };

        /*
         * EventLoop is used to notice any events from the connections
         */
        EventLoopFactory eventLoopFactory = new EventLoopFactory();
        EventLoop eventLoop;
        try {
            eventLoop = eventLoopFactory.create();
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }

        Thread eventLoopThread = new Thread(eventLoop);
        /*
         * eventLoopThread must run, otherwise nothing will be processed
         */
        eventLoopThread.start();

        /*
         * ServerFactory is used to create server instances
         */
        ServerFactory serverFactory = new ServerFactory(
                eventLoop,
                executorService,
                new PlainFactory(),
                new FrameDelegationClockFactory(frameDelegateSupplier)
        );

        try {
            serverFactory.create(listenPort);
            System.out.println("server started at port <" + listenPort + ">");
        }
        catch (IOException ioException) {
            throw new UncheckedIOException(ioException);
        }

        /*
         * Send Hello, World! via rlp_01
         */
        new ExampleRelpClient(listenPort).send("Hello, World!");
        new ExampleRelpClient(listenPort).send("Hello, World again!");

        /*
         * Stop eventLoop
         */
        eventLoop.stop();

        /*
         * Wait for stop to complete
         */
        try {
            eventLoopThread.join();
        }
        catch (InterruptedException interruptedException) {
            throw new RuntimeException(interruptedException);
        }
        System.out.println("server stopped at port <" + listenPort + ">");

        executorService.shutdown();
    }
}

If a separate handler is required for each connection which doesn’t need to be a thread-safe, create a new FrameDelegate in the Supplier<FrameDelegate>

        Supplier<FrameDelegate> frameDelegateSupplier = () -> {
            System.out.println("Providing frameDelegate for a connection");
            return new DefaultFrameDelegate(frameContext -> System.out.println(frameContext.relpFrame().payload().toString()));
        };

If a deferred handler is required for command processing, pass custom RelpEvent implementation to DefaultFrameDelegate via the Map<String, RelpEvent> constructor. See ReadmeDeferredTest.java for an example.

Contributing

You can involve yourself with our project by opening an issue or submitting a pull request.

Contribution requirements:

  1. All changes must be accompanied by a new or changed test. If you think testing is not required in your pull request, include a sufficient explanation as why you think so.

  2. Security checks must pass

  3. Pull requests must align with the principles and values of extreme programming.

  4. Pull requests must follow the principles of Object Thinking and Elegant Objects (EO).

Read more in our Contributing Guideline.

Contributor License Agreement

Contributors must sign Teragrep Contributor License Agreement before a pull request is accepted to organization’s repositories.

You need to submit the CLA only once. After submitting the CLA you can contribute to all Teragrep’s repositories.