feature: introduce java sdk

Signed-off-by: Shuoran Liu <shuoranliu@gmail.com>
This commit is contained in:
Shuoran Liu 2020-09-10 20:31:33 +08:00
parent 9a90934f31
commit e68042fac0
6 changed files with 362 additions and 2 deletions

31
java/README.md Normal file
View File

@ -0,0 +1,31 @@
# Usage
### Build shared library
```bash
cd libsdk
sh build.sh
sudo cp libcfs.so /usr/lib/libcfs.so
```
### Build jar with dependencies
```bash
cd java
mvn clean package
```
### Deploy single-node cluster using docker
```bash
cd docker
./run_docker.sh -r
```
## Run the java test program
```
java -cp target/libchubaofs-1.0-SNAPSHOT-jar-with-dependencies.jar io.chubao.fs.TestCfsClient ls <dirpath>
java -cp target/libchubaofs-1.0-SNAPSHOT-jar-with-dependencies.jar io.chubao.fs.TestCfsClient read <filepath>
java -cp target/libchubaofs-1.0-SNAPSHOT-jar-with-dependencies.jar io.chubao.fs.TestCfsClient write <filepath>
```

View File

@ -13,6 +13,14 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.6.0</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
@ -25,7 +33,32 @@
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@ -38,4 +71,4 @@
</plugins>
</build>
</project>
</project>

View File

@ -0,0 +1,94 @@
package io.chubao.fs;
import com.sun.jna.Library;
import com.sun.jna.Structure;
import com.sun.jna.Pointer;
import java.util.List;
import java.util.Arrays;
public interface CfsDriver extends Library {
public class StatInfo extends Structure implements Structure.ByReference {
// note that the field layout should be aligned with cfs_stat_info
public long ino;
public long size;
public long blocks;
public long atime;
public long mtime;
public long ctime;
public int atime_nsec;
public int mtime_nsec;
public int ctime_nsec;
public int mode;
public int nlink;
public int blkSize;
public int uid;
public int gid;
public StatInfo() {
super();
};
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "ino", "size", "blocks", "atime", "mtime", "ctime", "atime_nsec",
"mtime_nsec", "ctime_nsec", "mode", "nlink", "blkSize", "uid", "gid" });
}
}
public class Dirent extends Structure {
// note that the field layout should be aligned with cfs_dirent
public long ino;
public byte[] name = new byte[256];
public byte dType;
public Dirent() {
super();
};
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "ino", "name", "dType" });
}
}
public class DirentArray extends Structure {
public static class ByValue extends DirentArray implements Structure.ByValue {
}
// note that the field layout should be aligned with GoSlice
public Pointer data;
public long len;
public long cap;
public DirentArray() {
super();
}
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "data", "len", "cap" });
}
}
// exports from shared library
long cfs_new_client();
int cfs_set_client(long id, String key, String val);
int cfs_start_client(long id);
void cfs_close_client(long id);
int cfs_getattr(long id, String path, StatInfo stat);
int cfs_open(long id, String path, int flags, int mode);
int cfs_flush(long id, int fd);
void cfs_close(long id, int fd);
long cfs_write(long id, int fd, byte[] buf, long size, long offset);
long cfs_read(long id, int fd, byte[] buf, long size, long offset);
int cfs_readdir(long id, int fd, DirentArray.ByValue dents, long count);
}

View File

@ -0,0 +1,88 @@
package io.chubao.fs;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import io.chubao.fs.CfsDriver.Dirent;
import io.chubao.fs.CfsDriver.DirentArray;
public class CfsMount {
public int O_RDONLY = 0;
public int O_WRONLY = 1;
public int O_RDWR = 2;
public int O_ACCMODE = 3;
public int O_CREAT = 100;
public int O_TRUNC = 1000;
public int O_APPEND = 2000;
public int O_DIRECT = 40000;
public int S_IFDIR = 0040000;
public int S_IFREG = 0100000;
public int S_IFLNK = 0120000;
private CfsDriver driver;
private String libpath;
public CfsMount(String path) {
libpath = path;
driver = (CfsDriver) Native.load(libpath, CfsDriver.class);
}
public long NewClient() {
return driver.cfs_new_client();
}
public int SetClient(long id, String key, String val) {
return driver.cfs_set_client(id, key, val);
}
public int StartClient(long id) {
return driver.cfs_start_client(id);
}
public void CloseClient(long id) {
driver.cfs_close_client(id);
}
public int GetAttr(long id, String path, CfsDriver.StatInfo stat) {
return driver.cfs_getattr(id, path, stat);
}
public int Open(long id, String path, int flags, int mode) {
return driver.cfs_open(id, path, flags, mode);
}
public void Close(long id, int fd) {
driver.cfs_close(id, fd);
}
public long Write(long id, int fd, byte[] buf, long size, long offset) {
return driver.cfs_write(id, fd, buf, size, offset);
}
public long Read(long id, int fd, byte[] buf, long size, long offset) {
return driver.cfs_read(id, fd, buf, size, offset);
}
/*
* Note that the memory allocated for Dirent[] must be countinuous. For example,
* (new Dirent()).toArray(count).
*/
public int Readdir(long id, int fd, Dirent[] dents, int count) {
Pointer arr = dents[0].getPointer();
DirentArray.ByValue slice = new DirentArray.ByValue();
slice.data = arr;
slice.len = (long) count;
slice.cap = (long) count;
long arrSize = driver.cfs_readdir(id, fd, slice, count);
if (arrSize > 0) {
for (int i = 0; i < (int) arrSize; i++) {
dents[i].read();
}
}
return (int) arrSize;
}
}

View File

@ -0,0 +1,115 @@
package io.chubao.fs;
import io.chubao.fs.CfsDriver.Dirent;
public class TestCfsClient {
public static void main(String[] args) {
CfsMount mnt = new CfsMount("/usr/lib/libcfs.so");
long cid = mnt.NewClient();
mnt.SetClient(cid, "volName", "ltptest");
mnt.SetClient(cid, "masterAddr", "192.168.0.11:17010,192.168.0.12:17010,192.168.0.13:17010");
mnt.SetClient(cid, "logDir", "/home/liushuoran/log");
mnt.SetClient(cid, "logLeval", "info");
int ret = mnt.StartClient(cid);
if (ret < 0) {
System.out.println("start client failed!!!");
return;
}
if (args.length < 2) {
System.out.println("Invalid args: lack of path");
return;
}
String targetPath = args[1];
if (args[0].equals("read")) {
CfsDriver.StatInfo stat = new CfsDriver.StatInfo();
ret = mnt.GetAttr(cid, targetPath, stat);
if (ret < 0) {
System.out.println("GetAttr failed: " + ret);
return;
}
System.out.println("ino: " + stat.ino);
System.out.println("size: " + stat.size);
System.out.println("blocks: " + stat.blocks);
System.out.println("nlink: " + stat.nlink);
System.out.println("mode: " + stat.mode);
System.out.println("uid: " + stat.uid);
System.out.println("gid: " + stat.gid);
int fd = mnt.Open(cid, targetPath, mnt.O_RDONLY, 0644);
if (fd < 0) {
System.out.println("Open failed: " + fd);
return;
}
byte[] buf = new byte[4096];
long readByte = mnt.Read(cid, fd, buf, buf.length, 0);
System.out.println("fd: " + fd);
System.out.println("read bytes: " + readByte);
System.out.println(new String(buf));
// verify md5sum
byte[] toVerify = new byte[(int) readByte];
System.arraycopy(buf, 0, toVerify, 0, (int) readByte);
StringBuilder sb = new StringBuilder();
java.security.MessageDigest md5 = null;
try {
md5 = java.security.MessageDigest.getInstance("MD5");
md5.update(toVerify);
} catch (java.security.NoSuchAlgorithmException e) {
}
if (md5 != null) {
for (byte b : md5.digest()) {
sb.append(String.format("%02x", b));
}
}
System.out.println("md5: " + sb.toString());
mnt.Close(cid, fd);
} else if (args[0].equals("write")) {
int fd = mnt.Open(cid, targetPath, mnt.O_RDWR | mnt.O_CREAT, 0644);
if (fd < 0) {
System.out.println("Open failed: " + fd);
return;
}
String toWrite = "abcdefg";
byte[] buf = toWrite.getBytes();
long writeBytes = mnt.Write(cid, fd, buf, buf.length, 0);
System.out.println("write bytes: " + writeBytes);
mnt.Close(cid, fd);
} else if (args[0].equals("ls")) {
int fd = mnt.Open(cid, targetPath, mnt.O_RDWR, 0644);
if (fd < 0) {
System.out.println("Open failed: " + fd);
return;
}
Dirent dent = new Dirent();
Dirent[] dents = (Dirent[]) dent.toArray(16);
int n = mnt.Readdir(cid, fd, dents, 16);
System.out.println("num of entries: " + n);
for (int i = 0; i < n; i++) {
System.out.println("ino: " + dents[i].ino + " | d_type: " + dents[i].dType);
}
mnt.Close(cid, fd);
}
mnt.CloseClient(cid);
}
}

View File

@ -1 +0,0 @@
package io.chubao.fs;