mirror of
https://github.com/cubefs/cubefs.git
synced 2026-08-02 02:00:56 +00:00
feature: introduce java sdk
Signed-off-by: Shuoran Liu <shuoranliu@gmail.com>
This commit is contained in:
parent
9a90934f31
commit
e68042fac0
31
java/README.md
Normal file
31
java/README.md
Normal 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>
|
||||
```
|
||||
35
java/pom.xml
35
java/pom.xml
@ -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>
|
||||
|
||||
94
java/src/main/java/io/chubao/fs/CfsDriver.java
Normal file
94
java/src/main/java/io/chubao/fs/CfsDriver.java
Normal 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);
|
||||
}
|
||||
88
java/src/main/java/io/chubao/fs/CfsMount.java
Normal file
88
java/src/main/java/io/chubao/fs/CfsMount.java
Normal 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;
|
||||
}
|
||||
}
|
||||
115
java/src/main/java/io/chubao/fs/TestCfsClient.java
Normal file
115
java/src/main/java/io/chubao/fs/TestCfsClient.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
package io.chubao.fs;
|
||||
Loading…
Reference in New Issue
Block a user