找回密码
 注册
查看: 569|回复: 0

Java访问Ceph数据

[复制链接]

0

主题

0

回帖

9

积分

管理员

积分
9
QQ
发表于 2023-2-21 15:00:18 | 显示全部楼层 |阅读模式
1. 部署LIBRADOS环境. ^8 f- b3 B- ~; t
客户端应用程序需要librados才能连接到Ceph存储集群。+ B' P/ ^1 l+ g; h% ^
, [8 J# W4 Z1 R# U# J  d
1.1 安装jna.jar
1 d& A/ W  a) p! V$ }" d) KDebian/Ubuntu环境下执行以下命令  A( w  Z4 |9 j" g3 \
, N  r" g' q: Y/ Y, |
sudo apt-get install libjna-java
# d  |' ?7 J% j& w  [6 A8 L0 a! Q: _5 b
% l+ j, G; S+ A# R0 N
CentOS/RHEL环境下执行以下命令
* O. M) |  O2 Q
4 ~9 w+ u1 H# S5 Nsudo yum install jna! S) u" z: G5 W  t- N4 N
( K* S7 v& y0 y4 e+ i
JAR文件位于/usr/share/java.  _7 B& D+ v1 ^9 h. M& g( R
  w1 U1 f3 x0 \1 G
1.2 克隆rados-java代码库4 Y) D+ y& O8 w  s2 c9 p
git clone --recursive https://github.com/ceph/rados-java.git- w/ E' C) E% P* ~

! p$ }3 b/ t& _+ X/ ^1.3 编译rados-java代码:
7 h5 {3 A5 c  J2 b# }$ I( h. ?* Hcd rados-java
; O% y$ t# l- ?: f/ m8 Aant
& ?7 Q: ~7 ]5 }4 e& N3 J# [
1 C5 }2 {9 O8 e
5 R4 v5 f: m, i' }% x! j# h( HJAR文件位于rados-java/target目录下* d7 @( w$ l& O3 d& m' [

; c* g0 L& D5 n7 T1 V  \+ F1.4 关联路径
$ D* ^; N  s; f/ M( u- Y, b7 A复制该JAR文件到公共目录 (例如 /usr/share/java) ,并且确认该文件和JNA JAR在你的JVM’s classpath目录中. 举个例子,你可以按照以下的方法来关联路径:
- U" e" X! m# M# x1 k& Q, Q% [0 ?, U  m2 q. D7 L* h
sudo cp target/rados-0.1.3.jar /usr/share/java/rados-0.1.3.jar. ^& f9 g, h# C7 J5 U
sudo ln -s /usr/share/java/jna-3.2.7.jar /usr/lib/jvm/default-java/jre/lib/ext/jna-3.2.7.jar
: W: p/ G- D* z4 |* `1 A4 Rsudo ln -s /usr/share/java/rados-0.1.3.jar  /usr/lib/jvm/default-java/jre/lib/ext/rados-0.1.3.jar
* `% L% i3 b4 O4 b  l0 n8 ^  [  |3 P/ h, ]
  T' |0 F- }* V- _
编译文档可执行以下的命令:
4 ^, m/ c" h# R" x+ @7 s8 R9 S3 ^3 A  P! z) ?# b$ E
ant docs
9 H/ y. |1 c0 C; [( }' H0 C9 [1 r0 y  X
2. 配置群集句柄
9 Z  T* N: c# l一个Ceph的客户端通过librados,直接与交互的OSD来存储和检索数据。要与OSD交互,客户端应用程序必须调用 librados 并连接到Ceph Monitor。连接后,librados从Ceph Monitor中检索 Cluster Map。当客户端应用程序想要读取或写入数据时,它会创建I/O上下文并绑定到池。该池具有关联的规则集,该规则集定义了如何将数据放入存储群集中。通过I/O上下文,客户端向librados提供对象名称,它获取对象名称和集群映射(即集群的拓扑)并计算用于定位数据的放置组和OSD。然后客户端应用程序可以读取或写入数据。客户端应用程序无需直接了解群集的拓扑。
5 ]) [# |* L& x% X8 A$ u
: H8 f- G; t1 ?7 |Ceph存储集群句柄封装了客户端配置,包括:- n7 q. X9 B1 X6 x
6 m7 E' B  e# c/ W
使用用户ID的rados_create() 或使用用户名称的rados_create2() (推荐使用此方法).2 c4 C3 P( d8 Y9 Q. A2 @7 N
cephx认证密钥
; ]+ u( M8 y' k/ s监视器ID和IP地址
* ~% G1 T: h: }记录级别6 y" e8 u0 E; G1 }
调试级别- u" |4 ~0 w4 T0 G
因此,从您的应用程序使用群集的第一步是:1)创建应用程序将用于连接到存储群集的群集句柄,然后2)使用该句柄进行连接。要连接到群集,应用程序必须提供监视器地址,用户名和身份验证密钥(默认情况下启用cephx)。
! j, i4 t, F. d$ b- A- U/ T1 @
8 P( [0 t, o6 [! W注意 与不同的Ceph存储集群 - 或与不同用户的同一集群 - 交互需要不同的集群句柄。
1 \/ f5 V2 U; O" b4 j5 ]2 A* \& i% Z4 Z+ _  B% c5 D
RADOS提供了多种设置所需值的方法。对于监视器和加密密钥设置,一种处理它们的简单方法是确保您的Ceph配置文件包含密钥环文件的密钥环路径和至少一个监视器地址(例如,mon 主机)。例如:
) u5 h' S& E1 {1 y1 c5 S9 d
2 j' J" R3 T& ]5 F3 L! Q+ x[global]
" f) ^2 Y  Z( D: s  ?mon host = 192.168.11.1 5 e9 a- R1 l) y$ ]8 w
keyring = /etc/ceph/ceph.client.admin.keyring$ V- d2 E/ o$ ?/ w9 ]' S1 Z

! Y) `. l) A5 M5 }4 |" p1 @! [
1 M4 i6 W2 N6 e4 M; C创建句柄后,可以读取Ceph配置文件以配置句柄。还可以将参数传递给您的应用程序,并使用函数解析它们以解析命令行参数(例如,rados_conf_parse_argv()),或解析Ceph环境变量(例如,rados_conf_parse_env())。某些包装器无法实现便捷方法,因此需要实现这些功能。下图提供了初始连接的高级流程。
/ p- G  m7 g' l) M* D' K$ ]& }/ o7 W+ o0 U- K* c8 [5 q
连接后,应用程序可以仅使用群集句柄调用影响整个群集的功能。例如,一旦有了集群句柄,您就可以:
% r+ ]% u$ O3 I) \) O6 @
  U) [3 e$ A5 z" s获取群集统计信息* E( g* x2 K3 x
使用池操作(存在,创建,列表,删除)
9 s- b2 ]+ L+ Y! F获取并设置配置
8 z0 ?6 e, F  X1 }- ]1 ICeph的一个强大功能是能够绑定到不同的池。每个池可能具有不同数量的放置组,对象副本和复制策略。例如,可以将池设置为“热”池,其将SSD用于常用对象或使用擦除编码的“冷”池。
* [! i& a! z* z& W) g# dJava要求你指定用户ID(admin)或用户名(client.admin),并使用默认的ceph cluster name。Java绑定将基于C ++的错误转换为异常。
' X% y2 z0 R3 h6 K8 N
6 \1 s1 ?0 T2 Z- f3 l0 cimport com.ceph.rados.Rados;6 W3 R$ u; Z" n! K
import com.ceph.rados.RadosException;% z; Q, i  E! g7 u0 f- C' f/ |
5 O6 B+ {. C, V
import java.io.File;! B& y$ d6 c. ~, M9 G6 Y# a
8 P4 D  z0 z) @2 x! N/ S
public class CephClient {
( M! }9 c) z9 _9 v# D* `+ Q5 j        public static void main (String args[]){
( x' s6 D9 ^. [
0 p) B& w* y, I* T: z3 D                try {
0 Q1 C* |4 y9 ?+ @# V# i' X* S                        Rados cluster = new Rados("admin");
1 B: w" r1 X7 L" W                        System.out.println("Created cluster handle.");
3 D- l9 D5 d$ X1 {* n2 I8 a
1 y$ ~8 [4 v( d                        File f = new File("/etc/ceph/ceph.conf");
$ h4 ^( H: M4 S$ @/ D8 {: h                        cluster.confReadFile(f);
) E  V( i, C8 v! Q                        System.out.println("Read the configuration file.");' \# g9 y! c6 b, I/ E
( A& g8 L1 |  \1 |3 h' H6 l( s
                        cluster.connect();
. s( j' I- ]3 C$ i! E                        System.out.println("Connected to the cluster.");
* {6 z* Y2 _/ l. s4 h) K1 D& k9 `3 a3 Q: D2 T/ g" ~) F1 K
                } catch (RadosException e) {, b; K# d' m' a9 D( F/ a/ l
                        System.out.println(e.getMessage() + ": " + e.getReturnValue());) E, g1 }' L' d% R0 H' \/ U) q
                }
5 W. C3 x- F9 F3 ^0 x. J        }
/ ~8 p, q) _3 k7 q8 H9 t}
' y7 c1 {! h2 {4 ]/ r* q8 @
/ I, o$ I8 B& z; t; @; M4 E9 t4 v* S" }$ Y2 a; }. f& G
编译源代码; 然后,运行。如果你已经把连接Ceph的JAR文件复制到/usr/share/java并软连接到扩展路径, 就无需设置classpath. 如下运行:
8 A& Q) R; f+ f6 z: Z
! i- t3 p2 u) ?) Vjavac CephClient.java
2 G9 Z4 {2 U6 k8 b5 Ljava CephClient5 f1 u' R5 s% R" U, a, F2 X
1 m; L) J0 f+ y. K! a5 o1 h5 i
* x. P3 o" \" o7 i
3. 创建I/O上下文
5 ]" v. l  B% A% W一旦应用程序具有集群句柄和与Ceph存储集群的连接,就可以创建I/O上下文并开始读取和写入数据。I/O上下文将连接绑定到特定池。用户必须具有适当的 CAPS权限才能访问指定的池。例如,具有读访问权但不具有写访问权的用户将只能读取数据。I/O上下文功能包括:, W' q) I( V+ Y! a, n  W- o4 P

5 w, m+ R0 u# n5 t. Y写/读数据和扩展属性+ n/ S0 P/ d. p/ H% _& Y
列出并迭代对象和扩展属性$ _  A. d0 F( I- H! x- w) \
快照池,列表快照等
5 r8 i2 M# w4 SRADOS使应用程序可以同步和异步交互。一旦应用程序具有I/O上下文,读/写操作只需要知道object / xattr名称。封装在librados中的CRUSH算法使用群集映射来识别适当的OSD。OSD守护程序处理复制,如Smart Daemons启用超大规模中所述。所述librados库也映射对象来展示位置组,如在 计算PG的ID。$ f, v$ E: S* S3 A/ G* m

0 y7 d3 b  n& d% Y9 N以下示例使用默认数据池。但是,也可以使用API​​列出池,确保它们存在,或者创建和删除池。对于写操作,这些示例说明了如何使用同步模式。对于读取操作,这些示例说明了如何使用异步模式。5 L* a8 s9 S* V  x1 \
+ ?* s0 O: `& z/ `5 ?# N# M- ~
注意 使用此API删除池时请小心。如果删除池,池中的池和所有数据将丢失。1 U; p6 ?  i3 M
1
$ G9 R% U6 M1 q9 z9 m3.1 写入数据代码5 c3 N8 U; v: }
import com.ceph.rados.Rados;
; y7 @  A# u; Y4 }( L5 q# T; \import com.ceph.rados.RadosException;
/ X5 k0 b& X3 Z; O. @6 }' r- W2 V. r7 c+ q
import java.io.File;
3 V, E3 u% W5 Q9 m3 n; Dimport com.ceph.rados.IoCTX;4 I! u  Y- P4 F/ j  \

4 A" ~7 l0 y% a" b$ bpublic class CephClient {7 V' I7 p4 A5 i# [# _9 g
        public static void main (String args[]){
+ a2 @! l# z8 \8 e; V0 j/ H4 b8 x, n, t" b" ~, L
                try {8 e' E0 ]9 D- E' M
                        Rados cluster = new Rados("admin");
4 d5 S  m, R4 a, c! o# v                        System.out.println("Created cluster handle.");
9 |1 i7 ^; V. h: }  s9 Z5 `                                                //利用配置文件连接ceph
' [9 y, G4 e$ }+ u# h1 q; @7 F+ L                        File f = new File("/etc/ceph/ceph.conf");
& M1 }0 C0 F, \+ r                        cluster.confReadFile(f);
# {, u$ Z$ ~! K+ W( E8 d                        System.out.println("Read the configuration file.");
+ @2 e$ K. P5 W' N2 @( ?! d1 I, E' t
                        cluster.connect();+ ?6 l2 ^& ~! s9 Z# N8 c* K; C
                        System.out.println("Connected to the cluster.");7 I2 R% V0 o. A. N

8 e2 h* i2 T; P+ X5 m+ Z6 b  O                        IoCTX io = cluster.ioCtxCreate("data");1 _2 h9 {9 Q/ H% w
9 h" A2 m5 `/ U# D) Q- q1 n
                        String oidone = "hw";
# C# _2 e" h2 x8 t5 Y# h; I                        String contentone = "Hello World!";. C9 ]6 a! a, w2 y
                        io.write(oidone, contentone);: ^$ p5 w1 C4 f2 u6 S
( O1 D8 e, K5 m7 E8 \
                        String oidtwo = "bm";
7 ^) T6 [2 K( ~- q                        String contenttwo = "Bonjour tout le monde!";! |9 i" ]9 G% W/ Q$ Y& O# E2 t
                        io.write(oidtwo, contenttwo);
( S2 ~2 T5 W% U5 w! x! [' n% R
9 l+ K- o: r4 O0 J                        String[] objects = io.listObjects();+ a' G" H/ Y5 X9 r4 W
                        for (String object: objects)0 z- Q" j8 F% u
                                System.out.println(object);2 |( r8 B2 E( ]( q% i9 {

, F1 x9 b6 {0 _, f                        io.remove(oidone);# F) i  t' D( [$ v
                        io.remove(oidtwo);: {0 |+ U' v, y7 g; l# s

2 Q. _0 p% X) _/ h/ Y  e% U/ |. {                        cluster.ioCtxDestroy(io);+ ^3 t5 E" z! G; s1 }: T; r! j
' b8 u) J5 i9 T1 g( X4 C5 H1 y& H
                } catch (RadosException e) {
% [7 S2 y( t' A/ r9 S7 b4 }                        System.out.println(e.getMessage() + ": " + e.getReturnValue());
" r$ C1 |* z0 ?% r                }
; w2 \! Z6 w" l2 x: V  k' p# b        }$ N2 c4 [7 i9 C" u, }4 n
}% R# M; d  @" c) N8 u
6 r+ {2 F3 |( D
. g* T, P: f  L; H* w; E
3.2 一些基本操作) J" j8 _& r* [* P$ G$ V$ a- U) W
package com.ceph.rbd;
% @9 L, f- `$ L$ Y* Y* Z5 j  ^* \- d5 t, I6 w: P& ?- R9 q6 C$ Q" Q
import java.io.File;$ b, q' V3 w7 p% o+ P3 j
import java.util.Arrays;
& I* [5 f% I: t! nimport java.util.List;9 i+ Q! D" _# @) [

0 k. c: K7 ]- m) \- `4 ]import com.ceph.rados.IoCTX;
# R3 x0 f# b3 ~3 nimport com.ceph.rados.Rados;5 H. R0 p$ t: ~, x
import com.ceph.rados.exceptions.RadosException;
: H/ v- V7 K) A* F/ h7 W. `: Jimport com.ceph.rbd.jna.RbdImageInfo;9 P8 p7 t( z  F# ~
import com.ceph.rbd.jna.RbdSnapInfo;3 h  p& ?* k9 z; H# \2 Y2 V) E
2 s9 \1 ?+ r$ @& Q
public class RbdDao {  q0 E& {) @4 ^* B
8 f+ U. ]6 ^1 q' w6 |
    private static Rados rados;" f1 n) p( f7 d/ c5 s; J
    private static IoCTX ioctx;
" e7 R8 H; V( `4 }/ e. X4 p    private static Rbd rbd;0 h. Y* a' b( B9 ~- X1 x
     /**
8 e3 r5 L: k/ E/ K      * 连接上ceph环境! V1 J7 |, v# c5 n9 q0 R0 p$ Y
      */
9 c2 n8 _" r) k+ g; b' V     public static void connectCeph(){
8 }, Z- J, h3 ?" r           try {
$ K. Y$ X- `8 {2 \( P                           //利用参数连接Ceph
" [8 x7 F- g& j; I) o                rados = new Rados("admin");
' l; Q4 I4 E( S# g- f& J                rados.confSet("mon_host", "172.16.60.41");
. l- z9 }4 J9 j" f# L                rados.confSet("key", "AQCdP9pYGI4jBBAAc96J8/OconCkVKWPBNU2vg==");
' b( w1 x- {  H0 r/ M  P; L                rados.connect();
6 J. m6 ]1 V! g, b0 A% \% K                ioctx = rados.ioCtxCreate("rbd");! X2 Q& B- J  q$ q; }$ J# ^
                rbd = new Rbd(ioctx);
+ ^% G3 M) d1 X1 b                System.out.println("successs connetc");( c/ c/ E" @" {! A
          } catch (Exception e) {+ A) J3 y! D4 z% C  S
              e.printStackTrace();- X' n- f; m/ z: [$ [
            // TODO: handle exception. J4 m- [4 u& Y1 |- N% [
         }- x( K; A9 l* l& a0 R, V
     }9 B8 [+ A4 j* u# d/ W* X  h
0 y" f" }: L+ j4 J/ z% b: x/ S0 L% @( Z
     /**& U: Z( u4 @! u" w4 O, N3 e
      * 返回所有的image,并展示其详细信息
' ^% R! m& O( x      * @return' F" _) T" S- O/ c  l& M; P
      */' X( w% `% d6 t: r
     public static List<String> imageList(){
' ~& v2 p3 [# P  D! Z          List<String> imageList=null;) M$ U4 d2 J4 f( o$ E5 A
          try {
' J# T$ }% d$ g            imageList = Arrays.asList(rbd.list());
  {; I2 m1 x+ ^3 o. `: H            for(String s:imageList){
4 |, v* A1 b% o. Y) f9 b) X- r/ l                showDetailOfImage(s);
# A1 W5 j) f4 J) }/ v0 o) O* h0 |- Q/ T            }6 G3 T% A! n0 u. w
        } catch (RbdException e) {$ k4 z2 f# s' ^) O
            // TODO Auto-generated catch block
% K9 O8 g; K  U1 J7 x' z% W$ X            e.printStackTrace();) T& Y+ E2 P1 h9 I  |* H$ M
        }+ C* \: ~/ M9 Z& G$ v1 w  e
          return imageList;. K# C' D; C8 r6 e
     }6 B' ?3 ?  |/ d1 f( R' a
3 k# L& o! H1 ]
     /**/ F" D% n0 J1 |8 ~% o( ?- Y
      * 显示image的详细信息
0 A% l3 ?: g9 F( U4 s9 s      * @param imageName
4 z% }$ R, }5 w; }7 e$ m$ T( X      */
6 a' v$ |  [2 T% |% \3 ~1 R     public static void showDetailOfImage(String imageName){
, D, R' n6 _$ E: Z         RbdImage image;
- i5 _3 c" I+ O9 `1 \        try {
& g% Y% v  U; J; X              image = rbd.open(imageName);) Z+ T% h) u  ?/ ^
              RbdImageInfo info = image.stat();
4 s! _9 G2 o' }0 i4 f2 P% K* s              System.out.println("=================================================================");
7 o8 v8 u* @# n; O" k              System.out.println("imageName:    "+imageName);
5 m' V( s' n2 S2 u. {, W              System.out.println("imageSize:    "+info.size);2 J3 ^: L* y( p2 e2 E
              System.out.println("order:   "+info.order);
* I! e0 ]: K5 W( F              rbd.close(image);
% L+ M, v9 f1 |3 @3 q% X6 W- t        } catch (RbdException e) {9 {( R9 b- S" W4 k5 X& P
            // TODO Auto-generated catch block# _$ `& l8 \! Y7 A: P8 \
            e.printStackTrace();: ?7 {  t/ V% Z% M" g) p
        }) i9 C0 f' B- P3 m8 O4 G( X

7 }3 ~  w) [& D9 X9 e8 j2 g     }
7 S/ q* N  O$ b1 s! _# i, J$ C- U- W8 t8 D) ?
     /**, e: G8 z+ A, U$ ^9 f
      * 以格式1创建image
. p+ y- b9 c1 ^0 P* G      * @param imageName 名称
8 e! F  r$ u' m+ ?! C      * @param imageSize 大小
3 G2 W" |9 l9 t* ~0 M$ N8 g      */9 `0 T3 Z' X# p1 G# x0 Q
     public static void createRbd_format1(String imageName, long imageSize){4 t1 R& i6 E% F4 A+ j/ s' H
            try {
7 \2 I3 y2 M3 Z8 {& {                rbd.create(imageName, imageSize);
1 ^& n5 u" c$ |. @( f+ {" E0 m; w                RbdImage image = rbd.open(imageName);! \( r$ S1 f- p/ {
                boolean oldFormat = image.isOldFormat();; b/ |* c7 ^8 _5 P* L3 {# ?
                System.out.println("imageFormat:==========================="+oldFormat);
; p3 z9 k0 L( L) W" X
* G% |. k, ^  Z1 H5 H7 I                rbd.close(image);
$ r: @+ \5 J) N/ @            } catch (RbdException e) {
2 \  q6 w( t7 i/ o7 g                System.out.println(e.getMessage() + ": " + e.getReturnValue());- X0 O+ ^$ ^, g7 j
            }
* B% F& W' ?& o2 G     }7 w; G4 h) J- {) s
0 K9 y5 ?+ R; z. O, s+ V
     /**
1 F$ A7 {( u0 ~( f" ?( z      * 以格式2创建image,ceph 仅支持克隆 format 2 映像(即用 rbd create –format 2 创建的),而且内核 rbd 模块还不支持。
# q5 B7 c/ h" t5 w  所以现在你 只能用 QEMU/KVM 或 librbd直接访问克隆品2 @' |& a* j+ V# H; b" A/ I" F7 h
      * @param imageName 名称5 k' O6 {6 q) O# p) Z9 x4 a
      * @param imageSize 大小
! A% V; w2 l: K      */
9 l9 g/ Y6 y; \5 p     public static void createRbd_format2(String imageName, long imageSize){
7 J) u& x) P) a2 X' N- i" A            try {
6 y/ P# }8 _) E8 r6 U. v! w                int features = (1<<0);
+ y: ]8 \* k( g                System.out.println("features=============="+features);
* X" {0 [- l4 r) }5 J$ z' l. F                rbd.create(imageName, imageSize,features, 0);
4 p$ Z+ S" s2 u: y2 Q                RbdImage image = rbd.open(imageName);
3 O  [4 d  D6 [0 v  W6 \, s                boolean oldFormat = image.isOldFormat();
+ t+ ]0 ]% R3 X. E0 w                System.out.println("imageFormat:==========================="+oldFormat);               " ]9 W6 g5 _7 B. t/ ~
                rbd.close(image);1 Z( T7 j1 M, t' ~* @" T/ W0 C
                image.flatten();
1 Q) O2 l' n9 }6 E$ ^; |' @  K            } catch (RbdException e) {
3 Z% I% v: V5 `) q                System.out.println(e.getMessage() + ": " + e.getReturnValue());
# T; D. ~6 Q5 V3 I, ?            }
! A! \% k6 q7 R* E$ |3 s     }
' f- y8 p4 b- W9 C; F& x* ^3 ?# C/ B2 c2 k1 B& N0 D. e7 t: v% l9 [9 H4 U
     /*** s5 a/ W/ G0 L- G& G
      * 方法创建一个image并对重设置大小为初始化大小的2倍
) K5 `; o3 F; j* ?& h! m      * @param imageName' h  I4 w9 S0 [2 j6 ?) O$ F8 \2 L
      */( x' e5 ?6 e' ?
     public static void resizeImage(String imageName){$ r" H8 ^7 u- X
            long initialSize = 10485760;+ x( j; o0 a/ A2 v. h- M$ v: D9 o
            long newSize = initialSize * 2;
8 Q7 J( J* C/ z/ Q            try {7 ~. A; ]" N; |
                int features = (1<<0);
$ b+ \8 A3 O- \+ {                System.out.println("features=============="+features);
8 g# ^. n: S$ ^4 J% R) s                rbd.create(imageName, initialSize,features, 0);( e0 E' E+ B: n4 _
                RbdImage image = rbd.open(imageName);! Q' F5 M0 G5 u/ y9 w; x# j
                image.resize(newSize);
& E$ ~5 t5 U, N9 B                rbd.close(image);
$ Q( b' s5 \, f0 k9 i& @            } catch (RbdException e) {% B1 w5 H0 [% d% Q! Y$ e1 Z( |; X
                System.out.println(e.getMessage() + ": " + e.getReturnValue());
' ]. @" ~' I3 {            }
6 E& B5 u$ C' P+ \2 J" c5 Q     }: I1 Y% o& o& W6 O

. H! M! N, Y9 n8 b9 y0 J5 F: N; D     /**
! Z9 }0 `- |9 F2 H1 B- i- p      * 创建映像的快照
* @# w% O6 N& |: B4 s      * @param imageName 映像名称
! i* X8 j1 {: o0 F5 s      * @param snapName 快照名称6 |4 l+ D% |/ [) E; Z
      */
  R! r  k, P1 h     public static void createSnap(String imageName,String snapName){3 z* T  ^+ }( l8 C6 Y7 l; [
         try {9 M( C: l* o* q9 w: l3 w; b
            RbdImage image = rbd.open(imageName);
( P$ U1 j' m+ S9 W            //创建快照
3 ^( T" k$ w& p) ~2 j( T$ [            image.snapCreate(snapName);
! N1 f: U4 j9 ?4 o* [1 V            //保护快照可以防止快照被删除
4 q2 i+ f. k" L. O            image.snapProtect(snapName);
3 J# I5 W( i- `3 }7 i            //返回一个image的所有快照
# e+ ?1 c7 X9 J4 B/ `            List<RbdSnapInfo> snaps = image.snapList();
, @3 J1 q. z) q) _: w            for(RbdSnapInfo rbds:snaps){% o- G% m' E! U: [
                System.out.println("快照名称:"+rbds.name);
/ ~' E3 b" I- J: e1 a! e7 [0 {( _                System.out.println("快照大小:"+rbds.size);9 [$ q, x4 N+ L& S( \( s6 F2 y
            }7 l' J% K( {4 f* A$ c3 A2 }2 f* b/ |
        } catch (RbdException e) {
0 g) p0 O, _, }* I            // TODO Auto-generated catch block
& s6 {* c0 H- ~% w: O& \9 e1 N+ T; R            e.printStackTrace();6 u+ G- V( D( [7 G- U6 p
        }
3 X' K- A/ H7 ^& @' q" P; W5 u- T" t     }" a( Q# ^6 k7 s& W# x2 h3 M
0 p' A4 h4 F( p7 X& d& i, g# R0 m- Q
     /**
. a# ~# @5 M5 z( T* B. M8 D      * 通过快照克隆出新的image
0 v) D8 U2 G7 V, H& R      * @param parentImageName 快照对应的image名称
& ]8 U0 S5 A5 H4 b: d5 M      * @param snapName 快照的名称
1 q: Q6 m; J8 Z0 l4 r5 _      * @param newImageName 生成的新的image的名称; ^. }2 n! F& L% r, d  X/ \
      */. z7 J; d6 L: R. @
     public static void copySnapToNewImage(String parentImageName,String snapName,String newImageName){! j% V0 w( @9 k$ N/ ]* p9 w
         int features = (1<<0);& l0 G( q8 I; s2 O4 \
         try {
- g# O9 _6 v$ X1 h5 ^            rbd.clone(parentImageName, snapName, ioctx, newImageName, features, 0);1 e" i: m. i6 n8 D: G# I' o2 J
        } catch (RbdException e) {3 D! d5 d4 J- p5 K" E
            // TODO Auto-generated catch block7 d. [1 q8 A# W: J
            e.printStackTrace();3 \, N8 f  q1 D7 Y4 N( }# f8 U
        }
- }: z6 @/ u+ f0 w8 Q) g     }) l2 p: L0 ~* O. T. u! s( V
9 k! D8 R/ }% h
     /**
% f+ Z! {  A2 O. K/ h; {0 q2 r( L      * 删除某个image的名叫 snapName的快照,需要注意的是要删除快照,必须保证快照没有copy的子image,否则会删除失败。; \# C; K) W3 \- v
      * @param imageName9 i& u% u2 Z  l
      * @param snapName
8 y# i8 O% n) }      */$ Q* Q1 L: ^6 |
     public static void deleteSnap(String imageName,String snapName){
9 q3 C$ i, u8 d/ e( {  v         try {( ?* y) R. Q9 c! B" J
            RbdImage image = rbd.open(imageName);
6 H9 R5 _. y5 k1 Z( x- _( K) n            image.snapUnprotect(snapName);: |. D0 L+ n! i& t3 k/ b; v
            image.snapRemove(snapName);2 b' p6 i5 }7 x9 {
        } catch (RbdException e) {0 _- F7 f5 ~7 w8 P" o! m) S
            // TODO Auto-generated catch block
) Z7 A$ z5 T6 K4 N$ T4 m, z            e.printStackTrace();
1 R' h8 a' v  [& b# Q6 K        }
8 {. E) V/ u4 w     }
! E6 F1 k( _( O  H) X9 G6 Y, k4 S' M4 |' N0 n
     /**
3 ^: }8 l( c" x2 F      * 删除某一个image
( y$ i2 f* J2 m7 a& {      * @param r' B1 i6 f6 r& X9 W  i- n. |1 A2 P
      * @param io
7 C+ v: k) e! ^. s$ ?/ }" y) _! P      * @param imageName- O  l( P* P" G' |
      * @throws RadosException% ?) g- h' N8 O# u
      * @throws RbdException- R/ Q9 _- W! {$ @
      */: S" k$ R/ L! Z& I$ E( {8 y" C9 r
    public static void cleanupImage(Rados r, IoCTX io, String imageName) {
6 |- q) n/ @  p        try {- z5 k- S: T' ~7 c) v
            if (r != null) {
9 H8 K4 G2 V6 L$ ^. A: C# I7 K9 j                if (io != null) {
# Y, p( q# ]  i4 S                    Rbd rbd = new Rbd(ioctx);& [0 v  ?8 @/ `- D$ N/ B
                    RbdImage image = rbd.open(imageName);
; V6 B7 [" Q: \                    rbd.close(image);1 {6 g/ s! |/ O0 r" e
                    rbd.remove(imageName);
+ h7 n, F$ K0 D$ q( L% c/ V                }% A4 p) _* A7 y7 I5 f/ z+ X9 ^
            }
) @) [; q( {- F% W% C2 x8 r        } catch (Exception e) {8 a, \! P% S+ O5 n) \2 U- `3 |- W
            // TODO: handle exception
9 m- v  K; E& ^$ X( ~7 P6 t9 }        }  2 ?! j, V, M- M  X- U5 L* y$ J, `
     }% c( `0 S( m. E% Q: e/ z! P1 R

# C+ {9 l; Q8 N# q0 I& u( C: |9 u, z$ W+ _& T1 y6 r& o; [6 @9 H$ X
     public static void main(String[] args){3 T; H' g- m" `
         connectCeph();) r% L. o( C0 \- b4 u
         //createRbd_format1("mysql-hzb-2",10737418240l);5 M/ ]' _) O* C+ i! @' L+ K  D4 \
        //createRbd_format2("imageformat2",10485760);( [' d# `8 u  W: p; I
        //cleanupImage(rados,ioctx,"mysql-hzb");
# n1 l7 p0 d: m7 j3 R! }3 v         //resizeImage("mysql-hzb");7 n: [! {! T- @% g7 t$ R5 g

0 F$ N# r+ B9 ~# v' x        // createSnap("imageformat3","imageformat3-snap");
' o# {- |( L) g/ Y5 p7 T( r        //copySnapToNewImage("imageformat3","imageformat3-snap","imageformat3-copy");( n$ E6 v" B  C1 q$ y$ b
         //deleteSnap("imageformat3","imageformat3-snap");
% U' p3 L/ s0 k( b" A$ S9 d        imageList();
- Z7 U: P( h# @  G5 M  q     }
8 P: v0 H4 E5 I4 z}* a3 X/ F# {5 Y% i# f; X- h7 \; L
$ A7 H5 f" X' V
) c& z- L- d$ c" K7 v7 Z8 _9 v/ ]3 i
( `/ r2 V/ N: L1 o4 w4 J8 N0 r2 D, M% N
; A* V0 u# n" E" q) B. M
3.3 IoCTX源代码
- e$ L5 I$ d  X( s9 {5 k% H/*& m- ]$ c2 v0 H: @) \& s
* RADOS Java - Java bindings for librados9 a' @1 `' d6 [
*+ Z  |4 b. Q  j4 n
* Copyright (C) 2013 Wido den Hollander <wido@42on.com>4 Z) l5 T4 x8 j: s; q
* Copyright (C) 2014 1&1 - Behar Veliqi <behar.veliqi@1und1.de>
8 Z1 V8 B/ K; P4 y2 j9 y9 h *0 r& L# Z9 b' ^: ^$ [7 G1 C
* Licensed under the Apache License, Version 2.0 (the "License");
: E) i/ T' r% n4 F * you may not use this file except in compliance with
, X! K) R8 E9 I( M# T8 U * the License. You may obtain a copy of the License at& `3 l2 T1 X* h, [
*8 @+ B, ]; ?, @" K
*     http://www.apache.org/licenses/LICENSE-2.0. ]. V* ^9 ?: l
*2 R& Y+ Q6 P& d2 v* \
* Unless required by applicable law or agreed to in writing,
1 F) V  N  I, @! u  a * software distributed under the License is distributed on
7 P4 X* ?% ?! E * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,- K, p3 ~  |) J* p9 Z
* either express or implied. See the License for the specific
1 {% T  i2 H& A+ V* L& |! { * language governing permissions and limitations under the License.
  V2 w1 l5 `: _$ F */
2 w0 K4 z( n3 k2 h! f* p% l1 @$ E" M( H9 }. K/ l
package com.ceph.rados;; p, e5 x& \9 P; f# |; B* X
# O. L. b. b2 w" D( D
import static com.ceph.rados.Library.rados;
# ]. ]& d7 U: [$ {3 b, y' |
5 W! N& |# G. l9 G( k' Y1 vimport java.io.Closeable;
+ R$ x  j! P9 T' d0 nimport java.io.IOException;4 N' Z2 w6 {: i& a
import java.util.ArrayList;
$ v8 l" q! L. O2 U0 h$ A6 ?import java.util.HashMap;6 s9 Q! S; ^6 L) z; Q! F4 J; A+ X
import java.util.List;7 M8 b2 X+ L& s6 g* f
import java.util.Map;3 l$ c) E6 c4 K( P( u
import java.util.concurrent.Callable;- `- f9 a4 l7 j+ M2 r( c' }
0 Z0 ?- O, k9 p- c
import com.ceph.rados.exceptions.RadosException;# G" A3 n3 B% J% X
import com.ceph.rados.jna.RadosObjectInfo;0 M9 Z. J$ j1 ?8 y- Z2 }
import com.ceph.rados.jna.RadosPoolInfo;
0 Q4 \% ~* P2 ^import com.sun.jna.Memory;  A9 x% u8 Q$ [) ]3 e
import com.sun.jna.Native;" k" j1 K* Q! E1 }! k
import com.sun.jna.Pointer;" }5 V6 r* B/ ?6 R+ c
import com.sun.jna.ptr.IntByReference;
; }/ ]& }  A! c0 }. j) t( iimport com.sun.jna.ptr.LongByReference;* o- v: g, g: O7 U& x
import com.sun.jna.ptr.PointerByReference;
# b# T4 f9 m- l+ c
$ l- v) ?- n* q$ E% A3 Cpublic class IoCTX extends RadosBase implements Closeable {& f6 U- l% I1 ], @0 z- X  L
. }4 _+ D& l( w7 ]( A; X, t
    private static final int EXT_ATTR_MAX_LEN = 4096;2 {9 T6 Q! S  r) s6 p! ?) u1 V
9 T" c# v  x: W1 L# C' d
    private Pointer ioCtxPtr;; I3 O. U* ]) l  A
6 g# g9 [+ K2 @1 [8 G
    /**
+ s/ E: C9 }; |     * Create a new IO Context object% f* Z  i- p0 ?# I7 ~/ L
     *
+ h/ _: O* W: V     * This constructor should never be called, IO Context
, |* C4 y% L( l+ m% b7 W     * objects are created by the RADOS class and returned
4 q1 K7 k+ q* Q- V8 @. |+ J     * when creating a IO Context there& r+ ~4 i0 q+ |; x7 ~, @- j
    */
/ J7 M+ l) K5 H! t( Q/ |  L    public IoCTX(Pointer p) {
; i" G& C8 p* g' }! r: [! h        this.ioCtxPtr = p;
: ^0 j  J. k; ~1 E    }
, _3 l; t0 K5 F0 @& \! H0 \# x  W3 u+ m. _
    /**
5 Y3 v2 l( D' W/ ~( h     * Return the pointer to the IO Context' n; J4 H" Q5 s: f2 V( z8 V
     *. ?& Q+ Y+ ]" F# ^- J# \7 f3 U/ C
     * This method is used internally and by the RADOS class
, G* ~4 {% x9 B4 a8 @6 p1 T     * to destroy a IO Context
3 h4 X5 Q: r2 |9 Z5 }9 d     *: q+ n. I( P* ?) J; l$ y
     * @return Pointer0 j1 f1 Q% X0 x  D
     */# @  q6 q$ T. d6 R' v( A
    public Pointer getPointer() {3 p$ g0 Q5 o* h; e6 a+ F
        return this.ioCtxPtr.getPointer(0);3 w9 ~& @2 }- U( k2 }0 r2 Y, }
    }% c" }* d& I; A6 \

3 }( s* V4 @, s! @    /**2 g/ g/ V1 Y) A6 d# _
     * Set the namespace for objects within an IO context.; o1 p3 o. }% b: O
     *
' m3 W( }' p5 n) L' {$ r2 i     * The namespace specification further refines a pool into different domains. The mapping of objects to PGs is also based on this value.
3 u+ ~/ z* h4 `  j     *
5 d) q- c/ `+ s" f: P     * @param namespace The name to use as the namespace, or NULL use the default namespace.
8 ~! E  ]/ H# d- Z" M     */
5 r2 i+ w2 \7 F* t% ~8 x/ E    public void setNamespace(String namespace) {
3 N. A. g) L: v- P5 C' H        rados.rados_ioctx_set_namespace(getPointer(), namespace);; p; i# _5 O4 z, Y$ u
    }
4 o) Q. ?' \# d% S; W8 ?
. C, h5 |8 D1 u/ D! g1 R    /**
) w# c/ a& _' P8 }) }) }/ e     * Get the pool ID of this context+ j: |# Z1 [. ?( P% c7 x
     *! Q6 Q! p$ b; X! Z) }; o
     * @return long4 e: t; o$ {$ Q0 Z
     */
. F) E3 z) v+ O& k    public long getId() {
7 T  i. }% _* v. p) C        return rados.rados_ioctx_get_id(this.getPointer());
0 f) P& w+ T! E4 E# j) K    }
' k5 d/ f! {' ?/ q8 x- i7 [8 K( _( N, l: \1 X1 \
    /**
. o( j" O7 d3 z, T     * Set the associated auid owner of the current pool
6 b: [! C$ Y9 S+ |9 ]/ E2 A     *
0 V& G- Q- o+ X" Q9 v: ]     * @param auid3 W* ?5 ~, c7 w4 d4 ?4 m
     *           The new auid
7 _7 I: L8 _/ }" a: y0 K     * @throws RadosException
- L2 m+ j" q" g. r. u* E     */: D  x" k5 P9 t3 E
    public void setAuid(final long auid) throws RadosException {7 D; E- q5 M% y
        handleReturnCode(new Callable<Integer>() {
1 P7 o+ n) o% q' Y2 [2 F            @Override* J; {3 n/ j+ `7 Y  k3 ]2 k6 Y
            public Integer call() throws Exception {
" q) M4 d% c. r" G                return rados.rados_ioctx_pool_set_auid(getPointer(), auid);
7 u' t6 `$ `9 N$ A            }
9 U# f+ Y2 T2 G0 Q        }, "Failed to set the auid to %s", auid);9 ^* r$ g/ @8 }7 q) ^2 Q! I$ a. z& g
    }" B7 ]7 L6 R% h2 a, o- I4 R

1 Z9 _$ L8 H# r0 q- h$ l    /**/ z1 x; |5 A9 t9 D) T/ V) L
     * Get the associated auid owner of the current pool# [. X8 Z" K' \+ w3 i/ d  u2 y
     *7 z0 r% k, H3 t7 u5 \3 [
     * @return long# l9 n& E' P, l$ B
     * @throws RadosException
7 m- S( g0 B* Q8 l3 P6 }1 F, f     */0 I, t7 T' Q( l0 r, ]; Q& D
    public long getAuid() throws RadosException {% X% Z' c6 `: X2 y! s
        final LongByReference auid = new LongByReference();0 a! S, [6 y/ T. }" q! _* [7 V' ^: r

4 d; @% G* j: b! I; J        handleReturnCode(new Callable<Integer>() {5 M! T% j+ S. \9 e  P: A
            @Override
- i6 [  }; K; @, j            public Integer call() throws Exception {" C0 g8 f- Z( h; {. `2 Q2 t" K8 z* o
                return rados.rados_ioctx_pool_get_auid(getPointer(), auid);
+ P9 `! i* t8 T' t            }; ~- p; R5 N& t$ T9 ^, [
        }, "Failed to get the auid");
+ V6 F# D$ x  [+ f& ~) Q6 `. K1 M% t  q; w
        return auid.getValue();
. U4 C6 H% \" Q9 M6 \! z    }( g, o. H: x9 o. j

2 c1 o) f, G, a+ }    /**# S) P1 K0 R+ j! P; _5 e% L
     * Get the pool name of the context
4 e) o8 V+ j" n( X, _     *8 I2 P3 }# U1 i
     * @return String6 `8 f* s! S8 j. I4 {# `
     * @throws RadosException/ m% {% N1 f6 @, u6 P- Q4 H
     */8 f$ y# e4 Q/ ~  k7 @
    public String getPoolName() throws RadosException {- ~, L: ~! a% W
        final byte[] buf = new byte[1024];* J' [6 y/ z- D) E; L
        handleReturnCode(new Callable<Integer>() {" e+ l  g" b# ?, h7 a
            @Override
8 q' O9 S! m& f. m            public Integer call() throws Exception {9 S  p" W3 _. j7 t  |! U" p& C
                return rados.rados_ioctx_get_pool_name(getPointer(), buf, buf.length);& h. E3 s0 ~2 N5 o$ x! k
            }' ~# v. p* F4 @! {, X3 E
        }, "Failed to get the pool name");
1 Z& ?! @3 X, i' |% a! {+ z        return Native.toString(buf);
7 {: _( X3 _4 M5 p/ `; ~) B    }5 k: G8 V3 o* C' L) T

5 S7 a3 Y, A" Q7 Z$ h. m  ^2 l    /**4 ~' o8 F. w& f0 E( o" L% W
     * Set the locator key
/ Z# s% g3 g) y5 G& p3 ~  Y5 h     *
' M1 H9 M$ c# Z     * @param key( T: ~) s/ b/ W- @- F
     *          The new locator key or NULL to remove a previous one
  B4 t5 f: ~* O' ]     */
% E: v: v5 O. N9 p' K6 A    public void locatorSetKey(String key) {0 q: f4 Z, P( J4 X: q
        rados.rados_ioctx_locator_set_key(this.getPointer(), key);! F6 F7 o- u% V* l7 \
    }! s6 E% v+ l$ l

) u+ E8 F, n4 J% g0 R5 m6 N0 H    /**
7 j  Z3 W8 d3 H! E/ J     * List all objects in a pool" G! S, [0 I7 b5 R+ O8 P% p: ]
     *
. U4 {6 h+ B8 P( }     * @return String[]% Z! z! j# l! q0 w$ Z: {
     * @throws RadosException) g+ }9 y+ D7 ~
     */
2 T0 P9 ~6 b, @# c+ Z    public String[] listObjects() throws RadosException {+ f0 R9 O0 E" ]! y% G
        Pointer entry = new Memory(Pointer.SIZE);
2 a! {1 p" _$ {1 Z) R$ @        List<String> objects = new ArrayList<String>();
* V7 X: B. _, q2 T  ^  M        final Pointer list = new Memory(Pointer.SIZE);
# I! q6 I+ w5 z( J6 T" h; b' m
" O  n4 Z8 Q: R' D& Y# L9 b/ y% t        handleReturnCode(new Callable<Integer>() {
3 V4 F( `4 l- V+ g) e            @Override
6 m, g. i, C7 Q$ f2 V            public Integer call() throws Exception {) U* t* p+ w" x# Q
                return rados.rados_nobjects_list_open(getPointer(), list);
8 f) S- J, \2 ]4 N4 j            }
3 u+ x3 Z- B1 ^! m# b        }, "Failed starting to list all objects");4 L' i1 L" Y! o! ~4 i! p8 ?6 I! _1 s
5 j/ [/ C) T" q1 ~: @+ q$ [# K
        while (rados.rados_nobjects_list_next(list.getPointer(0), entry, null, null) == 0) {
- C: D. r' I$ r; y            objects.add(entry.getPointer(0).getString(0));
$ {. ?# a7 E  n7 j5 p% |5 p1 a# ]        }
' w6 U% E  ~1 H" }5 o2 e
6 J6 |, A1 |/ O. {; e& F7 m$ o: d        rados.rados_nobjects_list_close(list.getPointer(0));" G0 {' |8 Q# v1 F

4 N& S/ X8 p8 k        return objects.toArray(new String[objects.size()]);
- V6 M& s) f2 r: W    }- r. B" r1 m% n6 k

9 ?2 P& f) N4 m) U! n5 G& z& r    /**
1 J2 A( t7 l# r  i     * List all objects in a pool by piece. Useful if a lot of objects are in the pool and do not
3 r2 Q! c6 T4 f1 W- r     * fit in memory through listObjects() method1 F, m5 E. [( y3 o9 h
     * @param limit
. [! X1 d% }# m% z) l. A7 u     * @return a ListCtx from which nextObjects()/nextObjects(skip) and getObjects() could be called
2 u$ X  E  j+ Z9 M) {     * @throws RadosException
4 W8 s/ k8 t. g6 Q. s/ j     */
; w0 \( k3 k2 B- U    public ListCtx listObjectsPartial(int limit) throws RadosException {( R. i( }3 s0 {5 O
        Pointer list = new Memory(Pointer.SIZE);
2 C$ p7 i+ Y( }  S- f1 d2 |$ w5 s9 P$ R  \+ Q+ X  E
        int r = rados.rados_nobjects_list_open(this.getPointer(), list);
1 ^% _% S0 v/ c+ j        if (r < 0) {
8 s  @' G: ~9 }# Y! i            throw new RadosException("Failed listing all objects", r);" M( W& d& E& h, c# d
        }/ g) J, _( E. G
        return new ListCtx(limit, list);
5 x9 n5 _) u! f  Q# x- A    }
  m8 \0 ]7 c- E' A5 Q9 }3 ^
  k' x! t/ [# d/ H    /**3 o6 x+ g% s1 D  j! L
     * Write to an object
/ N6 k& ^4 i9 d: p$ t. A* O6 U     *
3 Q* w, v8 m6 z( M     * @param oid
, z) e5 w  _% o. ]- w1 D     *          The object to write to7 _! U/ q6 _$ Q8 I
     * @param buf
1 `' R6 q1 O- [3 i7 t* m' q     *          The content to write' h' w& W! t: y
     * @param offset
$ s# i& ]7 T7 e% v$ e9 ^2 m" N8 K0 ^     *          The offset when writing
6 I% R: K9 I6 P6 v' x     * @throws RadosException
% k0 E1 U2 w  L* j     */
; R7 B% t" z# J1 q  C( m4 o$ r    public void write(final String oid, final byte[] buf, final long offset) throws RadosException, IllegalArgumentException {1 W! y- z' H7 ^( |" L2 p
        if (offset < 0) {$ T2 J& O2 c$ ]! N
            throw new IllegalArgumentException("Offset shouldn't be a negative value");
$ h' G4 O" s! ?' j* I- w0 A1 h        }/ Q: B$ I6 a0 v, f/ F( ^5 ]" I
        handleReturnCode(new Callable<Integer>() {9 b  G2 h- c2 s& {2 m! G: b! I
            @Override( w* }' D2 f# t% m, o: ]$ L
            public Integer call() throws Exception {
+ ]' i) X4 ~* d+ g4 t                return rados.rados_write(getPointer(), oid, buf, buf.length, offset);! H, P% x* [. a+ \# T" n7 p. ]8 G$ ~
            }
9 I) n, w: f) N5 K. ?7 G        }, "Failed writing %s bytes with offset %s to %s", buf.length, offset, oid);
4 d; L# j4 I3 f    }( w$ }  [* g" s

3 z3 B( t- C" z4 X    /**5 L6 j. o6 B: r/ y
     * Write to an object without an offset
6 X* d. c7 K; H4 f/ R     *6 u9 t! E: s; v2 h5 S+ q
     * @param oid
& M: M$ T9 H3 c$ [" X     *          The object to write to
6 o1 m" @! H8 x. o- N     * @param buf: H# O. K4 Y3 [; x1 A
     *          The content to write  W' c2 K, v1 j, h
     * @throws RadosException' ?' n4 w8 m7 P# @1 E
     */4 R: S4 s- j$ |) W
    public void write(String oid, byte[] buf) throws RadosException {
" `3 I4 z7 H$ I" R# ~5 S8 x: u        this.writeFull(oid, buf, buf.length);
" p+ m- d0 a( ^& x: O* w# w7 ^    }
$ D  D4 V( G! m) C  [3 F+ [6 W8 @+ M& G, Q. N) O
    /**
9 B% r$ A7 B% G+ w     * Write an entire object
! H0 v9 H6 H; R1 m     * The object is filled with the provided data. If the object exists, it is atomically truncated and then written.; r% b/ ?3 u+ G7 `6 ]! [0 K
     *& Q. w: y: ~7 ~, \' \
     * @param oid
6 K$ m" f) R  C  N- _' o     *          The object to write to; d! u: z7 }( v# }" ]9 i* D
     * @param buf
* ^& l  O4 Z4 x* e5 j* H     *          The content to write; d) M: S: ~% v4 J+ N
     * @param len: t6 [( D* y2 e  T* A- ^3 f* c" w
     *          The length of the data to write
; `( l: N/ A* ]     * @throws RadosException
4 H% @: e' c! m0 i2 }  S3 E1 n     */! d" W$ f7 \5 O6 a' H. P- ~8 A7 ^
    public void writeFull(final String oid, final byte[] buf, final int len) throws RadosException {
& m, F* n1 h4 [% O! u& e9 D8 }        handleReturnCode(new Callable<Integer>() {$ Q( e5 {" ]4 e
            @Override" l: y4 Q. @2 h& k1 v; v
            public Integer call() throws Exception {
- y0 y, R- p5 c: S7 A6 k                return rados.rados_write_full(getPointer(), oid, buf, len);
. t% f4 \  r! t- a            }
% \8 W* \$ o; @3 h$ L3 `        }, "Failed to write %s bytes to %s", len, oid);
+ e& z3 P) _% C1 g7 p* L    }' G0 d3 ?( v4 p: v5 f
* K' n) h4 o; C) U
    /**6 ~: ~0 D0 D# Z  D
     * Write to an object without an offset
/ ~# b* K9 H# t! f     *
- z6 }) s) R0 [5 C! h% Y     * @param oid. E* ^4 z  i1 D2 Q* F! s; e% `! K
     *          The object to write to
2 X# H% A4 P+ A0 ?     * @param buf2 I- q$ _  A" P' I) E* P
     *          The content to write+ z0 v6 z' ~9 ~* J
     * @param offset
3 N2 W* Q6 S9 H+ k" q" _8 ]( ^     *          The offset when writing1 |' u$ j4 [1 V# p+ |% g+ p
     * @throws RadosException
" K' n( E; B$ a  w! r  ?8 X     */" \- Q  ]8 a6 d% z8 i
    public void write(String oid, String buf, long offset) throws RadosException {
7 v& |. T/ s! h( c: \/ p5 o. Z        this.write(oid, buf.getBytes(), offset);
* o2 T" p2 @# u; d+ L    }+ q: ?3 u1 a+ ?0 O4 i
  s5 ?( e3 ]' e3 E( i- [& E4 m
    /**
4 t' |9 K4 T# S4 h% q     * Write to an object without an offset
% \  N- P' }! {* v2 u8 x  v     *3 {6 N5 A5 v1 c  Y
     * @param oid7 l- x& D# T$ ~/ |+ e6 U! l' h& l
     *          The object to write to
! x5 e7 J! [/ }/ S/ _2 d     * @param buf
9 N- S) q) c( F0 l     *          The content to write
( p; `0 ^- k# a) T) x     * @throws RadosException/ Y/ f; K8 D5 O1 J& y
     */
( a  p/ E6 k+ f    public void write(String oid, String buf) throws RadosException {
" W8 q) u5 F9 C  Y! a4 a+ R* m        this.write(oid, buf.getBytes());
1 q8 ?! G! d  `9 \' C    }1 {1 Q! t: ~# V8 E4 O
) P/ S3 d- E! s/ O9 v" L8 {
    /**% s' \0 h" D/ D& T
     * Asynchronously write to an object8 ]- H. [( C8 [: j" `
     *
7 o3 n" P6 g* q- S0 b     * @param oid
9 E# o9 Q$ i6 q+ Q     *          The object to write to
3 |" r& @. R# A5 H     * @param completion0 Q! a) l7 M  i, r
     *          The completion instructions
- K" @- k, x; o( P1 |6 l     * @param buf
7 V5 P$ B8 T* _7 A9 G; m9 b0 n     *          The content to write
& z" ?/ b3 U3 @6 x$ {) J# M" d; V     * @param offset
$ Y- J6 X/ k7 u+ y     *          The offset when writing9 A' m& K' l9 i  ?
     * @throws RadosException1 w; H0 Q( l% G) o' r4 n: K
     */
; n; y* X4 x* W% f% `6 k8 t- i; M+ T    public void aioWrite(final String oid, final Completion completion, final byte[] buf, final long offset) throws RadosException, IllegalArgumentException {
, v/ d  R" w0 Z1 a        if (offset < 0) {
3 k+ x$ j2 R/ E* W3 E) [            throw new IllegalArgumentException("Offset shouldn't be a negative value");
0 U6 k* p% W% A# ?6 `% B$ E        }
* C# o8 F" T0 c* h  Z: N        handleReturnCode(new Callable<Integer>() {; m' E0 e" c! `9 S+ L# _
            @Override
$ U1 f& t) U' M- P8 W  W* v            public Integer call() throws Exception {
! r2 G+ l  T3 r, y; _                return rados.rados_aio_write(getPointer(), oid, completion.getPointer(), buf, buf.length, offset);2 f% F5 K7 U" j7 e) j6 a+ T( E& Q
            }2 E$ {4 j5 U& T! h/ R
        }, "Failed AIO writing %s bytes with offset %s to %s", buf.length, offset, oid);' d" R6 v- r! m; X% x
    }" o) x+ c% f# y

, M- y6 W$ h: L3 f    /**
4 r4 U- ~% @' m     * Asynchronously write to an object without an offset3 r1 X9 x1 K( _' b8 v; n/ l
     *8 l7 g  Z% J) l
     * @param oid8 M( @% w! o* F3 ?- n3 c0 R) M
     *          The object to write to5 p( {0 `  }- G$ b1 J
     * @param completion  T8 D! h! |- ~/ B/ Y' x
     *          The completion instructions
) R' x! j5 s0 X# @: N6 z- J     * @param buf
/ I1 P! x! x: y' `6 o! o7 P     *          The content to write) `# e) H4 N) s
     * @throws RadosException! K! v5 G0 P7 C: ^
     */. }& z5 r% a( ^" u& x
    public void aioWrite(String oid, final Completion completion, byte[] buf) throws RadosException {; B; w( s$ s4 n  C) c/ E7 b2 h
        this.aioWriteFull(oid, completion, buf, buf.length);% B$ ?% r$ v8 a
    }
4 ?. E, ?2 e$ Z+ x* I$ Q' C0 D$ i% h2 p% J" U7 \, ?) i8 X: ^6 x) H, f
    /**8 R7 v  J  J+ @  u+ `
     * Asynchronously write an entire object
4 N' S4 Z1 d: H0 S6 }% ]     * The object is filled with the provided data. If the object exists, it is atomically truncated and then written.
( I, d1 H1 ?7 C' Q, b     *
( h# S2 e( a2 X, H/ Q     * @param oid9 V0 x( h1 m; A* T% R
     *          The object to write to
$ w6 [8 I, z7 v# m, E5 ?     * @param completion
9 u7 s, H  G% Y& l2 n     *          The completion instructions8 X+ v/ R- g  e0 u1 R. @. t+ W
     * @param buf) Z- y7 C+ i  e( t6 ?  \7 a
     *          The content to write
( M, A9 y/ Y8 X' b. F9 L     * @param len7 D4 a: u( S8 s9 j/ V
     *          The length of the data to write" @) Q$ g( k. e! T  q  s5 j
     * @throws RadosException! u) l+ ~+ j4 E* b) f
     */
  I% _. \9 n2 i2 y9 A- @' C    public void aioWriteFull(final String oid, final Completion completion, final byte[] buf, final int len) throws RadosException {1 ~! q3 p% {8 J1 z1 \
        handleReturnCode(new Callable<Integer>() {# D$ g/ S7 O3 j$ Q" Z; N, M: U, |
            @Override
7 K# K. q7 q* z            public Integer call() throws Exception {% v7 m2 O6 V9 l; |: ?7 [' h
                return rados.rados_aio_write_full(getPointer(), oid, completion.getPointer(), buf, len);
3 ?1 H6 ]2 d4 u& K# B0 |            }' f9 u1 x9 v* Y8 C
        }, "Failed to AIO write %s bytes to %s", len, oid);
6 _6 i7 a( T# U, K5 S  i' t2 }    }& Q( D, ?% @8 d8 J! l! T

' d# T" T( ]" ^7 p/ x1 D    /**2 _: ?2 p9 t$ B3 t
     * Asynchronously write to an object without an offset
( Y& A4 p4 o4 A2 x7 H" d$ J     *& ~6 c; v! P# `
     * @param oid
4 a- e7 U( [# i  _$ @; F     *          The object to write to
  D" X' p4 n1 E     * @param completion* |9 f9 [+ A3 k% R4 K+ z
     *          The completion instructions
! A7 u( r! S' R$ _# X) o     * @param buf
; W7 c3 z5 y# Z  i/ }0 I     *          The content to write
: E% `# S7 `! s6 e2 [0 G     * @param offset1 D5 F: ^# b8 y* {
     *          The offset when writing  w5 ]/ T9 ~4 y  _9 f7 y! ?! `+ B# X) \7 b
     * @throws RadosException0 K$ S  h& n" r  L
     */# f( l6 s1 j4 z# F
    public void aioWrite(String oid, final Completion completion, String buf, long offset) throws RadosException {# X, v' G% y2 ~$ _
        this.aioWrite(oid, completion, buf.getBytes(), offset);
! G4 Q, Z" `+ Z$ A    }  b5 }8 }$ `- C- C9 D* F
8 C5 K/ A: i/ T# ]. \
    /**  W+ X$ |- Y1 P; c
     * Asynchronously write to an object without an offset! p$ f7 y+ P0 x% l6 j
     *% i, ]9 }3 @( |2 I' t. z6 [
     * @param oid8 j  S# x; Q" q0 m1 d, t! R! O% E
     *          The object to write to
" G8 r7 [$ _" G( f& @; ^     * @param completion/ @+ b) c/ R9 v- u! u. `( Z2 }5 S
     *          The completion instructions; Y, Q. G4 z9 N( `
     * @param buf4 I: B# {' h, Q  e
     *          The content to write
- O* V3 }# C3 W8 r. v     * @throws RadosException7 j5 W$ L, U5 k, L: k3 E% O3 a
     */) ^& l3 ?* H2 Y. {( I0 c1 W4 y
    public void aioWrite(String oid, final Completion completion, String buf) throws RadosException {) V) k1 J( ^0 b( f' |! @' w
        this.aioWrite(oid, completion, buf.getBytes());+ M+ ~( i7 `9 E8 b' T/ P9 {
    }
# L, o3 E( `8 a
$ ]+ W* M# m  n% K8 i% I    /**& F8 v  g) y  f7 O
     * Block until all pending writes in an io context are safe.
  ~0 t$ |# ?# U1 E. z  g     *7 [1 s' I' c3 q- U6 E) C# Y
     * This is not equivalent to calling rados_aio_wait_for_safe() on all write completions, since this waits for the associated callbacks to complete as well.
' e: @# l1 Z3 k: U; m$ }     * @throws RadosException5 |8 d9 Q6 a8 O3 `; L& W
     */5 {! J2 o2 T* o. o' n0 u
    public void aioFlush() throws RadosException {
5 {% L3 V# I. ]) @# x8 q        handleReturnCode(new Callable<Integer>() {8 V+ o; M& C% B" `
            @Override2 z2 r/ ~* {' y, P+ Y4 i) {- }
            public Integer call() throws Exception {/ C; d, A( m. c5 J. Z9 S9 ~
                return rados.rados_aio_flush(getPointer());9 B1 K; _9 k- r, B
            }
$ y9 R  u5 h( J. \. W        }, "Failed to AIO flush");: d9 r, R0 E+ W3 W- L) \2 J8 q
    }
( y9 _) e. Z2 \" G' q
' k6 n5 }6 E0 q9 b" H9 q2 C    /**
1 r; e( r: C6 b+ d9 t# y  d8 k     * Remove an object( j; }+ ?3 F# H0 |* x, ^
     *
+ L1 v) \+ v+ e; V8 P/ a3 s6 `     * @param oid
0 x1 s' y) H. ]: z     *          The object to remove; |% p4 ]+ l5 Y+ r4 f
     * @throws RadosException$ ^- z* ^9 {& L& ^) U6 m  U
     */1 I1 l7 L: Y+ V( v6 |; W2 ?  ]
    public void remove(final String oid) throws RadosException {
9 [7 T" A% g' u4 r3 c& T. P        handleReturnCode(new Callable<Integer>() {
' J- |, T; S7 w+ D& W6 i0 ~            @Override
' u  c6 @5 t8 C9 Q. X# i" {            public Integer call() throws Exception {) `& N# |6 |, Q/ w' n
                return rados.rados_remove(getPointer(), oid);
, W) k5 R0 G/ `3 i2 P" ]            }
" F5 j/ A" {3 [5 p& i! Q1 M        }, "Failed removing object %s", oid);
& Z6 t( G6 o. @$ e! a    }( [9 ?3 {! P3 ^+ W! X

/ p; v1 C, C* N    /**+ q$ j3 u( k- T  F4 X
     * Read data from an object
! O5 T' o5 J- @! l7 G) z1 y+ |, g     *
* g4 ]% c3 K+ W     * @param oid
8 |, R/ U* B# \& `* ^     *          The object's name5 c% P( D: t) N% |* Q, V  V) t7 y
     * @param length& W2 m( b% U/ T( t9 F& a
     *          Amount of bytes to read
* \, u$ N! `6 [! S9 p     * @param offset
* j6 x5 u0 a. v+ o& a. I     *          The offset where to start reading0 G8 @& E4 b; }
     * @param buf3 Y. R# x9 z" {" y; e
     *          The buffer to store the result) Q3 h6 V; R4 U0 o
     * @return Number of bytes read or negative on error
3 n, }" j+ H: _     * @throws RadosException
( S$ h1 M% h. m  w' c% q) F     */
2 M% u! ^6 u' ?) u    public int read(final String oid, final int length, final long offset, final byte[] buf)
+ G% ]. L; l" F            throws RadosException {
& _1 u; I2 a/ x2 p        if (length < 0) {% l! a2 d- e$ }* W3 \( d
            throw new IllegalArgumentException("Length shouldn't be a negative value");7 N, q6 p- @+ h8 {. ~7 E) v, i
        }
; y2 [8 f) z) ]: K: X# n6 j        if (offset < 0) {7 w2 ~/ ]+ `4 d' Z
            throw new IllegalArgumentException("Offset shouldn't be a negative value");7 @. T, M7 s; K0 B- a( W3 r
        }3 Y# I5 G) p* A/ n! [5 ~

3 e$ C- J2 T% J0 [7 v        return handleReturnCode(new Callable<Integer>() {
3 N, `) O; I! T6 a% u( F# n" t% W4 r" S            @Override
6 y4 @+ f1 y* u# A# H# Z) T            public Integer call() throws Exception {; r+ Z2 D& j2 G" _0 N. k- u& N
                return rados.rados_read(getPointer(), oid, buf, length, offset);: _# {$ O% ?/ L; g* x6 ?( j
            }
+ b$ l5 Q9 z3 `$ y# w        }, "Failed to read object %s using offset %s and length %s", oid, offset, length);
. K  Q! Q) o% }2 C6 y8 f+ @' u' N+ ]1 F    }4 S  p, P' S0 z" O% R7 j
7 R1 K/ [; [6 b7 _! U) E" i
    /**+ e3 U; \% P0 P# a, u
     * Resize an object& B: A( W. J  A7 r. Q9 @4 V
     *; S! i  v0 x6 g# p/ S, P3 d3 o
     * @param oid6 X* Y- Z4 p8 h4 X/ P  J+ |
     *           The object to resize
$ v( t3 y% ]! e3 [. s4 W     * @param size6 E# P7 F2 u7 y% u( v9 X
     *          The new length of the object.  If this enlarges the object,
5 H  k  J5 `1 {     *          the new area is logically filled with3 X8 o  J+ }7 D+ J5 \
     *          zeroes. If this shrinks the object, the excess data is removed.8 `! Y# Q  [  X0 e) w( h
     * @throws RadosException5 P1 i" f+ P3 |* D, A% E
     */
' \: V7 x* k& E: ?; `( G0 k    public void truncate(final String oid, final long size) throws RadosException {0 F& i& _$ G: y( ?
        if (size < 0) {# g7 D" s+ E. e/ m& O
            throw new IllegalArgumentException("Size shouldn't be a negative value");
8 }# ~( ^/ ^9 z; G+ w3 u" P        }
0 v+ T% G5 b+ I/ R# O& y- e1 v        handleReturnCode(new Callable<Integer>() {
2 ~8 m, }9 }5 w% _            @Override% e& U) _/ I& S! u" E8 W  R2 N% M
            public Integer call() throws Exception {% \7 U: B5 x+ m) d6 }2 ], O
                return rados.rados_trunc(getPointer(), oid, size);
5 j0 A5 {* J$ c0 E2 q            }
2 P7 F5 Z% w' u5 t: a( X  e- P9 C        }, "Failed resizing objects %s to %s bytes", oid, size);
. ^$ |4 I( z7 ]$ V3 Y% a( v    }9 R4 k& h$ S6 u6 I2 G2 [, T- N

% W4 K; p5 _5 e1 Y2 F" O" P  h    /**& q1 L6 x4 K. a
     * Append data to an object
( B+ z; F* W  e! K2 ^, J; X     *) D( `0 V& R: Y+ Y4 D) Z5 l: L
     * @param oid% s1 i# r1 A* X) i" J" a* `
     *           The name to append to
# ?0 D! ]. M; q( s2 c     * @param buf
7 Y( A" Z, D  W- Z" e     *           The data to append8 X: `$ P! Z8 I/ Y% p0 A  p/ g' n
     * @throws RadosException
. Y4 ^$ ^4 R2 O2 W8 F% `( L     */
" q% d3 i: y1 S' X% q    public void append(String oid, byte[] buf) throws RadosException {
) U- D5 f% B: O- t3 x1 S+ f  v% P        this.append(oid, buf, buf.length);( p9 p, D# w' i. f; @7 U( l
    }: C: T2 A8 [& V) N: w

/ x3 H# s. h. U! S/ d    /**
# B6 s( i: Z% J/ W  Z% }     *" r. l! S( P8 i# F3 k% }( X
     * @param oid
1 g0 B1 ]% m& U2 i6 m     *           The name to append to
, Z5 B, @5 {$ }# _' b/ _6 g7 \     * @param buf3 C5 n0 S/ }, `3 r
     *           The data to append
) X9 {4 ]$ H; l     * @param len
  r$ X2 w+ P( y+ q- z( j     *           The number of bytes to write from buf0 V; X# l3 x% o( D
     * @throws RadosException0 [! ~9 f8 i. v, b
     */9 i$ E( r  V9 L9 z/ P  E
    public void append(final String oid, final byte[] buf, final int len) throws RadosException {0 R; F/ D  d0 s2 }9 e
        handleReturnCode(new Callable<Integer>() {- B0 w( E$ {. V$ r2 n0 \1 `: a
            @Override3 S! K+ i. C6 |$ N
            public Integer call() throws Exception {1 j7 ~4 z8 B$ t0 D. K
                return rados.rados_append(getPointer(), oid, buf, len);
7 ~; f4 e. T. J4 p. d5 s            }/ b& ~$ n6 p. u8 J( T( y
        }, "Failed appending %s bytes to object %s", len, oid);6 {+ r- X! Q% S; S' k# C
    }7 n$ ^3 g( [6 L
* d0 D) g3 c. f, W6 m  `% J- ?! e' ?
    /**2 O' i/ O- R# e( b/ ~! \/ J, F
     * Append data to an object
! p3 _" a3 {2 e( ]" \% K     *. _- o( L: K3 m/ ?8 I
     * @param oid# b9 L: j) R! V% N( A# o
     *           The name to append to7 c. c( n, `5 U, \
     * @param buf
5 E& I' T5 e9 `$ c7 t) z" ~; i     *           The data to append
( C, k/ W2 n! n     * @throws RadosException) q, O, |; e% S- M
     */6 O! Z( j' }1 B
    public void append(String oid, String buf) throws RadosException {" t3 K  j" x! Y
        this.append(oid, buf.getBytes());
3 ~% L4 q" }! q, F! d+ Q# b    }
5 N1 ]& t5 b( h# s2 A" ]- |* u% \: v. }8 e* p- H/ ]( d* v/ C
    /**2 t( G$ o2 d  H1 D4 y- u8 A8 \
    * Efficiently copy a portion of one object to another
' d# {4 |) ^/ [) k; W2 i. u    *) e: z0 a! w0 x  ~7 g3 R% O
    * If the underlying filesystem on the OSD supports it, this will be a
5 g! i+ ~, J" b0 M( Y    * copy-on-write clone.  I8 x3 M% f. m' v/ z" z7 v
    *
3 g, K) \/ `  u" ?% l$ T    * The src and dest objects must be in the same pg. To ensure this,8 u4 u) M7 }1 I0 G2 H8 I1 u
    * the io context should have a locator key set (see IoCTX.locatorSetKey()).
+ @3 G8 E; H5 c/ A    ** ~" @5 E0 b$ y+ h- W  C
    * @param dst
" G8 ?1 m$ H9 Y% i( F. g7 w. N    *          The destination object% j. i: u. j3 @4 g  K+ s
    * @param dst_off
$ F3 `' ]: o0 p3 [    *          The offset at the destination object
8 ?; u6 f$ z" i4 P+ F9 l! A- r    * @param src! h7 i4 j& D# Q: C6 {- C
    *          The source object
# f+ J8 q  H7 @$ W+ c' z, _    * @param src_off3 m3 I8 I" O% S: M) D4 U
    *          The offset at the source object
- r% B/ e. A+ w8 T    * @param len$ u( p8 M7 c3 ]: b
    *          The amount of bytes to copy
: R. F. e/ s' Y. b9 Z3 L    * @throws RadosException8 R# C6 K& D6 h! }
    */# }) w. _# A3 E) h+ B2 Z* r
    public void clone(final String dst, final long dst_off, final String src, final long src_off, final long len) throws RadosException {
$ f) l2 F0 p% n4 C6 l        handleReturnCode(new Callable<Integer>() {  X( G* |; S$ i: Z
            @Override
' y- W  f* a! U            public Integer call() throws Exception {( o& _3 W8 G' u6 E& g' B7 j" \  D
                return rados.rados_clone_range(getPointer(), dst, dst_off, src, src_off, len);1 L2 ]3 i% D* H9 f0 M0 X2 P
            }
" ~, S3 r; G* \: H- U        }, "Failed to copy %s bytes from %s to %s", len, src, dst);$ p" d& l/ `8 W& b
    }. L; i# q9 B$ [$ z

5 A' a* V8 T5 j1 ?# D  ?6 x1 J7 l    /**$ o& v% i- ~  N1 t- J
     * Stat an object
( a6 n% y; N! L# \2 _- b; ^     *( O; ~8 h- ?- l/ b, W" K7 \
     * @param oid3 F! R% w% m( W0 L9 K
     *          The name of the object
( J1 }/ V, b6 u3 w# H& n& A     * @return RadosObjectInfo  _& t# i  O" m  ?* y8 \0 e* R
     *           The size and mtime of the object
; X; I- h$ p& M/ E% c" V     * @throws RadosException
8 X4 \& L) l+ x6 R4 y; V     */
( T. I/ ]2 |/ f$ \, k% n3 |    public RadosObjectInfo stat(final String oid) throws RadosException {
- O+ W" T, f5 b+ G4 G: {        final LongByReference size = new LongByReference();
. e: g- \( d# i: a5 L! {* }$ M( U        final LongByReference mtime = new LongByReference();0 h/ b, }9 Z+ x6 c3 O9 Q
        handleReturnCode(new Callable<Integer>() {0 q0 }' w6 V  S5 g: E
            @Override7 k# z: W( U$ Z2 n
            public Integer call() throws Exception {
6 L7 J4 c7 U: }, \% U                return rados.rados_stat(getPointer(), oid, size, mtime);
& Z0 A! b+ a* r  Q            }& }3 {* g2 z' }* r4 N' w
        }, "Failed performing a stat on object %s", oid);  i; X: Z/ P. k: O" s9 P$ @
        return new RadosObjectInfo(oid, size.getValue(), mtime.getValue());
$ o, Q! S( ^- L    }
# B5 t/ C* p, c/ p3 |$ s# D, G/ \  T
    /**4 A$ A/ d8 {, R  x; D' ~" \
     * Stat the currently open pool- f& L9 E' t" h/ J
     *% G8 r7 t: b. n/ ]' N9 z; j2 v
     * @return RadosPoolInfo$ w, X, n! p6 X/ g; c# q
     * @throws RadosException
7 J+ P' Y- L/ v% B     */
. ?, ^. A  g) I4 [7 g; t, l$ w    public RadosPoolInfo poolStat() throws RadosException {+ \8 w6 \$ s$ e; V; o( Q
        final RadosPoolInfo result = new RadosPoolInfo();3 W- |, |' w+ W: P* |1 ~1 w
        handleReturnCode(new Callable<Integer>() {! S1 v  U- C# O: S0 q0 ~/ U* k
            @Override
, a  S. C+ d3 X9 N4 g            public Integer call() throws Exception {
6 j1 X2 v% Y) [                return rados.rados_ioctx_pool_stat(getPointer(), result);
( C" e0 \7 q$ j9 G, N            }
" V" ^1 N+ B: G8 G# ^& t; F, d        }, "Failed retrieving the pool stats");, e2 c9 d6 X0 m6 |
        return result;7 z" j( R, v* |4 i
    }
+ D, X& [0 ]8 p" f& Y* ]
% [8 D6 a) d0 |+ _# ^    /**6 N& e0 J* k$ h2 F) y7 D9 q) K% i- D: I
     * Create a snapshot
* O; R7 I0 m4 k2 c     *& c: ~8 o' n6 a! B) c
     * @param snapname
  X5 q# j1 v7 `     *           The name of the snapshot! r, E& @( [$ O$ Q5 u2 N
     * @throws RadosException4 a+ E: n8 H% a3 ~1 h+ L* S
     */) N2 j4 b( H6 {7 h5 l, }' K+ g
    public void snapCreate(final String snapname) throws RadosException {
) a* j6 e& I/ j. ^1 Y$ Z0 Y        handleReturnCode(new Callable<Integer>() {
  j, ?+ B/ W- d9 U            @Override
7 l# U0 n% M: U4 [0 r( Q            public Integer call() throws Exception {" _9 F& z- M2 e$ w) h1 i
                return rados.rados_ioctx_snap_create(getPointer(), snapname);9 ~2 J0 A& |2 N4 C  S
            }/ q4 l2 q" _- O# y' w. M: \5 i
        }, "Failed to create snapshot %s", snapname);
" F% h, i# y% c7 d3 W, R  ~  r    }
! w  f+ o* e: {2 J' H  p; m+ o' A0 ^6 u
    /**
6 r* k2 h$ R  v" A1 h' f8 a0 d     * Remove a snapshot6 u, J7 e9 Q! t, V3 a% N1 O4 p9 s
     *; Y; a, d5 L  O: ?3 D
     * @param snapname
3 n8 f( U9 i6 q, v1 H5 ~     *           The name of the snapshot) f2 X  r9 p. Y; q' d9 t2 b7 }
     * @throws RadosException% E" E0 R1 V3 b5 s
     */6 R- p1 P- k' {* Z/ |- v, Y
    public void snapRemove(final String snapname) throws RadosException {
8 H- N2 }' ~6 b9 q        handleReturnCode(new Callable<Integer>() {
! d# ]9 C' ?8 f! A) P. R4 h. o( L3 |            @Override
7 A4 \" j" Z( G9 w* E            public Integer call() throws Exception {: F- G9 Y7 Z$ J: J8 `
                return rados.rados_ioctx_snap_remove(getPointer(), snapname);0 I$ z9 a) @" ]: T4 x5 Z# t8 M
            }% a4 {- n6 O5 z; Z5 t. Q
        }, "Failed to remove snapshot %s", snapname);" M) Z' f* I. X! s
    }
* _* k# }& \+ K7 L4 F% M# P7 v& l6 S6 j9 Y$ T
    /**0 u& @/ I' \9 a  `$ a. q) w
     * Get the ID of a snapshot
) H5 u- J: `! }1 W     *
, {" P8 {4 y. V3 [  W5 v; J     * @param snapname
& w$ Y: e$ ~" {& h9 D     *            The name of the snapshot
4 l' A+ o0 D) W     * @return long
6 H, U3 _$ L, K6 P# @% k     * @throws RadosException
# r& D$ `- p  Y9 n  o( b4 K     */
/ Y+ M' {+ R" g    public long snapLookup(final String snapname) throws RadosException {1 }- \4 E" W. a& Q* X$ Q3 j) b" [
        final LongByReference id = new LongByReference();
+ G9 R: i2 y- i9 t( i        handleReturnCode(new Callable<Integer>() {5 ]3 Y2 V) Q0 T; m$ A/ O
            @Override
3 X: E% V0 z0 e1 r' q" E! D/ j6 c            public Integer call() throws Exception {' }/ J8 f# A1 i
                return rados.rados_ioctx_snap_lookup(getPointer(), snapname, id);( n8 Y4 e/ L! J
            }
5 x' H' i+ M. A. ?+ `        }, "Failed to lookup the ID of snapshot %s", snapname);6 z; c6 G" z6 u) i) P+ F( _) q! F4 v
        return id.getValue();  f$ d$ @" _- E7 W+ Z2 V
    }5 o+ [- f- `7 b% m% ?: A1 ]1 _

  \2 P) P- S' B0 A% O7 M    /*** F9 m0 ?6 B: ]& G
     * Get the name of a snapshot by it's ID2 @/ B' Z/ q7 E. V, h  o* S
     *
1 w7 o6 t2 B; j9 p1 Y+ S" Z     * @param id
, ?$ D  ~; ?. p+ C! c3 {     *          The ID of the snapshot7 O* k0 p9 W8 `( h
     * @return String5 u; |9 T* J: @5 V2 B) H
     * @throws RadosException  s  }( v% T8 O/ z3 G% }  j# o0 u
     */
8 U$ y% |: r. ~/ z' j" t    public String snapGetName(final long id) throws RadosException {/ r8 E( F4 m4 g6 N
        final byte[] buf = new byte[512];$ n# O, E1 \$ V6 ^/ O  D
        handleReturnCode(new Callable<Integer>() {1 c; h" S) a2 y
            @Override
' G0 N' N! Z  Y) H0 ?, w- o            public Integer call() throws Exception {( x" h. h- H! F/ a8 U1 t8 I) W
                return rados.rados_ioctx_snap_get_name(getPointer(), id, buf, buf.length);% T7 g: E6 w0 P0 ~9 {. m
            }
8 ^4 O6 O! Y( j2 c        }, "Failed to lookup the name of snapshot %s", id);
" a/ ^' x6 O& s8 @8 Q' H        return new String(buf).trim();0 w! k% p' m# x
    }
4 }0 f/ T4 g1 R* p, r" P; J+ B; {/ e" s" Q
    /**4 d; J! T2 e: X! r9 t5 V
     * Get the timestamp of a snapshot: S6 A% d/ ?; i- S
     *
( B' k+ B" }$ t, U- Z2 K/ G     * @param id' b& h# m3 T+ L( E5 k
     *         The ID of the snapshot2 A8 y3 N0 }. }: ], _
     * @return long* p) Y  P3 M( P/ O
     * @throws RadosException
" K3 L3 p8 I3 l: _: O0 P) f. d     */
7 r9 y$ W! q: B, B! H( A& F# {2 E7 Z    public long snapGetStamp(final long id) throws RadosException {- {6 ^: h. i6 u/ \% a& C
        final LongByReference time = new LongByReference();
# N* N6 |/ ]( B* t5 s2 O2 A        handleReturnCode(new Callable<Integer>() {+ ^$ o2 d$ j4 Q
            @Override
2 m1 P0 e9 Y, }0 q            public Integer call() throws Exception {
+ k1 A( O8 o/ m# H( L- M! Y3 V                return rados.rados_ioctx_snap_get_stamp(getPointer(), id, time);
  C3 f1 C# _: o) Y9 F            }
4 c6 l: t1 U3 ~% \4 x( W        }, "Failed to retrieve the timestamp of snapshot %s", id);
% k/ @, A3 D  I- t0 q, i        return time.getValue();
6 O; E& ~" A" V/ Z    }7 |* D/ ?4 A. s5 E) c0 l  _( `

4 l, q3 |5 {/ I0 m+ t    /**
5 U8 P) M& c  s) {. \( S     * List all snapshots
+ \$ n! Q- {9 T$ j) a  e3 Q     *
2 {2 o2 J1 D4 J" f4 q6 ^0 n9 l     * @return Long[]4 ~% h( N: E8 ?# N8 `/ I
     * @throws RadosException
7 R6 V9 g3 j* F+ f% n1 |     */3 E0 ?/ H  ^& v, i: V- h
    public Long[] snapList() throws RadosException {3 ]3 _0 t- Z4 U. f
        final byte[] buf = new byte[512];5 ^) A, u# _' }7 j$ E4 I- a) L0 X

  \0 g4 a/ ?$ `- }        final Integer result = handleReturnCode(new Callable<Integer>() {" C1 ]3 u. C$ C$ r( w4 d
            @Override7 m+ `2 {& Z' J! F9 {+ N: o
            public Integer call() throws Exception {
& g# x- X# H, Y# J                return rados.rados_ioctx_snap_list(getPointer(), buf, buf.length);, d  e2 H3 t1 `% G) S# S" j( [
            }
4 w7 Y, ^6 E! d6 c) C        }, "Failed to list all snapshots");5 v) H7 z# Z. w% ?
# @6 H2 O* ^  s2 E4 o
        Long[] snaps = new Long[result];3 [% b. G" R2 L( c# G5 A
        for (int i = 0; i < result; i++) {
( ?, o7 ]1 R: ^7 D            snaps = (long) buf;* |) l1 _5 `* H- _/ z
        }
1 O4 J1 u8 Y: @1 w6 a5 ~3 I        return snaps;- C# Z, [3 _" E5 g2 i4 p" q# N/ V
    }* u6 n  m) M5 p( l6 K( ~) c

% x* S' u: d' p# @! ?    public ReadOp readOpCreate() {9 I1 M7 q  |+ |$ W; X# y, y9 x
        return new ReadOp(getPointer(), rados.rados_create_read_op());9 ?' M  z1 h- C8 {1 V4 W! a7 @9 Y
    }
* b) n/ U7 R, k7 t  \) P6 j" w. }1 j# m& w1 ?8 Q: |
    /**
: t* {( [+ E! ]     * Instead of releasing the read operation directly, better use ReadOp.close2 i  _$ x& e+ V  a- J
     */
& J6 n! V* t  X' |! a4 V7 r* N    @Deprecated
1 }2 D8 P. [& F$ X    public void readOpRelease(ReadOp read_op) {/ S9 j5 @, m! s- R$ t& R8 @" G% m
        rados.rados_release_read_op(read_op.getPointer());1 y. x" E1 f2 ^( T
    }" v0 v% g) l5 t$ ~

' z/ c" k+ {3 G" @6 k; C/ A+ |. L. t8 I9 U& ~# V; W
    /**
& P% \0 v  P* s! E3 U& x9 @" {     * Get the value of an extended attribute on an object.  j6 O3 P* g6 f& E1 b  Z( ?- Q
     *
, P* |! x, O/ n  b* N     * @param oid% p$ i9 c7 S/ j1 u3 _
     *          The name of the object
( E& U- A6 B% L2 c     * @param xattrName
2 c' B$ d! v2 i     *          The name of the extended attribute
6 h  p5 m  y& q7 v, k     * @return# _9 d! e7 U: k0 L/ g+ Q/ m
     *      The value of the extended attribute
% u6 r( q( U5 N     * @throws RadosException
) F. ~8 v3 v) G$ C     *      on failure -- common error codes:' s8 \# I. w7 F: V  Z$ `
     *      -34 (ERANGE)  : value exceeds buffer; |% Y9 R; S$ t) \# b* l
     *      -61 (ENODATA) : no such attribute
3 u; ~+ j# a4 p7 Y  \     */' E' F* X: E: h" h* K+ C& \, l# i
    public String getExtendedAttribute(final String oid, final String xattrName) throws RadosException {0 N" ?) Q' z5 @; v- Q/ T9 ?
        final byte[] buf = new byte[EXT_ATTR_MAX_LEN];* R( P0 W0 Q, Q5 c( S
        handleReturnCode(new Callable<Integer>() {
3 {' y. f0 f/ J            @Override" N) Z0 D4 S0 E! Q0 z
            public Integer call() throws Exception {
# ?; B. [! q' R; l1 L8 L6 x                return rados.rados_getxattr(getPointer(), oid, xattrName, buf, buf.length);
7 \+ g/ k. J% X1 |9 t            }
% I) A- Z  R# b9 W/ k; e        }, "Failed to get extended attribute %s on %s", xattrName, oid);8 u3 \8 \0 W7 ~' g
        // else...
0 ^% g: F& e* P5 o! G" V# }        return  Native.toString(buf);
- @7 m  q- [2 l/ k" m0 R! {. r    }
% f* [8 [; Y1 t9 ]7 F0 w1 y
1 a! z9 R1 x5 [0 u+ O    /**4 @, j* ^: e8 L, A
     * Set an extended attribute on an object.
! k% |; [  Y% i) }# z) Z# a     *& o) o5 R+ r0 b/ L- G
     * @param oid) V+ P1 U- B1 ~* l0 c6 p
     *          The name of the object
2 R2 f0 x% {- H: d1 U     * @param xattrName
" Z. z! w3 }: t" L( g( n' h; {6 ~     *          The name of the extended attribute
  U* d3 F. H) i0 d6 _     * @param val
# S1 G1 G) U# E; S, S+ R# `0 ?* n     *      The value of the extended attribute
8 \  O# P- ]/ c5 I  n; E" E/ }$ m     * @throws IllegalArgumentException
' o+ \: G3 L- B9 Z' v( e     *      attribute value is too long# B; s2 X: J7 U6 ]% y6 F0 ]
     * @throws RadosException
" R8 l# m* {4 W4 N2 |     *      on failure
' d" x' y2 D8 }     */$ @" {6 X- K  ]+ Q/ ~' V/ T3 n, }
    public void setExtendedAttribute(final String oid, final String xattrName, String val) throws IllegalArgumentException, RadosException {! _: z" w6 F6 y
        final byte[] buf = Native.toByteArray(val);
0 I- V6 U7 r8 k- K7 F  N# L        if (buf.length > EXT_ATTR_MAX_LEN) {
- N& x" h& }) P            throw new IllegalArgumentException( "Length of attribute value must not exceed " + EXT_ATTR_MAX_LEN);
6 s2 E1 G/ u3 }: h; A. |& @        }% D% V$ k" f/ l1 _0 M4 w% r
        // else...
6 z; ~% O5 o% l( d' Y4 i$ _7 ?        handleReturnCode(new Callable<Integer>() {0 E( a9 x. K5 i" W( k. u
            @Override
3 V" L3 b$ v3 t9 ^: r5 n/ x& L            public Integer call() throws Exception {, k' w8 W: \6 J9 S- }" J. x4 [
                return rados.rados_setxattr(getPointer(), oid, xattrName, buf, buf.length);! J. X- r  E- w3 s* D% \" l
            }: {0 m9 D0 U; A% O
        }, "Failed to set extended attribute %s on %s", xattrName, oid);
" h5 m' M: _- {* K/ Y% E  O    }
% \0 y4 {' s; [+ W' ~8 ?' k+ ]0 z( v3 g0 G' l
    /**
& ~+ \# k4 H, c) {( j$ }; F     * Delete an extended attribute from an object.
  F2 k$ f% c7 v5 t0 N- S     *: X' l/ P7 m. J* L1 i
     * @param oid8 j( i3 I3 U! A8 n9 D- ?4 k8 @
     *          The name of the object
6 v# B% c. [# L     * @param xattrName
4 r% }7 d. q, S6 u     *          The name of the extended attribute
0 I9 F2 Q3 M) R3 k+ h( v' ^6 S- C     * @throws RadosException9 P3 C$ }- C, e/ J8 S2 ?- h
     *      on failure2 {7 u  R5 A% O2 J
     */. d. a# g, R; B; k, `! ]8 c, L
    public void removeExtendedAttribute(final String oid, final String xattrName) throws RadosException {+ m. J; l+ X6 \3 E2 M( ]
        handleReturnCode(new Callable<Integer>() {
& H$ s* U  }) L6 p- k4 d- K            @Override
$ u# k! A0 q6 h- @: x4 @0 Q) C            public Integer call() throws Exception {
+ i4 l8 D' t" P" M- [                return rados.rados_rmxattr(getPointer(), oid, xattrName);
) \6 i4 i9 h# a- ~: E  \' e            }
1 d8 O& @) j, |  X3 N( V        }, "Failed to remove extended attribute %s from %s", xattrName, oid);
0 u  [. Q! N% o4 \! l+ s8 p   }
7 G! w9 a# ?! K% d" N3 Z' _4 ]. P
+ o$ B. v) a5 C* o' Q   /**
# F) |  H* M7 [- a     * Get all extended attributes on an object.
( A8 Z1 G; z7 s8 _6 L3 r     */ g6 {# V7 b/ z
     * @param oid
+ c5 w; \! W8 C7 c     *          The name of the object2 L; g* M) g* p5 r  `, L
     * @return, D! v; d! j& E. b
     *      The map of the extended attributes; U# z- a: z5 h7 D# ^
     * @throws RadosException
3 T+ k) F9 ~& J9 `     *      on failure; ?8 H& _2 v) Q7 O- r; [. D+ [
     */" s* U$ I' v. Z/ V9 p, D$ p
    public Map<String, String> getExtendedAttributes(final String oid) throws RadosException {$ b3 ~' Y: l5 ~$ ^, ]9 y: P
        Map<String, String> attr_map = new HashMap<>();' @' ^: K! D! V3 t
        final Pointer iterator = new Memory(Pointer.SIZE);+ d! D- _( Y/ E& L, E! Q& |
        final PointerByReference attr_name = new PointerByReference();
7 F& N- {( M4 S3 \9 T/ J! p        final PointerByReference attr_value = new PointerByReference();
. \5 S( b' X, F# e# h' K( |. W        final IntByReference attr_value_len = new IntByReference();# C' q$ W! F2 g
/ u. s( d9 X9 b* h* G+ }/ C
        handleReturnCode(new Callable<Integer>() {
( Y0 T* j) {& U            @Override
- S; X2 L) ]; N4 p& [0 r; Y            public Integer call() throws Exception {
8 `/ S6 o" |; C2 Y                return rados.rados_getxattrs(getPointer(), oid, iterator);  ]% e% ~" K  M; h3 y
            }
6 |! X* y) K( n        }, "Failed starting to list all extended attributes");
- P) J$ s  D6 \" a1 M+ @- D7 \
# _9 ?# n5 k* d8 q" w3 i" o        while (rados.rados_getxattrs_next(iterator.getPointer(0), attr_name, attr_value, attr_value_len) == 0( m/ e" O8 ]7 J9 K" L
                && attr_value_len.getValue() > 0) {1 G) W- \/ N9 T' T5 G; R; R0 B& w/ c
            int length = attr_value_len.getValue();
* n( x  B+ Y9 V$ P3 d            String name = (attr_name.getValue() == null ? null : new String(attr_name.getValue().getString(0)));
+ `" R6 E# w' A* w5 ]% l" e) n            String value = (attr_value.getValue() == null ? null : new String(attr_value.getValue().getString(0)));* |/ S. x9 A, m+ s; e
            if (length > 0 && name != null && value != null) {4 m( A  t3 I: N. K9 A% G: ?
                attr_map.put(name, value);
2 m& L6 W7 F- Q, q. Y4 Z: B, k            }
$ W0 u( \9 I! N2 ~: Q/ w+ b        }
6 s. Q! p) ?$ F3 x2 z1 Y! I8 ]# q- k3 e5 V9 N
        rados.rados_getxattrs_end(iterator.getPointer(0));# x  P) \" Y1 c& b3 K5 k

/ M7 Z7 N. q5 S5 G5 r$ ^        return attr_map;
. u. j1 ~% \, c3 ^    }
9 D; l, L$ W0 }1 @4 `- f  B7 w5 A4 f% `, t) P3 l; i0 S( R4 z/ e
    @Override
% M7 Y4 s# g, y% H. G: J% y; N7 D; O- ~    public void close() throws IOException {/ Q# _+ [- B4 g3 N! z
        rados.rados_ioctx_destroy(getPointer());; Y3 f( t6 K1 M$ v2 a/ P* G
    }
# o+ b6 v6 i: [  s! N}
; h+ k$ B: x# A" H' x' I( v) v" _* c# Z! E# Q1 ^$ J4 N% w0 p' ~7 C

7 e$ `" n+ V8 X- h2 [* ~2 F7 b至此,大家应该对Java访问Ceph有了彻底的认识了' k+ F# e' ?5 L. y( T/ u# I
( X! H% m4 }, _

# {+ B1 X6 H4 ]5 n) {/ o
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-11 22:57 , Processed in 0.036431 second(s), 24 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表