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

Update example B #3

Draft
wants to merge 5 commits into
base: main
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
2 changes: 2 additions & 0 deletions examples/B/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pmemkv
__pycache__/
target/
10 changes: 7 additions & 3 deletions examples/B/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ pmemkv: $(OBJS)
$(CXX) $(CXXFLAGS) -o $@ $(OBJS) $(LIBS)

# for the Python script, the build step just checks for syntax errors
kv: kv.py
python: kv.py
python3 -m py_compile kv.py

java:
$(MAKE) -C PmemkvExample java

clean:
$(RM) *.o core a.out

clobber: clean
$(RM) pmemkv
$(RM) -r pmemkv __pycache__/
$(MAKE) -C PmemkvExample clobber

.PHONY: all clean clobber
.PHONY: all clean clobber java
11 changes: 11 additions & 0 deletions examples/B/PmemkvExample/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#
# Makefile for java pmemkv example
#

java:
mvn package

clobber:
$(RM) -r target/

.PHONY: clobber java
80 changes: 80 additions & 0 deletions examples/B/PmemkvExample/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?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">
<modelVersion>4.0.0</modelVersion>

<groupId>io.pmem</groupId>
<artifactId>PmemkvExample</artifactId>
<version>1.2.0</version>
<description>Example for pmemkv Java binding</description>
<packaging>jar</packaging>

<!-- This example is compatible with pmemkv Java binding v1.2.0+ -->
<dependencies>
<dependency>
<groupId>io.pmem</groupId>
<artifactId>pmemkv</artifactId>
<version>[1.2.0,)</version>
</dependency>
</dependencies>

<properties>
<!-- use Java in ver. 8 and UTF-8 encoding -->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<showWarnings>true</showWarnings>
<failOnWarning>false</failOnWarning>
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${project.artifactId}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>${project.artifactId}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
79 changes: 79 additions & 0 deletions examples/B/PmemkvExample/src/main/java/PmemkvExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import io.pmem.pmemkv.Converter;
import io.pmem.pmemkv.Database;
import io.pmem.pmemkv.NotFoundException;

import java.nio.ByteBuffer;

/*
* Implementation of Converter interface to allow
* storing in the Database keys and values as Strings.
*/
class StringConverter implements Converter<String> {
public ByteBuffer toByteBuffer(String entry) {
return ByteBuffer.wrap(entry.getBytes());
}

public String fromByteBuffer(ByteBuffer entry) {
byte[] bytes;
bytes = new byte[entry.capacity()];
entry.get(bytes);
return new String(bytes);
}
}

public class PmemkvExample {
/*
* this is the main program, used this way:
* java PmemkvExample pmemfile -- print all the keys and values in the pmemfile
* java PmemkvExample pmemfile key -- lookup key and print the value
* java PmemkvExample pmemfile key value -- add a key/value pair to the pmemfile
*
* the pmemfile is created automatically if it doesn't already exist.
*/

public static void main(String[] args) {
int SIZE = 10 * 1024 * 1024; // 10 MiB
String ENGINE = "cmap";

if (args.length < 1 || args.length > 3) {
System.err.println("Usage: java PmemkvExample kvfile [key [value]]");
System.exit(1);
}

/*
* Configure and open Database, using Builder.
* Part of the configuration is given (as an example) as JSON Object.
* Note, it is required to define key and value converter (to/from ByteBuffer).
*/
Database<String, String> db = new Database.Builder<String, String>(ENGINE)
.fromJson("{\"path\":\"" + args[0] + "\", \"create_if_missing\":1}")
.setSize(SIZE)
.setKeyConverter(new StringConverter())
.setValueConverter(new StringConverter())
.build();

if (args.length == 1) {

// iterate through the key-value store, printing them
db.getAll((String k, String v) -> {
System.out.println(k + "=\"" + v + "\"");
});
} else if (args.length == 2) {

// lookup the given key and print the value
try {
db.get(args[1], (String v) -> {
System.out.println(args[1] + "=\"" + v + "\"");
});
} catch (NotFoundException e) {
System.out.println("Key '" + args[1] + "' wasn't found in DB");
}
} else {

// add the given key-value pair
db.put(args[1], args[2]);
}

db.stop();
}
}
39 changes: 26 additions & 13 deletions examples/B/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,36 @@ this example is recommended for everyone since it provides an overview
of how the most common libraries are used together.

The pmemkv.cpp program uses the C++ language bindings for libpmemkv,
and kv.py program uses the Python language bindings. The programs
are very simple, so even people who are not that familiar with C++
and Python should be able to understand them.
kv.py program uses the Python language bindings, and PmemkvExample is
a simple project using the Java bindings. The programs are
very simple, so even people who are not that familiar with C++, Python,
and Java should be able to understand them.

This is example consists of these files:
This example consists of these files:

pmemkv.cpp -- simple C++ program using libpmemkv
kvinit.cpp -- convenient function for creating/opening the kv store
Makefile -- rules for building this example
kv.py -- simple Python program using libpmemkv
run_cpp.sh -- script to run the C++ version
run_py.sh -- script to run the Python version
pmemkv.cpp -- simple C++ program using libpmemkv
kvinit.cpp -- convenient function for creating/opening the kv store
Makefile -- rules for building this example
kv.py -- simple Python program using libpmemkv
PmemkvExample/ -- simple Java project with its files:
Makefile -- rules for building the Java example
pom.xml -- project and dependencies configuration
PmemkvExample.java -- source file (located in sub-dir src/main/java)
run_cpp.sh -- script to run the C++ version
run_py.sh -- script to run the Python version
run_java.sh -- script to run the Java version
run_cross_lang.sh -- script executing all languages alternatively

To build this example run: make
To run it and see what it illustrates run: ./run_cpp.sh or ./run_py.sh
To run it and see what it illustrates run:
./run_cpp.sh, ./run_py.sh or ./run_java.sh

Modifying the code and run steps is a great way to learn from this example.
The last script - run_cross_lang.sh - shows how data in the same
database can be accessed using various programs, even implemented
in different programming languages. This will work in pmemkv
as long as they use the same engine.

Modifying the code and running steps is a great way to learn from this example.

This example shows a generic key-value store, called libpmemkv, which
handles all the details of persistent memory for you. Each "put"
Expand All @@ -38,7 +51,7 @@ This example uses:
- the "cmap" persistent memory concurrent hashmap, which uses:
- libpmemobj for allocation & transactions, which uses:
- libpmem for low-level mapping and flushing, which uses:
- a DAX-mounted file system to get direct access to pmem
- a DAX-mounted file system to get direct access to pmem.

Although the above stack seems like lots of SW, it is all designed to
give applications direct access to their data where sits in pmem, rather
Expand Down
17 changes: 11 additions & 6 deletions examples/B/kv.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ def kvprint(key, value):

#
# this is the main program, used this way:
# kv pmemfile -- print all the keys and values in the pmemfile
# kv pmemfile key -- lookup key and print the value
# kv pmemfile key value -- add a key/value pair to the pmemfile
# kv.py pmemfile -- print all the keys and values in the pmemfile
# kv.py pmemfile key -- lookup key and print the value
# kv.py pmemfile key value -- add a key/value pair to the pmemfile
#
# the pmemfile is created automatically if it doesn't already exist.
#
Expand All @@ -32,11 +32,16 @@ def kvprint(key, value):
if len(sys.argv) == 2:
# iterate through the key-value store, printing them
db.get_all(kvprint)

elif len(sys.argv) == 3:
# lookup the given key and print the value
db.get(sys.argv[2],
lambda value:
print(f"{sys.argv[2]}=\"{memoryview(value).tobytes().decode()}\""))
try:
db.get(sys.argv[2],
lambda value:
print(f"{sys.argv[2]}=\"{memoryview(value).tobytes().decode()}\""))
except KeyError:
print(f"Key '{sys.argv[2]}' wasn't found in DB")

else:
# add the given key-value pair
db.put(sys.argv[2], sys.argv[3])
Expand Down
34 changes: 15 additions & 19 deletions examples/B/kvinit.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
#include <cassert>
#include <filesystem>
#include <iostream>
#include <libpmemkv.hpp>

using namespace pmem::kv;
using std::cerr;
using std::cout;
using std::endl;
using std::string;

// default size for this example: 10 Meg
const uint64_t SIZE = 10 * 1024 * 1024;

//
// must_open_or_create() is a convenience function to open the
// open_or_create() is a convenience function to open the
// database if it already exists, or create it with a default
// size if it doesn't.
//
db *must_open_or_create(const char *path) {
db *open_or_create(const char *path) {

// start by creating the db object
db *kv = new db();
Expand All @@ -26,29 +23,28 @@ db *must_open_or_create(const char *path) {
// create the config information for the pmemkv open
config cfg;

if (cfg.put_string("path", path) != status::OK) {
// flag to control the behavior for open (create) method
if (cfg.put_create_if_missing(true) != status::OK) {
cerr << pmemkv_errormsg() << endl;
exit(1);
}

if (!std::filesystem::exists(path)) {
// file doesn't exist, so add config flags to create it
if (cfg.put_uint64("force_create", 1) != status::OK) {
cerr << pmemkv_errormsg() << endl;
exit(1);
}

if (cfg.put_uint64("size", SIZE) != status::OK) {
cerr << pmemkv_errormsg() << endl;
exit(1);
}
// specify path of DB
if (cfg.put_path(path) != status::OK) {
cerr << pmemkv_errormsg() << endl;
exit(1);
}

// if file doesn't exist, we need to specify size of DB to create
if (cfg.put_size(SIZE) != status::OK) {
cerr << pmemkv_errormsg() << endl;
exit(1);
}

if (kv->open("cmap", std::move(cfg)) != status::OK) {
cerr << errormsg() << endl;
cerr << pmemkv_errormsg() << endl;
exit(1);
}

return kv;

}
Loading