Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Dispatcher+Firenio works #87

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions gemini-firenio/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?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/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

<organization>
<name>TechEmpower, Inc.</name>
<url>https://www.techempower.com/</url>
</organization>

<licenses>
<license>
<name>Revised BSD License, 3-clause</name>
<distribution>repo</distribution>
</license>
</licenses>

<parent>
<artifactId>gemini-parent</artifactId>
<groupId>com.techempower</groupId>
<version>4.0.1-SNAPSHOT</version>
</parent>

<artifactId>gemini-firenio</artifactId>
<name>gemini-firenio</name>
<description>
An extension for Firenio-specific functionality with the Gemini web framework.
</description>

<dependencies>
<dependency>
<groupId>com.firenio</groupId>
<artifactId>firenio-all</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</dependency>
<dependency>
<groupId>com.techempower</groupId>
<artifactId>gemini</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.techempower.gemini.firenio;

import com.techempower.gemini.Context;
import com.techempower.gemini.GeminiApplication;
import com.techempower.gemini.Request;
import com.techempower.gemini.context.Attachments;

public class FirenioContext extends Context {

public FirenioContext(Request request, GeminiApplication application)
{
super(application, request);
}

@Override
public Attachments files() {
// FIXME
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
package com.techempower.gemini.firenio;

import com.firenio.Options;
import com.firenio.codec.http11.*;
import com.firenio.collection.ByteTree;
import com.firenio.common.Util;
import com.firenio.component.*;
import com.firenio.log.DebugUtil;
import com.techempower.data.ConnectionMonitor;
import com.techempower.data.ConnectorFactory;
import com.techempower.data.DatabaseAffinity;
import com.techempower.gemini.Context;
import com.techempower.gemini.Dispatcher;
import com.techempower.gemini.GeminiApplication;
import com.techempower.gemini.Request;
import com.techempower.gemini.firenio.lifecycle.InitAnnotationDispatcher;
import com.techempower.gemini.firenio.monitor.FirenioMonitor;
import com.techempower.gemini.firenio.mustache.FirenioMustacheManager;
import com.techempower.gemini.mustache.MustacheManager;
import com.techempower.gemini.firenio.path.AnnotationDispatcher;
import com.techempower.gemini.firenio.session.HttpSessionManager;
import com.techempower.gemini.session.SessionManager;
import com.techempower.util.EnhancedProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;

public abstract class FirenioGeminiApplication
extends GeminiApplication {

protected Logger log = LoggerFactory.getLogger(getClass());

/**
* Overload: Constructs an instance of a subclass of Context, provided the
* parameters used to construct Context objects. Note that it is NO
* LONGER necessary to overload this method if your application is not using
* a special subclass of Context.
*/
@Override
public Context getContext(Request request)
{
return new FirenioContext(request, this);
}

@Override
protected ConnectorFactory constructConnectorFactory() {
return new ConnectorFactory() {
@Override
public ConnectionMonitor getConnectionMonitor() throws SQLException {
return null;
}

@Override
public void determineIdentifierQuoteString() {

}

@Override
public String getIdentifierQuoteString() {
return null;
}

@Override
public DatabaseAffinity getDatabaseAffinity() {
return null;
}

@Override
public boolean isEnabled() {
return false;
}

@Override
public void configure(EnhancedProperties props) {

}
};
}

@Override
protected Dispatcher constructDispatcher() {
return new AnnotationDispatcher<>(this);
}

@Override
protected MustacheManager constructMustacheManager() {
return new FirenioMustacheManager(this);
}

@Override
protected SessionManager constructSessionManager() {
return new HttpSessionManager(this);
}

@Override
protected FirenioMonitor constructMonitor() {
return new FirenioMonitor(this);
}

/**
* Starts the FirenioGeminiApplication
* todo
*
* @throws Exception
*/
public final void start(String serverName, int port, int backlog) throws Exception {
boolean lite = Util.getBooleanProperty("lite");
boolean read = Util.getBooleanProperty("read");
boolean pool = Util.getBooleanProperty("pool");
boolean epoll = Util.getBooleanProperty("epoll");
boolean direct = Util.getBooleanProperty("direct");
boolean inline = Util.getBooleanProperty("inline");
boolean nodelay = Util.getBooleanProperty("nodelay");
boolean cachedurl = Util.getBooleanProperty("cachedurl");
boolean unsafeBuf = Util.getBooleanProperty("unsafeBuf");
int core = Util.getIntProperty("core", 1);
int frame = Util.getIntProperty("frame", 16);
int level = Util.getIntProperty("level", 1);
int readBuf = Util.getIntProperty("readBuf", 16);
Options.setBufAutoExpansion(false);
Options.setChannelReadFirst(read);
Options.setEnableEpoll(epoll);
Options.setEnableUnsafeBuf(unsafeBuf);
log.info("lite: {}", lite);
log.info("read: {}", read);
log.info("pool: {}", pool);
log.info("core: {}", core);
log.info("epoll: {}", epoll);
log.info("frame: {}", frame);
log.info("level: {}", level);
log.info("direct: {}", direct);
log.info("inline: {}", inline);
log.info("readBuf: {}", readBuf);
log.info("nodelay: {}", nodelay);
log.info("cachedurl: {}", cachedurl);
log.info("unsafeBuf: {}", unsafeBuf);

final FirenioGeminiApplication thiss = this;
this.getLifecycle().addInitializationTask(new InitAnnotationDispatcher());
// Initialize the application.
this.initialize(null);

int slept = 0;
int maxSleep = 10_000;
while (slept < maxSleep && !this.isRunning()) {
// Wait until the application is initialized and configured.
slept += 1000;
Thread.sleep(1000);
}

if (slept > maxSleep && !this.isRunning()) {
log.error("Failed to start Gemini application after {} seconds", slept);
return;
}

final IoEventHandle eventHandleAdaptor = new IoEventHandle() {

@Override
public void accept(Channel channel, Frame frame) throws Exception {
final HttpFrame httpFrame = (HttpFrame) frame;
final HttpRequest request = new HttpRequest(channel, httpFrame, thiss);
final FirenioContext context = new FirenioContext(request, thiss);
getDispatcher().dispatch(context);

// fixme - content type shouldn't be set here
// httpFrame.setContentType(HttpContentType.text_plain);
httpFrame.setConnection(HttpConnection.NONE);
httpFrame.setDate(HttpDateUtil.getDateLine());
channel.writeAndFlush(httpFrame);
channel.release(httpFrame);
}
};

int fcache = 1024 * 16;
int pool_cap = 1024 * 128;
int pool_unit = 256;
if (inline) {
pool_cap = 1024 * 8;
pool_unit = 256 * 16;
}
HttpDateUtil.start();
NioEventLoopGroup group = new NioEventLoopGroup();
ChannelAcceptor context = new ChannelAcceptor(group, port);
group.setMemoryPoolCapacity(pool_cap);
group.setEnableMemoryPoolDirect(direct);
group.setEnableMemoryPool(pool);
group.setMemoryPoolUnit(pool_unit);
group.setWriteBuffers(32);
group.setChannelReadBuffer(1024 * readBuf);
group.setEventLoopSize(Util.availableProcessors() * core);
group.setConcurrentFrameStack(false);
if (nodelay) {
context.addChannelEventListener(new ChannelEventListenerAdapter() {

@Override
public void channelOpened(Channel ch) throws Exception {
ch.setOption(SocketOptions.TCP_NODELAY, 1);
ch.setOption(SocketOptions.SO_KEEPALIVE, 0);
}
});
}
ByteTree cachedUrls = null;
if (cachedurl) {
cachedUrls = new ByteTree();
for (String route : getDispatcher().getRoutes()) {
cachedUrls.add(route);
}
}
context.addChannelEventListener(new LoggerChannelOpenListener());
context.setIoEventHandle(eventHandleAdaptor);
context.addProtocolCodec(new HttpCodec(serverName, fcache, lite, inline, cachedUrls));
context.bind(backlog);
}
}
Loading