Skip to content

Commit

Permalink
LevelDB native support #1839
Browse files Browse the repository at this point in the history
  • Loading branch information
JiriOndrusek committed Oct 12, 2020
1 parent d70ad47 commit 1a91fbb
Show file tree
Hide file tree
Showing 23 changed files with 745 additions and 90 deletions.
17 changes: 13 additions & 4 deletions docs/modules/ROOT/pages/reference/extensions/leveldb.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
// This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page
= LevelDB
:cq-artifact-id: camel-quarkus-leveldb
:cq-native-supported: false
:cq-status: Preview
:cq-native-supported: true
:cq-status: Stable
:cq-description: Using LevelDB as persistent EIP store
:cq-deprecated: false
:cq-jvm-since: 1.2.0
:cq-native-since: n/a
:cq-native-since: 1.2.0

[.badges]
[.badge-key]##JVM since##[.badge-supported]##1.2.0## [.badge-key]##Native##[.badge-unsupported]##unsupported##
[.badge-key]##JVM since##[.badge-supported]##1.2.0## [.badge-key]##Native since##[.badge-supported]##1.2.0##

Using LevelDB as persistent EIP store

Expand All @@ -31,3 +31,12 @@ Please refer to the above link for usage and configuration details.
----

Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.

== Camel Quarkus limitations

In native mode extension uses port of the LevelDB written in Java (https://github.com/dain/leveldb#leveldb-in-java[documentation]),
which is within 10% of the performance of the C++ original. Usage of native implementation will be investigated as a new issue.

GraalVM does not support `ObjectOutputStream.writeObject()` (https://github.com/oracle/graal/issues/460[issue]).
In native mode extension uses Jackson serialization instead. This approach could have some performance impact.

6 changes: 3 additions & 3 deletions docs/modules/ROOT/partials/reference/others/leveldb.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page
:cq-artifact-id: camel-quarkus-leveldb
:cq-artifact-id-base: leveldb
:cq-native-supported: false
:cq-status: Preview
:cq-native-supported: true
:cq-status: Stable
:cq-deprecated: false
:cq-jvm-since: 1.2.0
:cq-native-since: n/a
:cq-native-since: 1.2.0
:cq-camel-part-name: leveldb
:cq-camel-part-title: LevelDB
:cq-camel-part-description: Using LevelDB as persistent EIP store
Expand Down

This file was deleted.

1 change: 0 additions & 1 deletion extensions-jvm/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@
<module>language</module>
<module>ldap</module>
<module>ldif</module>
<module>leveldb</module>
<module>lra</module>
<module>lucene</module>
<module>lumberjack</module>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-leveldb</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jackson-deployment</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,41 @@
*/
package org.apache.camel.quarkus.component.leveldb.deployment;

import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.pkg.steps.NativeBuild;
import org.apache.camel.quarkus.core.JvmOnlyRecorder;
import org.jboss.logging.Logger;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
import org.apache.camel.support.DefaultExchangeHolder;

class LeveldbProcessor {

private static final Logger LOG = Logger.getLogger(LeveldbProcessor.class);
private static final String FEATURE = "camel-leveldb";

@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}

/**
* Remove this once this extension starts supporting the native mode.
*/
@BuildStep(onlyIf = NativeBuild.class)
@Record(value = ExecutionTime.RUNTIME_INIT)
void warnJvmInNative(JvmOnlyRecorder recorder) {
JvmOnlyRecorder.warnJvmInNative(LOG, FEATURE); // warn at build time
recorder.warnJvmInNative(FEATURE); // warn at runtime
@BuildStep
ReflectiveClassBuildItem registerForReflection() {
return new ReflectiveClassBuildItem(false, false, new String[] {
org.iq80.leveldb.impl.Iq80DBFactory.class.getName(),
org.apache.camel.support.DefaultExchangeHolder.class.getName()
});
}

@BuildStep
ReflectiveClassBuildItem registerForReflectionWithFields() {
return new ReflectiveClassBuildItem(false, true, new String[] {
DefaultExchangeHolder.class.getName(),
});
}

@BuildStep
public void registerRuntimeInitializedClasses(BuildProducer<RuntimeInitializedClassBuildItem> resource) {
resource.produce(new RuntimeInitializedClassBuildItem(
org.iq80.leveldb.table.Table.class.getName()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,5 @@
<modules>
<module>deployment</module>
<module>runtime</module>
<module>integration-test</module>
</modules>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

<properties>
<camel.quarkus.jvmSince>1.2.0</camel.quarkus.jvmSince>
<camel.quarkus.nativeSince>1.2.0</camel.quarkus.nativeSince>
</properties>

<dependencyManagement>
Expand All @@ -56,6 +57,35 @@
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-leveldb</artifactId>
<exclusions>
<exclusion>
<artifactId>leveldbjni-all</artifactId>
<groupId>org.fusesource.leveldbjni</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-leveldb</artifactId>
<exclusions>
<exclusion>
<groupId>org.fusesource.leveldbjni</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

Expand Down
5 changes: 5 additions & 0 deletions extensions/leveldb/runtime/src/main/doc/limitations.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
In native mode extension uses port of the LevelDB written in Java (https://github.com/dain/leveldb#leveldb-in-java[documentation]),
which is within 10% of the performance of the C++ original. Usage of native implementation will be investigated as a new issue.

GraalVM does not support `ObjectOutputStream.writeObject()` (https://github.com/oracle/graal/issues/460[issue]).
In native mode extension uses Jackson serialization instead. This approach could have some performance impact.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.quarkus.component.leveldb;

import java.nio.MappedByteBuffer;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import org.iq80.leveldb.impl.MMapLogWriter;

/**
* Workaround for https://github.com/oracle/graal/issues/2761
* (see OriginalByteBufferSupport for more information)
*/
@TargetClass(value = MMapLogWriter.class)
final class MMapLogWriterSubstitute {

@Alias
private MappedByteBuffer mappedByteBuffer;

@Substitute
private void unmap() {
OriginalByteBufferSupport.unmap(mappedByteBuffer);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.quarkus.component.leveldb;

import java.io.Closeable;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.Callable;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import org.iq80.leveldb.table.MMapTable;
import org.iq80.leveldb.util.Closeables;

/**
* Workaround for https://github.com/oracle/graal/issues/2761
* (see OriginalByteBufferSupport for more information)
*/
@TargetClass(value = MMapTable.class)
final class MMapTableSubstitute {

@Alias
protected String name;
@Alias
protected FileChannel fileChannel;
@Alias
private MappedByteBuffer data;

@Substitute
public Callable<?> closer() {
return new Closer(name, fileChannel, data);
}

private static class Closer
implements Callable<Void> {
private final String name;
private final Closeable closeable;
private final MappedByteBuffer data;

public Closer(String name, Closeable closeable, MappedByteBuffer data) {
this.name = name;
this.closeable = closeable;
this.data = data;
}

public Void call() {
OriginalByteBufferSupport.unmap(data);
Closeables.closeQuietly(closeable);
return null;
}
}

}

0 comments on commit 1a91fbb

Please sign in to comment.