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

Java访问Ceph数据

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2023-2-21 15:00:18 | 显示全部楼层 |阅读模式
1. 部署LIBRADOS环境# d0 }7 O& E3 z- b  h4 d
客户端应用程序需要librados才能连接到Ceph存储集群。1 S) I" {7 ]! ~. b) U8 f  v9 E
+ A$ t5 ~- J' g8 P) U! D6 j! K
1.1 安装jna.jar
& I3 x* H* n0 U  B4 i" g) gDebian/Ubuntu环境下执行以下命令' {7 }/ p* C2 x4 `6 I' g0 x, s

- o) n$ J, P  a$ q- Q. l: Psudo apt-get install libjna-java& M0 x: j, d1 c2 q7 l" q# ~  O

$ a% J& n, I% m
+ c. E% ?" Z! N$ lCentOS/RHEL环境下执行以下命令& g8 p% k% h; a( p9 b! v: O: G

+ D6 @7 @: r( i- o" ]sudo yum install jna
- s& _' }- ~. m; v: g
) l  K0 C' L- w& S6 y5 FJAR文件位于/usr/share/java.9 b7 O: `) g3 j3 V

0 u9 X2 L5 ^3 m: x# A' c% p1.2 克隆rados-java代码库
/ b) T. e2 T3 Wgit clone --recursive https://github.com/ceph/rados-java.git$ @6 I+ J% L3 S$ ]
. x8 }9 ~, f' `  ^; I( |7 _
1.3 编译rados-java代码:' b3 O0 M7 Z# a# ~
cd rados-java
9 d4 S) W3 z  G( \0 {ant
& D! ^" n& b+ _2 e0 i
9 {" g/ J9 ]5 W1 c. R: C1 O( o0 B9 B9 J* t, I4 f
JAR文件位于rados-java/target目录下* M$ w7 d- S( }

; ?* w1 @& z% f) E# u3 f1.4 关联路径
" w' N2 _! [6 L1 o8 X复制该JAR文件到公共目录 (例如 /usr/share/java) ,并且确认该文件和JNA JAR在你的JVM’s classpath目录中. 举个例子,你可以按照以下的方法来关联路径:) Y- J( K7 h* g5 ^7 H  p
' f6 A' O+ |9 }3 o. S
sudo cp target/rados-0.1.3.jar /usr/share/java/rados-0.1.3.jar
1 Q2 g3 ~- z6 E- Fsudo ln -s /usr/share/java/jna-3.2.7.jar /usr/lib/jvm/default-java/jre/lib/ext/jna-3.2.7.jar
7 L& g3 {( a& f, H$ Y0 {% t8 hsudo ln -s /usr/share/java/rados-0.1.3.jar  /usr/lib/jvm/default-java/jre/lib/ext/rados-0.1.3.jar* e, `3 g  N# V2 }- w. N
+ Z7 ^# |/ V/ T/ d* i& \

: d* d. o4 B! t5 P6 Y编译文档可执行以下的命令:+ q+ L3 c" B* X

/ j, ~' O$ S; Jant docs
! N, a, R0 p! _/ C; b8 D4 l2 U, q  V# {
2. 配置群集句柄7 u8 i& ^3 ~7 @0 q5 \
一个Ceph的客户端通过librados,直接与交互的OSD来存储和检索数据。要与OSD交互,客户端应用程序必须调用 librados 并连接到Ceph Monitor。连接后,librados从Ceph Monitor中检索 Cluster Map。当客户端应用程序想要读取或写入数据时,它会创建I/O上下文并绑定到池。该池具有关联的规则集,该规则集定义了如何将数据放入存储群集中。通过I/O上下文,客户端向librados提供对象名称,它获取对象名称和集群映射(即集群的拓扑)并计算用于定位数据的放置组和OSD。然后客户端应用程序可以读取或写入数据。客户端应用程序无需直接了解群集的拓扑。
& S$ n  A! [" ^" L' T" `' M( }+ q! V9 {7 `2 s% K
Ceph存储集群句柄封装了客户端配置,包括:! c3 N1 }' p/ @3 n% X
& B; Q( e& g) O2 a- y- ^1 x. U: ~( ^: k
使用用户ID的rados_create() 或使用用户名称的rados_create2() (推荐使用此方法).
( L) o7 c- o. ]cephx认证密钥0 |9 ~1 b5 U: Q3 v" x
监视器ID和IP地址
* F1 n6 s9 A' Z4 q# b- k记录级别- |/ M% _5 \$ C6 e" \
调试级别) z$ J4 ]# ~( X  @
因此,从您的应用程序使用群集的第一步是:1)创建应用程序将用于连接到存储群集的群集句柄,然后2)使用该句柄进行连接。要连接到群集,应用程序必须提供监视器地址,用户名和身份验证密钥(默认情况下启用cephx)。( r+ d, n  k, C( b2 i: d! w

7 W# @" i- V2 j6 z" k) g, O( A注意 与不同的Ceph存储集群 - 或与不同用户的同一集群 - 交互需要不同的集群句柄。
( a; b; y3 C8 V9 H
& g# @  Y) u, ^# W) G( D: gRADOS提供了多种设置所需值的方法。对于监视器和加密密钥设置,一种处理它们的简单方法是确保您的Ceph配置文件包含密钥环文件的密钥环路径和至少一个监视器地址(例如,mon 主机)。例如:/ r0 N3 S1 W8 {

% [/ @4 e& @* t# O+ P/ `[global]
3 a: r+ a5 ~8 I  t5 d4 w0 W: mmon host = 192.168.11.1 : S% v5 C$ i  I( J% @7 J8 L# ]; ^* y/ G
keyring = /etc/ceph/ceph.client.admin.keyring
; ]; {" C* g% o1 T( z+ P: N+ s% X5 g) Y" f, t" y
# O8 A* B( A8 O4 y
创建句柄后,可以读取Ceph配置文件以配置句柄。还可以将参数传递给您的应用程序,并使用函数解析它们以解析命令行参数(例如,rados_conf_parse_argv()),或解析Ceph环境变量(例如,rados_conf_parse_env())。某些包装器无法实现便捷方法,因此需要实现这些功能。下图提供了初始连接的高级流程。( R# @* O# s1 Z' \& t4 R3 J
. f" E# D$ R- T$ f
连接后,应用程序可以仅使用群集句柄调用影响整个群集的功能。例如,一旦有了集群句柄,您就可以:; J: K/ A: ~' q+ h

9 X( h9 g" W+ [获取群集统计信息/ r! J3 O( Y) C" x7 {
使用池操作(存在,创建,列表,删除)
1 _; R2 \3 v# B$ t获取并设置配置% V  u/ s. z( p. B  V4 n
Ceph的一个强大功能是能够绑定到不同的池。每个池可能具有不同数量的放置组,对象副本和复制策略。例如,可以将池设置为“热”池,其将SSD用于常用对象或使用擦除编码的“冷”池。% j) t* o% s$ s
Java要求你指定用户ID(admin)或用户名(client.admin),并使用默认的ceph cluster name。Java绑定将基于C ++的错误转换为异常。& [% B5 \& @. T+ D7 X
; l$ O  L& R! x) P
import com.ceph.rados.Rados;
/ L0 X9 w! b! V: j  `& Aimport com.ceph.rados.RadosException;- [  I" c: O1 c

/ U. v' J5 b, B: r, \' uimport java.io.File;* e* P# l# ]1 a7 Z  Q
/ X) ^, J- b" X. I) u9 u
public class CephClient {# h6 q$ [0 u. |( g5 _
        public static void main (String args[]){2 a5 O/ }3 @1 R# U6 D" f  g! z
' t  F  ~/ ~. N5 }6 ~9 U% B+ w
                try {
/ x) ?9 A, K7 e* M# D: @9 e" Y6 n                        Rados cluster = new Rados("admin");; G' }! y2 @' m" ]
                        System.out.println("Created cluster handle.");( G4 x6 W3 ^0 t+ u  O) t

7 A$ `/ O$ ^$ k" s# O                        File f = new File("/etc/ceph/ceph.conf");7 o/ f& B  {: _; T+ h" t7 v
                        cluster.confReadFile(f);2 o+ ^$ U- z% m: J8 h8 V
                        System.out.println("Read the configuration file.");) J# ~: w+ L! y8 t
6 h" i! o8 w4 J; d) ]4 z+ J
                        cluster.connect();. |- j0 ?+ ?5 i/ i
                        System.out.println("Connected to the cluster.");: j% U, v+ B( e' R3 [* R' G6 S
4 D1 C1 f4 G6 f) d9 d' n
                } catch (RadosException e) {
! B: {: _: S- b3 _: _3 H                        System.out.println(e.getMessage() + ": " + e.getReturnValue());4 w# |6 s0 j/ a8 ]+ l3 m
                }
& @# i$ i# B& c( ~        }6 U9 B7 X8 |$ X/ ~8 L' v- j
}
  q$ g- N* x3 y8 U" T
% \/ W1 l2 h1 |- {8 F8 `# t, i7 A' b  V/ r
编译源代码; 然后,运行。如果你已经把连接Ceph的JAR文件复制到/usr/share/java并软连接到扩展路径, 就无需设置classpath. 如下运行:
0 b2 S8 \, ?1 y& R3 J+ s3 q3 |. p# f
javac CephClient.java
$ W$ B: a' M! i5 \7 y/ U$ ujava CephClient" d# P; |5 F4 B6 T6 Z5 C0 B$ T/ |
" ~" ^4 g, g( w9 t+ L  ]: H
3 }/ d: N) f$ {4 b" ]4 X8 S" i' c
3. 创建I/O上下文5 L; d4 e, y1 x; F4 X' a7 X) U
一旦应用程序具有集群句柄和与Ceph存储集群的连接,就可以创建I/O上下文并开始读取和写入数据。I/O上下文将连接绑定到特定池。用户必须具有适当的 CAPS权限才能访问指定的池。例如,具有读访问权但不具有写访问权的用户将只能读取数据。I/O上下文功能包括:
9 \8 a6 L6 i7 o' l) m3 }
" T5 u* A7 T5 [- U写/读数据和扩展属性
! k8 N! Q% M, f+ Q列出并迭代对象和扩展属性
' n2 ]/ X! P' q  m3 U; B" M0 h( k快照池,列表快照等
$ k9 a) y5 i1 C% G& q+ uRADOS使应用程序可以同步和异步交互。一旦应用程序具有I/O上下文,读/写操作只需要知道object / xattr名称。封装在librados中的CRUSH算法使用群集映射来识别适当的OSD。OSD守护程序处理复制,如Smart Daemons启用超大规模中所述。所述librados库也映射对象来展示位置组,如在 计算PG的ID。
; J) Q! h2 P6 C& m2 V' _$ s8 w/ }* R  ^. o- Z9 R. G) Q/ ~) O; w
以下示例使用默认数据池。但是,也可以使用API​​列出池,确保它们存在,或者创建和删除池。对于写操作,这些示例说明了如何使用同步模式。对于读取操作,这些示例说明了如何使用异步模式。
) s& K% n# N' v3 e# S8 j8 H2 ^% G3 f9 h1 j& e8 |/ B, M
注意 使用此API删除池时请小心。如果删除池,池中的池和所有数据将丢失。2 c/ }! S  S) R& P9 m4 M
1
3 O  {" k% W; w3.1 写入数据代码  F, \) ^2 ~6 k+ ?- Z6 @
import com.ceph.rados.Rados;0 C; N% F$ C! z+ J2 k
import com.ceph.rados.RadosException;4 L' `( t, ~; t% P9 _' u- r: u

  n  @* h& I1 A6 iimport java.io.File;
1 u' z; k  s* X; J3 H8 Limport com.ceph.rados.IoCTX;
) J) Y% ~7 Z, L1 o
& W, l6 f9 S) f+ x2 [2 Wpublic class CephClient {
. u6 O9 }6 U* L* r, L        public static void main (String args[]){6 m7 i- u$ i' M7 c+ C7 {/ f
$ w. ]; q. h; x" w2 s1 O7 B6 `3 U7 @
                try {5 s( E1 s8 O$ t
                        Rados cluster = new Rados("admin");0 p3 K4 t0 ]2 O$ D8 D
                        System.out.println("Created cluster handle.");* m% f; {, i# ?% x' G$ y
                                                //利用配置文件连接ceph( I4 K1 l8 [% ]8 m% Q& t  E
                        File f = new File("/etc/ceph/ceph.conf");0 k7 w9 P* X9 W8 O* K4 V
                        cluster.confReadFile(f);. l6 K6 ?2 l. m' A& I  u
                        System.out.println("Read the configuration file.");( N7 D3 y2 d( B: \5 ~2 \" V* Z

  R; }  K9 Z. Z. f/ w6 G                        cluster.connect();% i$ C% @/ V1 u6 U' x
                        System.out.println("Connected to the cluster.");/ a1 J0 x* s6 C4 D3 {

: I, A) r! t! j& ~& K+ F4 ]& g& _! v                        IoCTX io = cluster.ioCtxCreate("data");( U4 e9 e" B) i% \! }& o
& j; l* g: A5 u" }  G6 K
                        String oidone = "hw";
! I: O' X7 M7 A# u  r- S& u                        String contentone = "Hello World!";$ h* ~8 R6 ~% O& y0 j4 A  |% R
                        io.write(oidone, contentone);
; [3 |4 Y; f+ l. ?6 U: Y8 c9 `$ ]( o* H) V* p4 k' `! B  l! C8 ]0 {
                        String oidtwo = "bm";
& j1 i( N4 J5 C$ D; l# V                        String contenttwo = "Bonjour tout le monde!";& S& O, ?. \; ~1 {* ]) [$ @
                        io.write(oidtwo, contenttwo);+ m1 _  z9 m7 X% a9 ~
7 O# h1 G& U* f" M& n% b
                        String[] objects = io.listObjects();2 t2 z# U/ ]8 R4 `
                        for (String object: objects)
$ G7 N1 U. I0 C- {                                System.out.println(object);. M5 H0 v3 z$ C1 S3 Q4 C

7 b8 T' G! }* P8 `. b                        io.remove(oidone);( s7 |* W6 m" b; z* |8 C
                        io.remove(oidtwo);
1 G% M9 E, d4 a0 E7 H7 I% b8 q0 G7 H6 O+ D
                        cluster.ioCtxDestroy(io);, U# a  y$ ^$ W+ L

! W( s- ^: D4 f                } catch (RadosException e) {1 u  b$ Y0 E9 |: W& v, i
                        System.out.println(e.getMessage() + ": " + e.getReturnValue());! Z7 \. B8 V3 T) p
                }
8 ]5 `' J2 ~$ h        }* @" ^2 ]# c* Z
}# [" t0 a$ _( ]7 y
* O: s$ q8 |2 ^0 E( ?$ V' i
; |% F/ _0 m5 L% k4 E5 i# |
3.2 一些基本操作2 ~! r9 \6 p: `, P  x- k
package com.ceph.rbd;+ \6 N9 _. K0 c# v
& G" d8 N5 i# b: Z8 D2 Y: O
import java.io.File;! U- Z$ A4 _7 q3 p1 L5 P
import java.util.Arrays;
+ m% A% I+ w. r9 Z6 Y4 s, V' J) rimport java.util.List;
6 a) W# c0 V$ N' Z( Y6 X- u% ~  F. A) J+ q
import com.ceph.rados.IoCTX;
- d5 A- ?% R& m& l$ Nimport com.ceph.rados.Rados;6 m. Z3 @/ }& M. |% t
import com.ceph.rados.exceptions.RadosException;
9 ?/ d& O" O$ Eimport com.ceph.rbd.jna.RbdImageInfo;
3 ^: E  v( z5 ]9 ^9 f) C1 Pimport com.ceph.rbd.jna.RbdSnapInfo;6 o) w8 q, B6 b$ u' ~

6 O8 Y& Q3 T4 Rpublic class RbdDao {& q5 P3 J$ e1 Z( I" ^4 K1 S* a4 w
" S0 \* s6 V; f% K6 K0 Y0 f, t
    private static Rados rados;0 g, I7 |( c2 l* M' x. g0 \
    private static IoCTX ioctx;
, V0 d( G  u$ d6 E0 n    private static Rbd rbd;4 u7 q* _9 a4 r! G4 r" v0 T7 r
     /**
- W" i5 ]5 h8 u8 \# E8 F' D, k      * 连接上ceph环境
; q8 Q# C9 U1 o. M      *// F# S5 ^2 x. P9 r# }3 k/ U' l
     public static void connectCeph(){" _/ ~* h: x4 f& p# p5 U" @6 c
           try {" S0 ]$ i9 `. S- @1 ?: H
                           //利用参数连接Ceph
+ e" u6 x/ P. u8 n- v+ G                rados = new Rados("admin");
0 d& _2 a7 }! k1 Z5 p( L                rados.confSet("mon_host", "172.16.60.41");
- w" }( l, ~2 q5 d. K( R                rados.confSet("key", "AQCdP9pYGI4jBBAAc96J8/OconCkVKWPBNU2vg==");
; ~) Z- h' ~( n8 S  Y7 ]                rados.connect();7 p- `" m( E. X# |
                ioctx = rados.ioCtxCreate("rbd");
# |% m- g7 r" r: ?; r  Y& ]! ~                rbd = new Rbd(ioctx);
* l- e8 r' b- D/ B5 b# J                System.out.println("successs connetc");& M2 n! L* v( \5 C( z, K' X
          } catch (Exception e) {& k0 B! u1 @' w, c! s
              e.printStackTrace();# D; }4 ^3 O9 @- r
            // TODO: handle exception
- a8 T; S" ^, E8 q# m& ]9 O# m+ H         }3 x& p/ v+ M! X% r5 M6 T5 {
     }
8 s7 a2 G' M5 F! a$ x2 s2 x0 M* Z( k. a
     /**7 ]5 y( H& n- u" P/ |/ U7 Z
      * 返回所有的image,并展示其详细信息. |$ J3 E* Z- d4 J% `0 d  P/ @$ I4 Y
      * @return' [- J1 Q/ B: o) i3 C; X6 f* @
      */
1 {' I( y4 S3 i: V. a5 p     public static List<String> imageList(){
+ @1 R2 ]2 l- b' H( c          List<String> imageList=null;
8 ]4 e& d+ x% F+ q9 o2 u          try {
  {3 V' m7 a% z# C0 y; ]  b            imageList = Arrays.asList(rbd.list());
! q/ _5 ^/ {7 {0 G; N$ v& k! A            for(String s:imageList){
" ^$ Q2 ], v5 J' Y                showDetailOfImage(s);
# H9 {% H9 q  W# B            }) K0 c; k, d! Z; T& L  |5 \$ G$ p
        } catch (RbdException e) {# c8 J1 S8 i9 z: F. k, L
            // TODO Auto-generated catch block% h4 T% j. G- C& x, t+ R# ^
            e.printStackTrace();# z; O+ C) S0 t3 Z' U& m
        }
+ E( ~2 U- b+ g! r7 \- b( z- Q          return imageList;: G3 B. S1 U" v  v# h' K
     }- C$ L/ D0 D0 |/ O

: F$ u3 S" H% Y, h     /**5 I0 D# T0 y" W( x. r
      * 显示image的详细信息
  a* v" x9 J+ n) o) ^9 k      * @param imageName
) I! ~: Z% v3 ]  V5 h0 Y      */; S5 n9 k7 [0 W) r1 X4 G0 C
     public static void showDetailOfImage(String imageName){
9 M$ A. H* d9 u+ t/ l& Q& b         RbdImage image;
* L# ?9 N' {+ G        try {" i2 T: Y5 @9 y
              image = rbd.open(imageName);
* x! T8 N4 e  ?$ x              RbdImageInfo info = image.stat();
  J5 z- q6 i5 t+ Y7 I$ q3 ?              System.out.println("=================================================================");0 G0 g; I3 P: j
              System.out.println("imageName:    "+imageName);
4 H' m( R9 k+ m8 t: e& _8 A              System.out.println("imageSize:    "+info.size);# Z: w" m1 q& r# c" V
              System.out.println("order:   "+info.order);! Y9 f4 Q5 d* S
              rbd.close(image);
  r" U" d4 x% [4 l, Y7 t' ~        } catch (RbdException e) {; w; M" s( `1 Y8 x/ G" c
            // TODO Auto-generated catch block7 {. ^( G9 D. U( Y5 C3 P% m1 h* u
            e.printStackTrace();
; C- {8 a& H( I. X8 b        }, r  y& k& x5 \: s- \( Y

) r& K! g) v3 i4 o     }& g& \1 o3 E+ a7 C
' X! }, L/ X* v0 F, l6 Y
     /**
" X: ]: w! d6 z6 X9 G      * 以格式1创建image9 ]1 P6 Y) u3 J+ \. D) I0 i6 q( L4 X
      * @param imageName 名称; ~; h, Q$ c0 _
      * @param imageSize 大小' l& l; {/ }& ^) k9 S$ P# U) j
      */
4 o8 _; G" ^) ?     public static void createRbd_format1(String imageName, long imageSize){
; }, v+ @& d2 l            try {) y& e9 Q  m1 Y- J  J; E
                rbd.create(imageName, imageSize);
% G9 D1 E$ Z4 G7 u0 C" E- J                RbdImage image = rbd.open(imageName);
9 ~. U) h* }5 K8 N6 p9 I3 t                boolean oldFormat = image.isOldFormat();
8 b" _& J  B, T  L" W                System.out.println("imageFormat:==========================="+oldFormat);% D: F" c3 Z9 W5 c8 d6 y

# S3 `2 q6 ^4 K% ^2 w% ]                rbd.close(image);0 f' b! d2 C% a
            } catch (RbdException e) {, _6 _4 J* Y1 b$ _1 ~0 _4 o
                System.out.println(e.getMessage() + ": " + e.getReturnValue());
' R1 P1 e* s. K# U" V            }9 ?2 o* U% e& D8 w0 _
     }
2 J( t% d/ [8 p- ?; o; V, F/ T  N7 C$ L5 ]
     /**/ z  i; {- z) Y
      * 以格式2创建image,ceph 仅支持克隆 format 2 映像(即用 rbd create –format 2 创建的),而且内核 rbd 模块还不支持。
5 o- f; s9 y3 I' s2 K2 \% }+ ^8 X  所以现在你 只能用 QEMU/KVM 或 librbd直接访问克隆品; f  p+ R1 r% n7 k4 q
      * @param imageName 名称
" w  l, T' N; T- Z' k9 U" L2 {      * @param imageSize 大小- @% U/ [, t1 a( @5 m/ q
      */
  s* C% r2 m7 a- Z8 y     public static void createRbd_format2(String imageName, long imageSize){
6 ?+ G  r9 ^8 J+ f0 Q& W            try {* K' X* n* {, t! v/ O0 \
                int features = (1<<0);( [, s2 d8 D, n' |/ r0 p+ Q9 `3 x
                System.out.println("features=============="+features);1 T; v+ a4 s( `8 l+ w% j% h
                rbd.create(imageName, imageSize,features, 0);
$ J5 E9 n+ l" v# ~8 K' C                RbdImage image = rbd.open(imageName);' t6 o$ O7 d1 m, N; ^" h, P
                boolean oldFormat = image.isOldFormat();* P- N& G& T0 v) I
                System.out.println("imageFormat:==========================="+oldFormat);               ; k+ @: ~; ~4 e0 i; Q' l
                rbd.close(image);
# z. |& ~/ I% J: Q- K# [                image.flatten();# Z8 Q+ n0 H, z
            } catch (RbdException e) {
) `% a; `( P) d8 ~9 Y- o                System.out.println(e.getMessage() + ": " + e.getReturnValue());6 R) O1 G" y: l6 Y" E) g# @
            }
' ^! U# a1 J5 y5 Z" |/ \     }
" K; K8 U7 R/ S3 ~
' Q" [( k. Z# M% c/ C/ R& I     /**
! o( u& f; E5 K: K6 F$ i      * 方法创建一个image并对重设置大小为初始化大小的2倍
/ V  |% z! c  H2 d2 Y; X! u* c7 W# v3 a      * @param imageName) v8 e: Q, G- J4 \4 P: L
      */( u& p3 ]- ?; x
     public static void resizeImage(String imageName){0 o, k# D, r4 P( O8 C5 Y" N
            long initialSize = 10485760;7 w" R9 x& v1 }
            long newSize = initialSize * 2;. }* ~7 ~3 m9 k1 `2 |+ `
            try {/ [! ^7 e6 w( W* ^& [
                int features = (1<<0);
8 o6 ?, V7 E( w$ ?* {. j: t                System.out.println("features=============="+features);
- ~& ^- ^6 p' X% \4 K                rbd.create(imageName, initialSize,features, 0);1 F, d( y3 |& n: `5 f( u
                RbdImage image = rbd.open(imageName);
/ W9 o' K" z* c7 D* g3 J                image.resize(newSize);) v( B. b  X$ T
                rbd.close(image);
2 g/ Z5 |# y7 o3 {- ~5 S5 M3 W% y            } catch (RbdException e) {$ f1 h- q" S; ], e6 U
                System.out.println(e.getMessage() + ": " + e.getReturnValue());; g7 p2 D  j* F% B% `
            }( C! R6 |8 Y% X
     }
2 s3 ^5 _* R0 Q. J$ [# a0 q2 ^% A5 r; w. j0 t, z
     /**
. T- N: G$ j) Q6 o! e3 d, s/ S2 j      * 创建映像的快照
( r0 k$ Y' v( m5 A      * @param imageName 映像名称6 d$ |1 w: e* c& S6 h' u9 y
      * @param snapName 快照名称
+ l  c9 `3 m: J/ V3 n: z: n+ R      */+ D7 P- k2 P1 v3 x1 P
     public static void createSnap(String imageName,String snapName){
1 z6 Q- a3 f/ I! A% r1 A8 U  L         try {7 y0 n- P0 G: D2 o# r% b  R) O
            RbdImage image = rbd.open(imageName);
3 m5 r# |5 h9 K0 b9 a' y            //创建快照( [4 v% I" d; A3 k; w1 {% J! N
            image.snapCreate(snapName);7 L" J8 d9 {# M* d7 n; `3 H4 F$ i
            //保护快照可以防止快照被删除
  z: P) o5 P" y) A  l/ D( f1 D            image.snapProtect(snapName);
& ?, {3 u, e( \& T$ X/ d4 B            //返回一个image的所有快照
1 u+ r% {7 t1 N2 \" I8 E& N            List<RbdSnapInfo> snaps = image.snapList();+ f6 Y5 q( T4 P: z
            for(RbdSnapInfo rbds:snaps){
7 d' l: P7 ~! }8 W. ~# W                System.out.println("快照名称:"+rbds.name);( C' `8 E# M3 L; @+ F  v- O- ?
                System.out.println("快照大小:"+rbds.size);: u) @- `, S8 X5 @5 A, O) h" b
            }! }- ?+ q, Z8 T
        } catch (RbdException e) {
* b. g; S9 ^. K% n5 F& K  d            // TODO Auto-generated catch block
6 }7 ~- Z% f4 N0 k2 D            e.printStackTrace();
; h2 ~; Y7 Q- `        }
7 {+ j0 {" t5 h+ H     }
7 I" B' D7 F$ I9 M. d( Z5 X. l% H' d) x  u
     /**
8 P# G0 {$ }! d6 Z: k      * 通过快照克隆出新的image+ X8 J0 v8 R7 e' m3 `* i& J, c
      * @param parentImageName 快照对应的image名称
+ \1 f. m# \+ g, j  C2 @      * @param snapName 快照的名称/ V" ~& O4 J9 ?# N
      * @param newImageName 生成的新的image的名称3 I; C, U& e0 R! c6 W, R, z( L
      *// O1 o' p* t) J( n6 a3 w
     public static void copySnapToNewImage(String parentImageName,String snapName,String newImageName){3 M: t; L, S- @
         int features = (1<<0);$ F3 K8 p$ l3 B
         try {
0 F. m( R0 k- x            rbd.clone(parentImageName, snapName, ioctx, newImageName, features, 0);
7 g' z! F9 f# Q        } catch (RbdException e) {, R# u) Y% K0 m9 `5 \2 H0 j& h
            // TODO Auto-generated catch block
& u" |& @  r3 T# ?            e.printStackTrace();  S$ _8 s4 Y" ?3 u8 u: R# R# ^
        }
  `" M" M; |& |4 p# t: _' K$ e     }
; v5 t* H# F4 k9 ?3 p
& F* J9 p7 l3 C' U; Y     /**
# s7 n7 a4 _. z0 E8 V7 w0 `      * 删除某个image的名叫 snapName的快照,需要注意的是要删除快照,必须保证快照没有copy的子image,否则会删除失败。3 @1 t; j% B' _- _7 Y  \1 w
      * @param imageName1 U! ^; b# j" D- {' t
      * @param snapName. z/ p; W/ n* s! S
      */* p, X, q+ _3 I+ z& i; I+ i
     public static void deleteSnap(String imageName,String snapName){" _+ m% U) p% D8 X
         try {
. s! I; w# H8 [) N/ h            RbdImage image = rbd.open(imageName);
5 y7 Z: y6 m4 T7 B& D5 x, D9 p            image.snapUnprotect(snapName);9 ~3 P& Q6 E( c
            image.snapRemove(snapName);# ^  j/ z& @4 d/ E- H8 G4 v
        } catch (RbdException e) {
6 I3 l  T$ e7 q; y# h' H3 e  R! \            // TODO Auto-generated catch block; J9 B# K- D, h! u6 U
            e.printStackTrace();
3 ?1 m6 B" X; J+ e9 n; A9 W  ^        }
0 ?/ Z" M: c. j5 A9 w) R     }5 w+ q( P7 {7 o& y
. I! l. d- C/ \9 }8 ?" r- D
     /**
1 \6 k$ P. @/ {4 w      * 删除某一个image; {  P5 U& @. ~& F- G# L
      * @param r
; I  B* C/ n3 k& L0 ]. [      * @param io0 X( f% R8 m. {, e% X! q
      * @param imageName; l0 u- Y5 |1 J  I' F
      * @throws RadosException5 q) k' J) b! I; |* c
      * @throws RbdException
1 D4 {# |7 F, [* d  m" m      */
) b: Y' n& U  z# V( y    public static void cleanupImage(Rados r, IoCTX io, String imageName) {
7 M4 S2 b! H0 C- o! P- f        try {3 M- t+ u$ r4 b$ Z+ A/ c1 C
            if (r != null) {
6 Y  P+ @5 c$ o2 v% q. Z# z  q5 t4 g                if (io != null) {
( i$ m' o. Z$ U) ~& W$ w+ i                    Rbd rbd = new Rbd(ioctx);
& Q7 r6 O) j8 c# \2 e9 X                    RbdImage image = rbd.open(imageName);
4 S- f5 s5 b4 B* B- R                    rbd.close(image);
. L% {  H1 v+ Y% v- H# k                    rbd.remove(imageName);: h. L4 y" W8 y7 f% h" i
                }( u7 m! g& o0 G3 [8 H
            }; h. m2 K+ K( G/ i0 d! t
        } catch (Exception e) {
4 P! H$ G& r3 V; P6 c            // TODO: handle exception
* ]; ^0 k# D2 r4 l        }  & M6 Z( J. E  v7 Z. c  T2 r% k6 N
     }( z( o4 R, J) ], H

! P7 M, l) u/ R3 T6 ?
+ N5 V3 `+ E6 U1 z9 n$ Y& A& G( s3 P9 X     public static void main(String[] args){
0 p$ |: n, Q* f7 ~  M7 y+ ~         connectCeph();9 S* R" {; \% w* D6 l: s
         //createRbd_format1("mysql-hzb-2",10737418240l);
! ^: |; m* }+ |( L- e$ d0 V, i5 `        //createRbd_format2("imageformat2",10485760);0 G% {' c- ?. ]4 ]
        //cleanupImage(rados,ioctx,"mysql-hzb");
- ~: N) H2 a, _' {/ Q. y         //resizeImage("mysql-hzb");
) f3 p% C! u0 r5 q
; V3 g! u7 p( ~5 {2 h        // createSnap("imageformat3","imageformat3-snap");- K& K. m9 ]  {+ N
        //copySnapToNewImage("imageformat3","imageformat3-snap","imageformat3-copy");
: v/ E% N/ u: j         //deleteSnap("imageformat3","imageformat3-snap");
) c8 O4 B2 V0 r        imageList();
- }0 S4 S) A# Z) ^4 r. G! }, j* Y     }
4 n6 g- @) E( V; J}
1 e7 `, e3 g) b6 p, A8 t8 ?3 Y2 V4 y" ~, w; b: s2 U5 B1 G

3 F- l9 w* F3 B* ^: T/ }6 ^
+ Q  i1 C7 Q. I6 f# ]7 z
) ?4 h6 H7 b' w3.3 IoCTX源代码
/ Y3 U8 i( C7 N: B3 D4 W  g3 W/*
, ?3 F& @; x6 S; U) h) ?' r" O; i+ } * RADOS Java - Java bindings for librados
8 _1 E$ t  o9 Z# u: s8 H *6 _" H. U; }" R2 N/ Y1 B7 Q
* Copyright (C) 2013 Wido den Hollander <wido@42on.com>
# ~4 x0 v% U* Y/ e2 ]# K * Copyright (C) 2014 1&1 - Behar Veliqi <behar.veliqi@1und1.de>
( n' B6 S. l% \2 Z- o *( Z# B+ @4 _* M6 S  [8 G
* Licensed under the Apache License, Version 2.0 (the "License");
0 a# m; e  w; p+ c0 ?& \% p/ J * you may not use this file except in compliance with
$ K- r! \7 K+ @/ }: I0 J# V; q * the License. You may obtain a copy of the License at
# W( ?0 {4 R2 m* @6 i *: Q% {/ W; |$ a6 c3 l2 n
*     http://www.apache.org/licenses/LICENSE-2.01 n2 G% V! ~& g, {  a3 m4 P# d
*  c( ~; S# [. h/ I5 R5 [
* Unless required by applicable law or agreed to in writing,: ^' g8 r; J$ B
* software distributed under the License is distributed on
5 F6 _0 [# J0 w/ H+ A * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
) z6 Y6 O* d. U2 a$ V: h6 n2 \" ? * either express or implied. See the License for the specific
6 S+ V3 D4 Q+ }" K, G- {" ^6 r * language governing permissions and limitations under the License.
9 b  Q9 ~, T) H+ \( r2 ]* n! k- \ */# w/ Q7 }& Z. J
# n7 G4 D7 Z0 P' B6 z+ K
package com.ceph.rados;
# D* ~$ m! I; J8 {5 d
9 P# q; P0 Y  simport static com.ceph.rados.Library.rados;
. {% C: k# R2 S7 ]6 i9 u6 k
. N1 n# {/ Q, v; uimport java.io.Closeable;
) U9 p3 `! o  ^0 Y% b6 a% ?import java.io.IOException;
1 |3 e, p. i' y8 s1 j# limport java.util.ArrayList;
1 ~2 g2 D3 w( t2 d+ j/ |% g% zimport java.util.HashMap;
( ?" N2 M6 d, }" U4 cimport java.util.List;( x# {, f2 H7 ?" {3 S8 q
import java.util.Map;
: \. o) g/ i5 j3 X2 J6 f! kimport java.util.concurrent.Callable;
. T/ v7 c- E$ U
, q$ S) Z6 Z& |1 O9 Yimport com.ceph.rados.exceptions.RadosException;' S5 `! S+ `" M' N+ L- _
import com.ceph.rados.jna.RadosObjectInfo;5 ]+ W* n4 _3 n( F1 U8 j
import com.ceph.rados.jna.RadosPoolInfo;& y1 q+ z% r, x
import com.sun.jna.Memory;
! K) p8 @+ m% ^% mimport com.sun.jna.Native;1 B3 x- [! j5 q
import com.sun.jna.Pointer;' V+ B6 P5 o4 J- b# U4 P
import com.sun.jna.ptr.IntByReference;
. n7 `% _4 W" A7 T! m2 ximport com.sun.jna.ptr.LongByReference;
- J* q- H1 X& L0 a& Yimport com.sun.jna.ptr.PointerByReference;
7 N% i- F' |* G
2 H8 n! V- y, m5 p; ppublic class IoCTX extends RadosBase implements Closeable {
+ O& F! z, O' \1 Z5 G' ~+ L) S% s% G4 m2 ]2 A! Q5 r9 g
    private static final int EXT_ATTR_MAX_LEN = 4096;( C6 m6 R% J1 R  ^2 i1 x

$ y5 d1 u1 c- t    private Pointer ioCtxPtr;
4 T+ E& ^, l3 d! K, n1 \8 D: Y6 o
' D2 S5 {1 Y& D9 _# ]( I; f+ c    /**
' a( c6 C; W$ R" J     * Create a new IO Context object
: X; d. E( t0 u7 y( I$ l     *0 a# N  J9 z, v! K6 O* p
     * This constructor should never be called, IO Context
! ~  W9 [( @! \. F9 v     * objects are created by the RADOS class and returned, a  }2 r/ H# s- a& E& x# O
     * when creating a IO Context there
3 w4 ]2 v; Y. ?$ {4 s% a4 G    */
, L+ z+ ?7 W' R) J- @+ S    public IoCTX(Pointer p) {$ B: @7 W7 h4 {% X0 J, b
        this.ioCtxPtr = p;- m4 K1 {  u! [1 ~; a  k) p0 [& X% z
    }" e9 `( c1 F/ E8 f0 o

* t! P: i1 E/ h2 B+ f- [! L% P+ Z  s    /**$ h3 c+ `$ c, W% _$ M/ h
     * Return the pointer to the IO Context" x. [) z. e; |& |0 p6 s( \1 H
     *
, @- q- E* }: a1 O# e! y8 S  n     * This method is used internally and by the RADOS class
: t; e$ M$ j8 b1 @; w; \* w1 k     * to destroy a IO Context: E% \" i. M6 w4 F8 h0 M
     *
9 |  G% K; S0 J4 X     * @return Pointer$ H3 O, z7 g! y! i9 G
     */
% h! w$ M; r# `" f    public Pointer getPointer() {5 A' E$ h, `$ F8 A+ N  b6 _
        return this.ioCtxPtr.getPointer(0);
& P6 |5 t4 x  q2 l+ w+ S, {; O: t    }
' @$ j: x8 _& u) U& d1 m+ y0 m% F5 A' J  n) `1 \! l
    /**
' z  s  @1 i+ W7 s     * Set the namespace for objects within an IO context.# A" g3 A3 Q0 X' M, Z5 x
     *& ^+ L) X+ o% I9 o  G8 {' N( R1 m
     * The namespace specification further refines a pool into different domains. The mapping of objects to PGs is also based on this value.! J: `& J! A5 h6 ?* t( |, L" i
     *
  T) H/ j9 w- r2 A3 b4 G- @     * @param namespace The name to use as the namespace, or NULL use the default namespace.5 F* a$ N6 v9 J5 B- |9 Y
     */
6 }# g0 q- M+ U6 B; J    public void setNamespace(String namespace) {8 K! u3 [6 _! a% q3 Y) t) m1 G
        rados.rados_ioctx_set_namespace(getPointer(), namespace);2 z5 G0 V6 Y) O
    }5 D( e* l, ?- V% @+ v1 S& T# B

0 j* v2 S% o  M6 j    /**9 e  H0 Z7 p, Z' b! u8 A/ @
     * Get the pool ID of this context( K- l0 |, a. z) H0 k
     *+ W6 F; l+ j3 A: G8 }
     * @return long
" s3 L+ p" ?9 z! t4 t0 P: ?$ `     */
2 v# E- I2 `- h, v* J    public long getId() {7 |: o" r/ O) N& n, n$ l$ c- a
        return rados.rados_ioctx_get_id(this.getPointer());
! d% P9 ?8 @/ d: Z$ ]    }
0 c! d# g' H* K' s( T
! s5 N, O- H" \- Y    /**! Z$ d  {8 @$ X& ?/ Y6 i" P
     * Set the associated auid owner of the current pool
' p- z( a3 N8 q9 A     *
1 ^# {: d% d2 j3 q( U8 a     * @param auid
: d5 w' N/ r# y+ N5 z     *           The new auid
% ]9 ]' g- Q6 U, s; Y" e     * @throws RadosException
3 w+ x5 {9 }, }" u     *// A5 h! C5 e$ V$ O/ ]+ D1 l& [
    public void setAuid(final long auid) throws RadosException {
0 K% [5 }9 t( G6 Y        handleReturnCode(new Callable<Integer>() {+ t5 ?, b' t# Q1 e
            @Override9 h% l. U* @) y! Z0 o5 V
            public Integer call() throws Exception {! A( ^1 `/ [1 ~
                return rados.rados_ioctx_pool_set_auid(getPointer(), auid);- x4 ?7 i; _' N! u* w$ f( ]
            }. Z/ Y3 B2 l2 }& h0 k
        }, "Failed to set the auid to %s", auid);
* ^4 a" W+ b8 U6 ?    }
9 `' V9 t/ Y* _# [3 T+ ~* z3 e7 }9 `. u3 K) M* U" W
    /**
! Z% H/ T, ^  r% Q$ F+ A8 @2 B/ d     * Get the associated auid owner of the current pool
9 w8 [. u6 J/ j+ ~& o0 l     *
* c) w- {" U0 F* [1 n     * @return long9 {& w9 y0 V9 x+ k1 j$ }
     * @throws RadosException) u- L' a6 {9 w! M8 V# R- Z$ X" t
     */1 _# n% W8 e5 }2 [- W
    public long getAuid() throws RadosException {
, O% T3 W% ]+ r        final LongByReference auid = new LongByReference();
5 p. i# ~7 p* Q- T6 o1 z5 ~4 ~& m8 D3 a( _) x5 q" J
        handleReturnCode(new Callable<Integer>() {
$ A2 f4 y1 W/ o& I& T            @Override
1 d' V( W, m3 W. s            public Integer call() throws Exception {$ G; g' t. k# A- x* |- Z; D3 ^1 H' q
                return rados.rados_ioctx_pool_get_auid(getPointer(), auid);
" `: l, `$ m% G. S            }
* o( {! y+ O: c1 g9 O        }, "Failed to get the auid");
4 N5 B* E8 D" ?. E- E3 g+ \* R8 r6 C7 M: f  j  g' x2 S
        return auid.getValue();
1 @: z" E* o+ o2 T( W6 U. y% K    }6 c' I. W& B1 l9 K3 t

% C5 a+ T' H* [    /**
; q9 y3 ~9 j! @, z0 \& M, K8 z     * Get the pool name of the context
9 _; V& D. D% }4 i+ X" y     *
; W* b' G+ v5 y0 [1 q& C- O9 \: m' @3 \     * @return String
1 J0 e2 C" S0 a7 T0 C4 |     * @throws RadosException
" @5 o4 I8 n# V6 {4 h* T3 \% B. W     */
% `8 R6 \! \5 P- K" k$ p4 X    public String getPoolName() throws RadosException {: g0 i( b; C4 f& n$ w
        final byte[] buf = new byte[1024];1 k3 c+ a) q; L8 H* G! M9 P# r
        handleReturnCode(new Callable<Integer>() {
% }) R! `* A1 r. H7 V& F7 h            @Override
% N: G3 J# G  n/ |4 l% U7 @( D            public Integer call() throws Exception {
3 B+ N& \* H2 j7 m( {# R                return rados.rados_ioctx_get_pool_name(getPointer(), buf, buf.length);
( |& X8 |& c+ R; K! |& e            }
; H" a1 Y/ P1 s2 H  f6 z$ q; `        }, "Failed to get the pool name");
  I9 F' \2 {# B) Y- B% ^        return Native.toString(buf);
1 V8 S5 I5 p; q! ^1 O    }* ?' Z8 @6 k( N* v$ P

. a2 h3 S1 n0 N3 {/ U    /**( [- @# L6 M4 U6 z8 U& @' a- F. [
     * Set the locator key
3 q0 u4 {" a1 x     *5 l$ _4 G7 J+ a$ }) ?% }1 N& j
     * @param key2 e2 |/ \3 \1 y: r
     *          The new locator key or NULL to remove a previous one
9 r1 t$ o0 M0 N& V     */! D" ~6 n% d: y) ]+ [
    public void locatorSetKey(String key) {! V) Q" w. f7 T# _3 @/ c* l
        rados.rados_ioctx_locator_set_key(this.getPointer(), key);- g2 j! y. L1 N, z5 }
    }
6 o; o6 L: K: C) r. @9 C4 y- L) C5 b! Y& `$ ~9 ^
    /**
/ f( c2 Z7 o. L# L4 j2 a     * List all objects in a pool) H$ U- q0 D. C; ^: K
     *( ~& B1 D4 V# s
     * @return String[]
  r7 S" R5 Q/ z# ]. F     * @throws RadosException
- n, w% |% [( S% s  m4 z     */
3 K* e# x+ S% t' x, k    public String[] listObjects() throws RadosException {9 |" J3 x$ ~; E5 v
        Pointer entry = new Memory(Pointer.SIZE);9 W) E7 O( F# r! g8 A& \
        List<String> objects = new ArrayList<String>();
) g. h1 }) a+ E& z- C3 X        final Pointer list = new Memory(Pointer.SIZE);4 q1 D0 @% l9 O$ Z2 Z
6 p" F5 Z+ p3 a1 A& p4 I! o4 B& \* ]
        handleReturnCode(new Callable<Integer>() {
. [6 B6 {+ o4 t- G& s1 ?  f, Q, G' c            @Override
8 g$ E8 R7 y; N6 F7 I            public Integer call() throws Exception {
- `7 t7 }' t) t, x; [& q. w* u% ~1 k                return rados.rados_nobjects_list_open(getPointer(), list);
& J8 K" ~6 [% k' [  q) f" Z6 x            }2 _3 S: \; T, A, k3 ?
        }, "Failed starting to list all objects");$ B, |& `" e: \) ]& w$ [
8 e6 V5 b8 n9 R# _4 M
        while (rados.rados_nobjects_list_next(list.getPointer(0), entry, null, null) == 0) {
' H8 h# \$ q) N! J! H3 {4 G            objects.add(entry.getPointer(0).getString(0));" R8 r, l4 f0 L
        }- ~- Y& k' V+ f! u& L0 l7 s) m

( s+ K2 i3 N( p        rados.rados_nobjects_list_close(list.getPointer(0));
5 y1 E' X0 D  u$ V. X" P% A' ]. y/ e" O3 Q+ Q
        return objects.toArray(new String[objects.size()]);2 `' A4 [4 w5 K; W0 [; t
    }
; L: [8 l1 O- D! I  [2 o2 p, B2 d; E; j+ l
    /**
& X( ?6 q) `7 I: S     * List all objects in a pool by piece. Useful if a lot of objects are in the pool and do not
7 N9 j) q9 {9 ~, z0 X5 t     * fit in memory through listObjects() method) |* F" `* B( K! G1 r7 k! w8 w1 ~9 o
     * @param limit3 r0 v$ h- I& n! Y
     * @return a ListCtx from which nextObjects()/nextObjects(skip) and getObjects() could be called
7 h4 Y+ c3 @8 ~# @! Z1 u* W7 x& H+ G8 n     * @throws RadosException
0 E6 v8 G% X8 T. i) X) Z     */6 ~( x+ e; B7 F! ~3 Z; j
    public ListCtx listObjectsPartial(int limit) throws RadosException {1 f6 k8 `7 L0 l  r7 o
        Pointer list = new Memory(Pointer.SIZE);
) K6 \8 X5 f: T; G2 x" P. ~
  A3 m/ }  D% e8 b        int r = rados.rados_nobjects_list_open(this.getPointer(), list);
& F5 M' _) n( ~; f3 [" q% n4 N        if (r < 0) {
  W1 T% M7 g. H* ]2 M5 Z5 H- l+ @1 L            throw new RadosException("Failed listing all objects", r);- w0 L" N& H9 Z& o/ b
        }9 t( z) t- V& X+ x- d3 z4 p
        return new ListCtx(limit, list);
/ ?$ _6 h0 h0 X  ]6 n. @    }# U# b3 X8 w+ \" y  Y/ X

3 p6 z! i& _; Y) m! D6 [8 W' y) M    /**8 p; g/ b9 N2 B  Y% r8 n0 k
     * Write to an object! C9 z8 T8 \; ?
     *
9 `$ _$ v9 s0 W4 C/ c" {' [     * @param oid
6 Y5 b7 U+ f- ?0 a7 X4 A( f     *          The object to write to  x% |+ B* t& k+ V; G5 W
     * @param buf  S6 D( ?6 N. p* S0 k- D
     *          The content to write8 a! e! M+ j- z- P
     * @param offset7 S% j' a( f) N# R9 z  _
     *          The offset when writing
8 C1 f4 g3 L* }9 g- ]$ p9 b     * @throws RadosException) M) B; V( V3 c: w/ O3 C
     */8 g/ b7 s$ Y9 ?, \. ~; N  s& |% \9 x1 L7 U
    public void write(final String oid, final byte[] buf, final long offset) throws RadosException, IllegalArgumentException {& L5 D2 N' M4 |  ]
        if (offset < 0) {
$ v% P' b, Q6 r0 T9 u8 A) d            throw new IllegalArgumentException("Offset shouldn't be a negative value");
9 ~+ C) X% y8 u3 z        }
5 Y: B+ ?" L4 }) B. }        handleReturnCode(new Callable<Integer>() {4 R0 N7 h2 t, q' ], k# B! \" H2 a
            @Override
+ ?8 e' z& z+ e( K4 R            public Integer call() throws Exception {# W0 V  c4 s4 l  t
                return rados.rados_write(getPointer(), oid, buf, buf.length, offset);
5 G7 R& L1 i: f& ]0 ?: C            }
# q0 a- ?% W( X# g0 y        }, "Failed writing %s bytes with offset %s to %s", buf.length, offset, oid);  k" H, [* ]* r( O" K" t9 R
    }5 U( I1 n$ W6 l3 ?6 B  |

" H  k* p2 A9 O( \* A* d    /**
: V; ?% j; j' Q1 V     * Write to an object without an offset
- T* U: ]  ], t     *6 R& N) B% t0 r
     * @param oid
7 _# ^$ t7 R: J' c8 z     *          The object to write to8 i9 ]0 i* s( v6 y
     * @param buf
* u: c$ P: Z; R* f     *          The content to write
& O+ P2 e! ]( I1 ~     * @throws RadosException
% j! `9 r2 K; N* Z4 m  d) _, T     */9 q( B" y& ^$ ^) |1 p) ^# k3 Y1 I
    public void write(String oid, byte[] buf) throws RadosException {
' d; c% f0 X$ s2 V$ F        this.writeFull(oid, buf, buf.length);6 |8 Z8 @  \* o8 j3 t
    }9 j! f/ T  b" T

7 D  f% P3 c2 V8 u+ l1 n  a    /**( S6 t1 ^$ E" G0 `
     * Write an entire object: `9 b- U% R, H: Y! J
     * The object is filled with the provided data. If the object exists, it is atomically truncated and then written.8 X- Q5 r4 F' F! r& Y5 @. a8 E0 _& @
     *
! E8 p7 C# I1 R- p) x+ L     * @param oid
* Z7 ~# b4 b& T  g" ~. g     *          The object to write to: h9 H$ T  [- f: N4 o
     * @param buf3 i1 y  u$ s4 [6 s- ^* E
     *          The content to write
2 P2 b8 l5 L3 |. p- |     * @param len
7 N  \$ }$ e' f' s     *          The length of the data to write/ N- X$ N  t4 x1 k4 k( N
     * @throws RadosException. M4 M0 w1 j- ~; |  T4 c0 `
     */
  S# [. [; Z# D2 h: ~! v    public void writeFull(final String oid, final byte[] buf, final int len) throws RadosException {& v3 a. i5 M' T; x
        handleReturnCode(new Callable<Integer>() {8 g+ `& S0 d0 m# N& s
            @Override) B6 z  t3 t4 y& D6 ^; W
            public Integer call() throws Exception {
1 c0 T% Q- G7 t" h0 O                return rados.rados_write_full(getPointer(), oid, buf, len);
2 O) P' A9 j* a            }
% I; R: `+ `5 c3 H9 c& R        }, "Failed to write %s bytes to %s", len, oid);
! D$ f& O9 g: A    }
5 |: @" _, t; L2 \$ Z" u6 T5 A; `/ v3 @" }
    /**
, M# e9 x3 e3 s' j& E# j     * Write to an object without an offset
$ T( D) y( b: b- l: N$ g- W* F     *# M  i( _: I- J  _' N
     * @param oid
3 |' ?- d% {8 Q9 B# J     *          The object to write to: l6 r# }* B; d# x& e0 A
     * @param buf
1 Y% |/ G5 {- X# W8 ?7 e, D! |     *          The content to write
& d) Y6 R+ E- ]! n) C     * @param offset  v# B7 u" U2 q8 Z
     *          The offset when writing
: y( q3 {) ]6 N9 I# s     * @throws RadosException- D2 l, ~. z2 X; Q% i2 ~& }$ B
     */4 f  W& K$ l- z( v! c# d0 X
    public void write(String oid, String buf, long offset) throws RadosException {
: l) p8 \' O! e# F  k! s( r$ M        this.write(oid, buf.getBytes(), offset);
5 w1 g: C3 |1 j. i7 g) |: m# d    }% O  z0 i, }4 c7 ~2 m
) p0 W8 ?7 _: H, Z! Q2 I2 S+ e
    /**
' B& d: q6 o. I' @     * Write to an object without an offset
3 N& }5 h8 M" `5 T  d     *
- \9 y" h$ d- A$ n     * @param oid
! M; n( ^( D; g3 @7 Y7 H$ a" L     *          The object to write to
" W0 e. b* n7 Y' y  _     * @param buf, n8 X6 B- T1 G; v: E9 g
     *          The content to write
: q* {; i7 U% p0 Y) i7 T     * @throws RadosException
& O, i0 e6 Y9 s) F4 P     */, p! E# l7 ~5 Q* B/ c0 B
    public void write(String oid, String buf) throws RadosException {2 H0 D7 P8 r1 p* {4 E
        this.write(oid, buf.getBytes());( ^2 K: w, R& w8 T! f2 ?
    }1 I' f6 ?0 A4 O1 d) L
3 g& o+ d- I' u+ Z* {4 I
    /**
4 A8 ?2 l# H5 |3 P8 |0 G# r6 o, W- v     * Asynchronously write to an object, g2 a! p  J" J8 ^& G
     *6 @2 d( c/ u8 q" y( a" U- n7 G
     * @param oid
5 _8 j) a$ J' b, F# d1 g: M     *          The object to write to. @" L5 ]9 ~( ]
     * @param completion
1 B1 N- }$ k8 V2 r     *          The completion instructions8 V" u" o2 e. L0 y: ^* u
     * @param buf6 |( g! v) _* R
     *          The content to write
0 c; W; v% K  n7 j" c     * @param offset
5 h4 ?2 p4 d8 I4 D+ U/ X6 M     *          The offset when writing1 H0 l* B8 G9 K, n; T6 R
     * @throws RadosException
0 H3 U1 h" W$ ~( A$ A+ ~     */
( i/ b1 D3 y8 x+ h( H6 X    public void aioWrite(final String oid, final Completion completion, final byte[] buf, final long offset) throws RadosException, IllegalArgumentException {$ h$ e- h! ~/ |) ^
        if (offset < 0) {* p4 F/ Z% R) s( `) {
            throw new IllegalArgumentException("Offset shouldn't be a negative value");2 S. [. a# Q  u9 q  ]
        }: p3 ~: i* l* ^) J; D+ f
        handleReturnCode(new Callable<Integer>() {* e4 b9 W$ g9 H% F- g1 |( o
            @Override
$ ~8 U1 H. P3 I* @! m! u' K            public Integer call() throws Exception {5 Y* Q) A3 J) o4 s
                return rados.rados_aio_write(getPointer(), oid, completion.getPointer(), buf, buf.length, offset);& C  R0 G% K# Y$ X% P
            }( H- t, [# M: }5 i
        }, "Failed AIO writing %s bytes with offset %s to %s", buf.length, offset, oid);
0 g- k! u4 L7 @    }! e0 n8 b2 p& r* k2 W8 n/ t& S( v

) F7 [$ v! H3 R9 N9 ~7 _    /**( U. e1 p, z) \: Y. I! q$ f& ~
     * Asynchronously write to an object without an offset
; }/ i6 p1 A8 l9 h/ W8 B5 Q     *$ U& {. `9 [; X9 H6 r
     * @param oid4 X3 ?- @  v" g
     *          The object to write to1 L% x  S7 b7 @1 J% I
     * @param completion& X  ]8 h! c& F( P
     *          The completion instructions
- F2 x- }- g* D* o# U8 S: N; _: ]     * @param buf
4 c- f/ H3 Q6 d     *          The content to write
0 d9 P2 Z8 R% m: o7 Z     * @throws RadosException
. e7 @, N3 T- ^/ F1 |- A     */$ x( G" k- s# l9 h* v' q
    public void aioWrite(String oid, final Completion completion, byte[] buf) throws RadosException {
" I+ {; B- i, K5 V        this.aioWriteFull(oid, completion, buf, buf.length);2 l6 g' t: v' S/ {  k9 a
    }
. d, B' l" Y2 l. ]2 k7 a5 c) h2 ~% L
    /**
' o$ W" B) s8 u/ @     * Asynchronously write an entire object
* \2 @9 l" ]" k& K  _9 h     * The object is filled with the provided data. If the object exists, it is atomically truncated and then written./ l. ]: b( L5 z* I4 ]
     *
$ c3 `# {7 ^$ T0 x     * @param oid7 w% r% Z# C* Y. f
     *          The object to write to
  f- g- R( E1 r' m" @     * @param completion
  A- u$ \4 X, k' B4 ~     *          The completion instructions
$ \+ q8 P0 M' ^, Z5 _8 v     * @param buf/ J5 T9 Y7 @- M/ f
     *          The content to write* m$ m0 G: y; r: Y3 m8 M7 A: X
     * @param len8 K2 B/ j0 A9 W, L
     *          The length of the data to write
/ d$ S( x( {1 N: N$ Z1 o     * @throws RadosException" d  G; @" f1 ?" ?) M! G
     */% n& y6 y# N9 X  ?+ p
    public void aioWriteFull(final String oid, final Completion completion, final byte[] buf, final int len) throws RadosException {
5 \6 w0 {4 [) v( v5 l        handleReturnCode(new Callable<Integer>() {5 N% o& s& s$ I5 W% s( M, h
            @Override! ?8 x6 y# I: A0 u+ [) v
            public Integer call() throws Exception {& u4 B1 A" B! O7 i5 [& i9 Q2 ?! T6 q5 d
                return rados.rados_aio_write_full(getPointer(), oid, completion.getPointer(), buf, len);1 A, c6 [: H& _( _$ `
            }
6 k3 T+ Z0 G. U        }, "Failed to AIO write %s bytes to %s", len, oid);4 f& `. F+ ^  F) v) z
    }& b- B- x' g6 S7 G8 K! U
/ G1 A/ R  B8 I' ~+ p( t
    /**
  v7 {2 _# i# U  q$ o9 v/ `  E     * Asynchronously write to an object without an offset
* q% m9 J* b) p     *
; c2 ]* Y: O/ L2 D' U5 t     * @param oid
) ]) x; {$ {4 A& o% c7 y5 n     *          The object to write to) t  A" R9 v1 E$ Q" U
     * @param completion- {; S6 I2 f- r' {2 {+ t
     *          The completion instructions
) H# M0 R* e2 ?. n6 c# F0 z  C     * @param buf8 e% n. R7 m9 H7 g$ x1 p% K0 |& l
     *          The content to write
+ n; K( Q5 ^0 R9 }5 j7 d( Z/ Y& x     * @param offset* a& D( ?$ n( B5 o, n8 b) k4 \
     *          The offset when writing
- f: C1 M5 H. f& h% Q     * @throws RadosException8 ]& p; W9 t# \/ Y+ S
     */
+ C) O6 a! k1 c! s1 v0 D+ J    public void aioWrite(String oid, final Completion completion, String buf, long offset) throws RadosException {3 _6 Z. U' p1 }( J. I4 |; ~& ~
        this.aioWrite(oid, completion, buf.getBytes(), offset);; M* H/ y; K1 k6 d- y6 J5 z5 d
    }
" W+ p- i9 L  v5 B- M
0 J4 ~; [, T8 o: ~  D0 N    /**
4 [4 m8 s/ p/ c- h& R: o1 x     * Asynchronously write to an object without an offset
. m$ p5 W0 @# A( j6 ~! J     *% N7 C$ N- x( S! ]  Z, K
     * @param oid. e; x& C+ w  D
     *          The object to write to* m3 a* z5 w( R' H
     * @param completion
' ?1 @8 v; u3 {* B     *          The completion instructions
' ]( \4 w! U/ R  x% t6 z1 l* D  {     * @param buf
$ J3 ]9 Q0 e! X7 k8 N' b( x  H: U% |     *          The content to write* v$ P! Z' @9 N3 Z5 r7 y, m, {
     * @throws RadosException
/ x" L+ [- k) K! ^     */
  I4 c+ \8 W- H6 g% N& L" L' |    public void aioWrite(String oid, final Completion completion, String buf) throws RadosException {
1 v; ^( ^! i* ?3 _# o7 {        this.aioWrite(oid, completion, buf.getBytes());
( Z8 E+ C' k" e# H    }
- X5 Z/ `' W# L: \" ?- i- l1 U1 u8 y
6 m' t2 Q& R; p. Y' W5 U    /**7 m7 b+ `+ v- A# ]7 {' C
     * Block until all pending writes in an io context are safe.
  @9 v9 N2 e9 m4 G# V- g% v. q     *3 N7 G, ]  m) H* i
     * 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.% l3 x# v; x. V/ y2 z  u
     * @throws RadosException
' E0 k" A2 R& B* p. K9 h6 n6 g     */
, n( }4 z5 v* ^9 q, f8 N    public void aioFlush() throws RadosException {
% ?5 R2 M# t4 \/ T9 F0 u        handleReturnCode(new Callable<Integer>() {
5 Y7 `: N, U) J. w            @Override
3 @6 i/ v# h# N8 z            public Integer call() throws Exception {. M! f# U7 w# c5 _8 a+ O
                return rados.rados_aio_flush(getPointer());
& b, b' Z- t- J& R            }
& z# H) x8 `' }% R/ O6 i+ r4 `        }, "Failed to AIO flush");7 e, e& S9 D) _# ]8 h6 h7 I
    }# H6 T2 F) H# s; l# _

$ _  i/ U: i( \4 o  p    /**. c* Y/ N/ M3 r' @# X/ L
     * Remove an object
! a: ?! a9 x) F* {! u     *8 X" j8 P5 w0 y1 r2 J8 h
     * @param oid  l! @$ q6 M  h% W
     *          The object to remove% L% f  G& T, \- l7 q
     * @throws RadosException0 o" V# j2 h' G
     *// c+ j% v9 U( y9 c# A
    public void remove(final String oid) throws RadosException {
$ P& i" U' N2 B; H        handleReturnCode(new Callable<Integer>() {, ^+ E# D8 Z  N/ B5 w* G- [
            @Override5 O3 R" w9 r, V# L2 H: ^0 H0 _6 N
            public Integer call() throws Exception {% G; ~2 S; W) }, F7 z
                return rados.rados_remove(getPointer(), oid);
# J9 j4 O8 ?% A4 \) Z, p4 _! d            }
  i9 B# Z8 \" c, A5 s0 d        }, "Failed removing object %s", oid);
: V& ~+ @$ ]" m1 \+ w8 `    }1 Z. R: s! C2 E/ e8 R- q
, R% _' _/ X5 `6 r
    /**+ T# F  g. d3 [/ S: I
     * Read data from an object  ?' ]$ x. o0 {4 C) w  t
     *
5 g1 G4 y: s; N" [( _& }; K     * @param oid1 a7 z7 Q8 X1 i) X6 m; y' w
     *          The object's name4 q6 ^: T, {! o  ?
     * @param length1 d4 {; C+ i* w
     *          Amount of bytes to read3 k* E1 n+ B- k- r. s" d) p
     * @param offset
- ^7 j/ P0 R' |1 A! o9 K     *          The offset where to start reading$ M3 o0 |6 y& k5 J4 q
     * @param buf
! X) u7 U- s) w     *          The buffer to store the result# A" p( s2 e" ]
     * @return Number of bytes read or negative on error
3 o6 O# S$ \2 z2 o     * @throws RadosException
: D! f' d6 v$ p. H7 y/ T     */
; `5 l$ g1 [% F6 b    public int read(final String oid, final int length, final long offset, final byte[] buf)( e# ^) G. ?- _* J$ f, ]$ |
            throws RadosException {
7 S3 z$ ?; q# m. x5 z        if (length < 0) {( D  l  C! H9 F+ [4 k
            throw new IllegalArgumentException("Length shouldn't be a negative value");) ~4 Q' u$ W1 c/ J
        }
- L* O& m- w0 n; ~; M; o5 Z        if (offset < 0) {7 B, b: b) |, h5 {8 l! d
            throw new IllegalArgumentException("Offset shouldn't be a negative value");
, Z9 R# V7 l; X' d        }6 {3 |0 ]+ W* Q; Y& k
. ^( F( q6 W/ |& ?: R( v3 I' e$ T
        return handleReturnCode(new Callable<Integer>() {
/ G; D; O) j' R# ^, R            @Override, P: c" H: I( l# B: g
            public Integer call() throws Exception {" s2 b8 Q% z. s  i  w& L
                return rados.rados_read(getPointer(), oid, buf, length, offset);% x1 D9 V+ X$ H/ D( {9 ]5 M
            }
0 A2 K* p# x7 g& V5 Q        }, "Failed to read object %s using offset %s and length %s", oid, offset, length);
+ R8 w" u) I9 d  ~4 E4 w+ [    }
0 ~/ S7 L8 S/ {
8 I  z. r  N5 P( m- ^    /**
; @3 |, w4 h6 s! @: N; s# b! h: Z+ }     * Resize an object
+ T& L6 T; A( D0 X: D+ v$ q7 l     *
8 ^3 A6 E2 a: |: ]3 h/ z     * @param oid; B" G: G) x4 h2 f( n
     *           The object to resize
' b1 ^4 Q* w& m) W     * @param size
- S+ y0 B6 J+ _& E/ O  Z& ^& W% u& g     *          The new length of the object.  If this enlarges the object,
. w/ ^2 ]7 T+ Q1 d- ~- I/ B+ ^     *          the new area is logically filled with' c4 _3 T8 H5 M
     *          zeroes. If this shrinks the object, the excess data is removed.
- V3 g5 w" R$ v6 i9 T+ A. q     * @throws RadosException' @6 T6 [' ~- }* S+ \, m
     */, C5 H* \: ?2 q7 T& X/ g
    public void truncate(final String oid, final long size) throws RadosException {2 \" V5 |: n- F3 |4 T. C; p
        if (size < 0) {0 a; w9 A: G6 Z; c1 M7 M- a- J8 k" \
            throw new IllegalArgumentException("Size shouldn't be a negative value");
  x  s% X# K1 A7 Z* ^% u        }7 O* ]2 T* s5 |: i& j
        handleReturnCode(new Callable<Integer>() {1 [6 |8 B6 {1 }7 A0 v' Y
            @Override0 ^* n' l2 M7 n. R
            public Integer call() throws Exception {
0 K. S& |4 Q7 W; b0 U                return rados.rados_trunc(getPointer(), oid, size);5 T2 Q( G: \  s) {/ \
            }5 Z( R; ]1 P. Z' U: ~5 G1 E  o) z- p, x
        }, "Failed resizing objects %s to %s bytes", oid, size);
! B) P  ~! x0 i+ E, @2 x    }
# f/ y* ?) a8 P2 Z; e9 b
" I. W* W' S3 i4 R- F! K4 E- q    /**
0 Q3 x1 O8 J8 f8 k4 v     * Append data to an object8 C! f" v$ t, o3 \+ G% Q# S3 I
     *" a/ Y2 d% k8 _8 b: r2 \& Z
     * @param oid
; D: U' Z8 t# i     *           The name to append to
: G1 [. a2 q: V) g     * @param buf
, `3 A( q, x6 b# {! e" }: l4 R     *           The data to append
* O- j/ y% a2 G. Y. Z4 q: v     * @throws RadosException; N; `2 L0 r( d- V3 r
     */
) O0 k# n" O9 s    public void append(String oid, byte[] buf) throws RadosException {
4 a9 R" Q8 p9 H. m0 `+ }+ n        this.append(oid, buf, buf.length);
) ]1 Y& i) a) ~7 t    }
1 p( L1 d& Z+ F0 U" H# H( J
' {) n4 h1 [0 X% [( T/ _    /**1 _3 @, s& e2 ?* K9 j( u5 v& l
     *
( L8 K# ]! N0 ~2 T; \- Z% p+ y& k     * @param oid% b( _* L7 [6 |6 }# K3 [( E
     *           The name to append to! q3 V: L! c) I
     * @param buf
6 o/ A/ ^8 J" }$ y     *           The data to append
) x1 h& O8 S9 t2 ~1 h4 s     * @param len# F% v) C. n/ L4 s) _, B
     *           The number of bytes to write from buf- {. h! K# c9 o# I# C# X
     * @throws RadosException
4 x7 r" N0 f0 l( h& \     */
9 ^6 j4 U  P: A0 k1 e    public void append(final String oid, final byte[] buf, final int len) throws RadosException {9 H" i' K& k' b1 A% O; }
        handleReturnCode(new Callable<Integer>() {
, Q6 D  V$ i1 @: Q2 X) O0 l            @Override1 l5 O2 u  W4 X+ b8 ~9 D( I4 h
            public Integer call() throws Exception {
2 ]  [! K7 w7 ~& n$ a" V. S; @                return rados.rados_append(getPointer(), oid, buf, len);
9 j( o' D2 h6 A7 N            }5 Q( I8 H- d# ?+ c
        }, "Failed appending %s bytes to object %s", len, oid);
6 _8 q8 q. M3 a' K    }
- t' e5 q' _8 B) ?( L6 u2 L/ b9 Y: y% k' r% o5 [) B, x
    /**
* Y$ U2 c8 {- _/ s2 ?5 o( ^     * Append data to an object) }; K& t) H  O0 m3 j5 {& z
     *
9 h% [( ~# e! n: Q5 j5 X2 s     * @param oid
- R8 ]5 f% |6 M% ^- |     *           The name to append to, `' N# B: j  L2 Q$ L, t5 Q
     * @param buf- V2 t  x, j, y1 D% j3 n
     *           The data to append5 V' W# L2 d& ], h- l! ^3 _
     * @throws RadosException( p7 R, {9 _3 ?9 R: W) {
     */" O* x" D% K* x, i( `6 N
    public void append(String oid, String buf) throws RadosException {$ n4 i6 i* s& @
        this.append(oid, buf.getBytes());
9 y- w9 O; v6 A( a) U    }
: N; K5 g4 {( a
$ V0 d* i# s) `# r8 v$ L    /**2 `* g8 W6 Q8 ?/ k1 d" `
    * Efficiently copy a portion of one object to another% C/ n4 x" g& W: n" `( A% J" d7 k) }
    *
# |3 H' {) q) S, \2 j    * If the underlying filesystem on the OSD supports it, this will be a
* Y: U' i" G+ c; X3 b! p$ ^# n    * copy-on-write clone.& V3 A4 V+ _, L2 J* M$ D
    *
! {* R- V6 U; G: z, e- k8 M3 Q    * The src and dest objects must be in the same pg. To ensure this,; x2 f5 }8 X3 [3 x9 K4 f
    * the io context should have a locator key set (see IoCTX.locatorSetKey()).
6 _$ @8 J: ]% Y    *
4 i% A5 Z( F5 E( i! b. |( @/ S7 I4 n    * @param dst* n4 D3 k; [# i+ l' {
    *          The destination object
3 Z+ e! A; {# |* i" G/ P    * @param dst_off9 n2 ]& W% x8 a, f0 l, s
    *          The offset at the destination object
7 b4 o- ?; |' M! L7 B+ u    * @param src
% m# U% n/ P; q" T    *          The source object
& a* S% a( a9 o    * @param src_off7 D, Z& [; E5 S% M; p, X
    *          The offset at the source object6 C; X; \( S$ m* S( o7 T: ?
    * @param len
* W* _0 l% J6 n6 d    *          The amount of bytes to copy
" y6 x; ?  D% A( x1 b    * @throws RadosException
) r0 Q& j' [) ~) l2 T% M5 z    */1 n5 F' U$ P' ?; X, y
    public void clone(final String dst, final long dst_off, final String src, final long src_off, final long len) throws RadosException {
" W3 n, N! b3 z3 R5 |+ W! q% ~        handleReturnCode(new Callable<Integer>() {0 c3 a+ B: O" x; S0 X9 Y
            @Override6 d5 D* ^* r8 {4 U7 u) V, k
            public Integer call() throws Exception {
4 ]" I' \! V. ~' q. O0 H# J                return rados.rados_clone_range(getPointer(), dst, dst_off, src, src_off, len);
) {* y. J# C4 p            }
5 J1 z; k8 s( ?/ |+ g* F% f        }, "Failed to copy %s bytes from %s to %s", len, src, dst);" A2 u) Z& i5 _% Z) p
    }
; ^, v+ K" ?+ g0 |/ K3 v/ p! g$ f1 k" A- l% |# K* l  k6 U3 R* J
    /**
3 l; D5 x- P3 S. A: i     * Stat an object
2 Z7 i: F1 ~( k, M     *
  g* N2 @1 o' ]) d( e     * @param oid
7 q6 R1 C/ T) m# ]; v     *          The name of the object6 B5 ]# X% @3 E! J
     * @return RadosObjectInfo3 X0 [+ ~% Z) D; s" L
     *           The size and mtime of the object
( y* s8 n9 `$ E2 _     * @throws RadosException$ ~! [/ ?; U5 J$ `* h# @" z' l
     */6 n+ F9 I7 Q' z" v
    public RadosObjectInfo stat(final String oid) throws RadosException {
2 ?$ I$ |$ D; Y/ Z  R4 X        final LongByReference size = new LongByReference();7 I5 T$ C0 e. p: v5 ^+ x9 \
        final LongByReference mtime = new LongByReference();1 o3 [6 O6 L2 @& n$ @
        handleReturnCode(new Callable<Integer>() {
: b/ b( J+ u! ^8 X! B            @Override
# b! }7 S4 L  P, M5 u  B            public Integer call() throws Exception {
/ F7 }* G' s4 t$ ^, D                return rados.rados_stat(getPointer(), oid, size, mtime);
  m5 k5 X/ s5 x5 D7 x' ^; P- e            }
7 W, N  _/ i) {        }, "Failed performing a stat on object %s", oid);
% h" V, a9 B) R) t2 _) E        return new RadosObjectInfo(oid, size.getValue(), mtime.getValue());' v. j+ T/ r, N+ |
    }) m* `' u7 c& a8 s0 y* t7 V

3 D; a# D) D) v' i# |+ A    /**
# i6 A. U% U( N7 W/ A% @% j7 b* T     * Stat the currently open pool
, D) ~" {- I# {! |     *
  ^# i, G. \8 H% }3 N8 X     * @return RadosPoolInfo# F  V( A1 G. Q4 Y
     * @throws RadosException
, B- K& ?0 d2 E     */
: ]& w! x( t- g# L: I6 |    public RadosPoolInfo poolStat() throws RadosException {, {* Q2 W3 h/ x  L" ]* u. Z1 ~/ L
        final RadosPoolInfo result = new RadosPoolInfo();4 W# `" V' ^7 V% O; J4 y
        handleReturnCode(new Callable<Integer>() {5 j& T8 [" \/ o
            @Override& L, u- v8 G0 G; u$ Q  V
            public Integer call() throws Exception {
( o  N( |1 {$ b, F* h7 i                return rados.rados_ioctx_pool_stat(getPointer(), result);1 g3 a7 S* T3 |: y; g4 d0 o  c
            }* f% ]: G7 s) n/ @. A- i, I7 j
        }, "Failed retrieving the pool stats");
( F. u, G9 U$ \! ~, C        return result;# y: I% |2 A/ x' r
    }
4 w* h' \3 D" T5 E* b) Y; K% T1 O" t5 [5 R
    /**
+ B5 O  Q: E4 h: N3 }/ ]7 S     * Create a snapshot
- {$ V0 j  W& N! G/ S( @     *1 v7 q3 `( Q# m5 Y# m# B' l
     * @param snapname) t8 B" F5 u5 j) ?/ F' |- X
     *           The name of the snapshot
5 S9 ?5 Q1 p5 f& I8 p- `! C0 P     * @throws RadosException
2 i/ u! y1 y3 o0 C  |     */+ D0 q* R; H1 x4 ?! I2 m
    public void snapCreate(final String snapname) throws RadosException {
2 x6 N$ m6 @4 ~6 G- z2 H# C        handleReturnCode(new Callable<Integer>() {* S! @4 W5 ?, G% m; T8 G# N# j
            @Override
. P9 i2 Q/ i- g$ _  t8 }            public Integer call() throws Exception {
; o4 u3 w) Z" s: X, |1 T( u2 w                return rados.rados_ioctx_snap_create(getPointer(), snapname);# W: G6 W* E# t+ {* h' L. e
            }+ t2 D( Y+ {4 p3 ^* p
        }, "Failed to create snapshot %s", snapname);
  k; x, s# ~) M# h7 o    }* [; }' t& F' q8 _0 z. K9 K7 Q

6 Z  Y& h3 N) }3 ]- f$ a    /**
& X0 d$ D$ {$ U     * Remove a snapshot3 }* H# q8 ~4 q4 E0 F8 l/ N
     *
) ~  \1 {* [5 F1 S7 {) U     * @param snapname# i0 O" e) R4 _3 H- Y
     *           The name of the snapshot: ?+ Q4 Y3 g& J; L& s+ g: @
     * @throws RadosException& M0 r/ L4 p5 ]0 s
     */# T) o/ g- L; l& J- U
    public void snapRemove(final String snapname) throws RadosException {. \; _1 H8 X, Y8 D, f
        handleReturnCode(new Callable<Integer>() {
" H/ z3 a" G: V' _( X            @Override' G4 \+ F" L+ V$ A5 }+ E
            public Integer call() throws Exception {
4 x8 K6 K3 h% [. [! }3 r! F                return rados.rados_ioctx_snap_remove(getPointer(), snapname);
: B0 v$ R. G2 G$ G            }9 y7 y' K. \( k* A4 t
        }, "Failed to remove snapshot %s", snapname);
! d- G6 U! u0 _0 X4 J& {    }
) ], M7 t6 T* q* Z, R) l. o; F; ?# H8 i; w0 p% r" u3 n! U
    /**6 d" e% N. q; b  I
     * Get the ID of a snapshot
; G, m. s  }& c2 N7 Q# d5 A. R     *
' e5 [3 ]0 s1 i     * @param snapname
9 n# C: f5 w, |4 w* D     *            The name of the snapshot
  a8 q* K+ D+ O; m; k6 n. e. \1 K     * @return long
# p# K( ^  _9 R& E$ |: n  e3 M     * @throws RadosException" p' e8 |4 S* P2 T  }3 [- X
     */: A' X  p* P5 y
    public long snapLookup(final String snapname) throws RadosException {
* [; P! t0 g5 q: f  @3 l        final LongByReference id = new LongByReference();4 z% J- b( u4 @
        handleReturnCode(new Callable<Integer>() {
) Z% Y$ J3 L8 p; D            @Override
. H% u/ V1 E; X            public Integer call() throws Exception {
' b4 x, I. h$ d2 \9 K2 M                return rados.rados_ioctx_snap_lookup(getPointer(), snapname, id);
! ~, p% V4 Q! f" B. D            }
3 w5 H. O" p' R9 |        }, "Failed to lookup the ID of snapshot %s", snapname);6 b& T/ c; F' n- S, B
        return id.getValue();
( D/ m2 n. ?$ R# V9 Z3 E' J! w    }
, B1 @5 O. K' o. Z& V
& v. c3 W( A8 _    /**$ m+ h4 H! ^( ~, D. s
     * Get the name of a snapshot by it's ID
: s6 U, B! n9 A% E9 ]# _$ V     *$ p; r5 S+ B! e( Z3 O; M
     * @param id# ?+ ?6 y! p& p2 t
     *          The ID of the snapshot0 N* y! ~1 r2 ]: e, H6 O
     * @return String" s' L0 ]: }! |. ]' y% c0 u
     * @throws RadosException) C4 x& s# b" H
     */
4 r$ U) c+ ~1 [6 P: Z8 J2 j2 L    public String snapGetName(final long id) throws RadosException {' p3 C0 B3 ?0 \8 i, b
        final byte[] buf = new byte[512];
% Q/ M+ Q: n/ i5 a! ]2 ?        handleReturnCode(new Callable<Integer>() {% b7 s1 c" L- |: s
            @Override. i6 m; b6 l' v4 b: J
            public Integer call() throws Exception {- D5 V- C; c% }! \. t% {
                return rados.rados_ioctx_snap_get_name(getPointer(), id, buf, buf.length);3 i( n: @: `7 |: a( z/ `  n5 \0 o
            }
, j" H% g+ @8 A3 O3 d. ]5 A3 j        }, "Failed to lookup the name of snapshot %s", id);
" L7 r3 f' m8 Q! M3 J& g3 e/ N! v        return new String(buf).trim();$ c4 }( `$ `0 n3 n# R; K6 b# {
    }
& D2 F$ ]$ f: T$ t- ?
; T- X- G, I3 N' r* i    /**
' G) }2 Y1 D! ]9 Y$ p     * Get the timestamp of a snapshot
5 e9 x' w4 ^0 n7 w     *
8 \- ]5 L6 Y/ F# w  E. B/ J4 w     * @param id
5 u6 X0 h0 r; y+ z. q7 t- E     *         The ID of the snapshot' \, t& j- f/ W7 X/ {) q( R
     * @return long2 L0 {1 M1 m0 H- L
     * @throws RadosException
6 x' v/ E: \7 ^# I     */- i; z$ I) E" C) p/ e
    public long snapGetStamp(final long id) throws RadosException {
* Z! }' I6 Z' c% d/ A  r# T        final LongByReference time = new LongByReference();( L9 B) J' v9 q) z8 ?9 S
        handleReturnCode(new Callable<Integer>() {) q- O+ ?  z) m9 e$ J
            @Override2 t  k. m2 T9 R1 O
            public Integer call() throws Exception {
) t" h; C& g; Z; v3 h5 U$ b( @                return rados.rados_ioctx_snap_get_stamp(getPointer(), id, time);( V2 E# M0 [% b/ m1 |- {/ U
            }; q- C9 n; E( Y9 u0 f. x
        }, "Failed to retrieve the timestamp of snapshot %s", id);' G3 `2 c! v* O+ F  ~% \! b1 |
        return time.getValue();
) r6 Q& ^( G0 ~9 b- k    }
8 L0 k3 l' e3 u. L2 t" r; S  T5 {$ T7 Y$ \; c- \: H
    /**
$ Y- \0 O7 Y" R' b+ K" n# C, I     * List all snapshots
7 I/ f5 o' o) e$ A* s6 h9 x0 M# D     *4 w  B1 ]) c; ]. J
     * @return Long[]
6 C# b2 a: S& E( z  c     * @throws RadosException
; a4 Z( w$ m( S& f7 ~; ?     */: }3 D  x# D) y* m1 ^3 ?
    public Long[] snapList() throws RadosException {8 K6 S$ j) Q3 h; t0 s
        final byte[] buf = new byte[512];
7 y1 S% r7 g; b6 _! a- V6 P% ]! B& _9 K  Q0 M2 j/ ^4 w( i: j
        final Integer result = handleReturnCode(new Callable<Integer>() {* G! L; l3 M+ ?6 Z: }
            @Override2 i$ j8 [6 i/ x- R2 z6 ^2 H* d
            public Integer call() throws Exception {
8 u  O$ g5 J3 \2 k1 g" k" _                return rados.rados_ioctx_snap_list(getPointer(), buf, buf.length);
3 p6 M( P! l# {* S- v5 X; s            }/ p7 v$ q* Z0 o- P. E, d
        }, "Failed to list all snapshots");
( M! i  q* c5 F  Q, x' m5 m" E
5 l+ X% e* t4 @: u' H9 t        Long[] snaps = new Long[result];0 m' }2 [+ S5 `; C* b
        for (int i = 0; i < result; i++) {
- o1 w6 U! `. k. B7 R2 U            snaps = (long) buf;
/ g2 @% b' r: B  r, v$ }        }
0 Z2 _+ v/ }& `! ]2 S$ h        return snaps;
) U/ C* `# S- s* l    }/ n% A1 @3 ~  G! h/ p

7 \7 c& e! c4 \1 ~    public ReadOp readOpCreate() {5 m; o* Q0 V. D3 d4 S: ]
        return new ReadOp(getPointer(), rados.rados_create_read_op());& J' d2 ?; m! x0 n
    }
: Q; {7 f8 F, [( F: r+ ^3 s( c# o9 a5 Q+ Y$ O/ i
    /**) @7 E3 c. D& V. \+ L
     * Instead of releasing the read operation directly, better use ReadOp.close
' S  f8 `6 `0 W; Q* X* F! O  a     */( c4 i5 R, c* p9 W# A
    @Deprecated8 m; L' T* p4 i9 N3 [
    public void readOpRelease(ReadOp read_op) {+ Y# Z" v: v9 }2 }5 I) S* |
        rados.rados_release_read_op(read_op.getPointer());
5 R) J8 P# I; Z0 T8 J    }
; v: ]+ M9 b) H3 V! Z5 a* Z% ^0 ~1 m* j4 f9 x2 X
5 n& @+ a" k5 I9 ]8 h9 F( s0 Z
    /**. y( I  {4 z# }6 `  T' G& i2 H
     * Get the value of an extended attribute on an object.% [5 k. t0 @0 {: R- e$ K
     *4 _2 C% d+ v. }: s" F  ]+ G
     * @param oid
) `9 a6 C, `. m/ W! S     *          The name of the object0 V3 T# a  p- G' O
     * @param xattrName
0 p! F) I9 s* ?/ W1 c: j9 f# r: L" _5 Y     *          The name of the extended attribute+ {! t, l2 r, ?4 N
     * @return- d% c5 [' n) W+ g! v
     *      The value of the extended attribute% W( q' O9 T8 Y, |- z/ P2 G9 Z, N
     * @throws RadosException
' j) j4 L5 r: D6 s& I6 ]. @     *      on failure -- common error codes:
7 Z. g. H+ k9 {) @& h     *      -34 (ERANGE)  : value exceeds buffer' x% W- h, G3 n
     *      -61 (ENODATA) : no such attribute: q& y1 |. g0 x; B, |7 C) M) f1 g
     */- \  ~! b2 y) o* j% W2 \: [
    public String getExtendedAttribute(final String oid, final String xattrName) throws RadosException {
+ _+ t' X% h$ e" F  w        final byte[] buf = new byte[EXT_ATTR_MAX_LEN];3 o( @& |& o# N8 n
        handleReturnCode(new Callable<Integer>() {# ~9 K3 `9 X9 p: c5 @$ {, e: Z
            @Override& f' \& V: \% j4 C: e) m- a3 B. D5 ]
            public Integer call() throws Exception {4 Z, n5 h* f, U! s
                return rados.rados_getxattr(getPointer(), oid, xattrName, buf, buf.length);
$ ~4 G  G0 a' Y            }
" Y. Z* O: _3 f0 A. E        }, "Failed to get extended attribute %s on %s", xattrName, oid);
. d6 k# V' A, t' `( o. Y/ C: S        // else...
4 W# j  l" M3 v5 y# F        return  Native.toString(buf);
7 f+ F1 |  Z/ _    }+ Y/ R! x5 ~" w* T; A' o

3 g, }. a5 @2 ~; w    /**
) {( }7 {6 \" q+ Q5 A7 s     * Set an extended attribute on an object.
' s3 {& V! n0 Z" X0 Q3 \     *5 ^# d! Y; e- a1 I  G5 @2 W
     * @param oid7 H" u' l& q2 }: U# y( Z# X! M
     *          The name of the object4 U/ \2 [" D$ l: }/ @' a% ]
     * @param xattrName+ @: p- b0 J/ O8 P
     *          The name of the extended attribute8 o7 b. Y7 l5 K! Q9 n1 z! L
     * @param val8 P# {7 w$ t5 F7 m
     *      The value of the extended attribute
) _2 R2 i' h! [& O, `     * @throws IllegalArgumentException
. a$ G, \' S! n. c' w' ?8 ]     *      attribute value is too long$ p7 Q+ E0 d0 M. p& S
     * @throws RadosException
; M: H3 F6 i4 @$ {: S) l( s     *      on failure
( w& O' Q( y# H     */
% ~' p- o# @3 u' B- i8 p3 }    public void setExtendedAttribute(final String oid, final String xattrName, String val) throws IllegalArgumentException, RadosException {
+ p' W. x4 }0 H* O, V        final byte[] buf = Native.toByteArray(val);; f/ h  D- _( T! m4 B; \. s6 s7 m
        if (buf.length > EXT_ATTR_MAX_LEN) {
# x6 u) x7 d; t7 _7 m5 q            throw new IllegalArgumentException( "Length of attribute value must not exceed " + EXT_ATTR_MAX_LEN);
% q. q/ B* W. U8 P# t* ^        }
: P; z  Z  T* b% `4 `$ M3 |" n        // else...) ^0 s4 g: w" ]) t2 {- R& {
        handleReturnCode(new Callable<Integer>() {
* o2 ~$ n/ c: J: r            @Override, G1 G- }8 r1 ]( C" S& a
            public Integer call() throws Exception {4 l% _4 w# ~4 I; W7 Y4 u6 D
                return rados.rados_setxattr(getPointer(), oid, xattrName, buf, buf.length);0 h4 g" I: i+ {" o
            }
$ B/ ?! ]9 _7 V' f        }, "Failed to set extended attribute %s on %s", xattrName, oid);
( x# I- f. e. u0 i" t    }  L/ |3 z3 |$ H" y( Z

9 i3 R' ^9 O( m. z; r$ O$ o    /**4 C, Q& g* q' b# U
     * Delete an extended attribute from an object.
- b  ]. p( O$ d7 }     *
# T! u& |" b+ k% _- f5 z     * @param oid3 A8 l. Y) C- d6 d* B
     *          The name of the object
( b7 I" a4 p, x; R+ x( x     * @param xattrName
1 X, P8 Q5 K% W% C     *          The name of the extended attribute0 }) K+ h  f& I* z" D/ T9 r) @
     * @throws RadosException! q9 c; s: U% u( V3 X
     *      on failure
; \9 u& I, e9 D! ]; {5 K& j     */
) g" d( y$ [' u    public void removeExtendedAttribute(final String oid, final String xattrName) throws RadosException {
) w9 b+ U7 F+ c7 i  b6 ?! L* f        handleReturnCode(new Callable<Integer>() {# J7 R. }4 Y1 U8 ~
            @Override% C7 q5 l) [4 n
            public Integer call() throws Exception {: K5 w. @* Q* P' w4 s2 D) D
                return rados.rados_rmxattr(getPointer(), oid, xattrName);
: Z, v: r4 _0 H/ O            }
% t2 S" e/ @$ m  s5 O( D, B        }, "Failed to remove extended attribute %s from %s", xattrName, oid);" K  Q& Y. u+ e' A  N
   }
% e) A9 C0 w0 c5 ^. q
% U* f% j2 s% s6 @$ p; S; f1 F3 I   /**
; N5 ]9 U8 h& n' K1 o) G     * Get all extended attributes on an object.
0 e' O( m- q3 O+ t3 y     *
* e6 n# Y6 f1 E3 p  }     * @param oid& C, v% r; p& E  }% X( ?
     *          The name of the object' p( F8 V4 z0 V
     * @return
/ e/ r- j: R: T: O     *      The map of the extended attributes) \, i% {- N! X* R" g
     * @throws RadosException' \2 w+ \) Z. B! I" T4 R: Y3 A1 k1 X
     *      on failure
7 Y: Z9 O6 I! `6 m     */  R6 T8 b$ s) L% i1 P3 \+ m: q3 ]
    public Map<String, String> getExtendedAttributes(final String oid) throws RadosException {
/ c+ @# {* e2 B/ g# C        Map<String, String> attr_map = new HashMap<>();
, _9 ?. e. r6 Z3 K# |8 V9 N" D( X( i" P        final Pointer iterator = new Memory(Pointer.SIZE);
" f: X5 P; g; n9 \6 V        final PointerByReference attr_name = new PointerByReference();. i( y+ @8 u, {7 L  S# _
        final PointerByReference attr_value = new PointerByReference();
& Y/ F) G* f1 a% Q. H) a6 q        final IntByReference attr_value_len = new IntByReference();/ ~1 v& \/ W  H" E3 r" U: N

1 D- n  s1 l' w        handleReturnCode(new Callable<Integer>() {$ w+ f) V3 ]- n3 |, f4 h
            @Override- R; s% j. A( P% `8 z% d& {2 c+ b
            public Integer call() throws Exception {
) Q; t+ Q4 K) l- F                return rados.rados_getxattrs(getPointer(), oid, iterator);5 N9 Y/ a# }1 H- N
            }! G+ l6 x$ W( G
        }, "Failed starting to list all extended attributes");+ H4 n4 l! }) e! r- s, M8 q3 `: V

8 v4 H1 m" L! ]        while (rados.rados_getxattrs_next(iterator.getPointer(0), attr_name, attr_value, attr_value_len) == 0& U% x% e: R0 z/ ?7 D6 s! q
                && attr_value_len.getValue() > 0) {
7 K: U8 G! A8 o- ]$ a% H6 n            int length = attr_value_len.getValue();& i& _8 w- p6 v  M
            String name = (attr_name.getValue() == null ? null : new String(attr_name.getValue().getString(0)));' j' a, Z- s) y9 Y# {
            String value = (attr_value.getValue() == null ? null : new String(attr_value.getValue().getString(0)));
. |) T' C$ q! s1 ]. m9 X            if (length > 0 && name != null && value != null) {
% x; l/ k3 r$ G; _* o/ A                attr_map.put(name, value);; L$ T1 _" n9 U  u9 m% P
            }
  x4 O7 ^2 q( n. @* E2 l( D- u        }
8 G+ h9 E0 X3 S! @$ y
3 q9 T6 ]* n5 C, Q4 N        rados.rados_getxattrs_end(iterator.getPointer(0));# u3 b& L: X8 I0 S/ \- `
+ @) f3 M& h: Z4 f( H* H
        return attr_map;
% u; D+ }) Z% x    }
+ [$ E1 S- r% h6 y, V: d; h$ b% S2 |: g8 F
    @Override  `- j5 p' N4 u0 v8 }+ ~
    public void close() throws IOException {, z( o5 k, w* c, G2 `% [! s
        rados.rados_ioctx_destroy(getPointer());
& W) a2 ~  E, E3 _8 y    }. H* t! w4 V0 k, Q8 \
}
3 P) Q/ |) X* s' \* Z% f/ A2 a
* f; p0 G- h3 p4 R+ a) V
  [& y' P; F# I& }0 ?0 d至此,大家应该对Java访问Ceph有了彻底的认识了
" R0 _& T" U% p9 C3 V9 I0 @! Z) x. v2 i# X9 _7 q+ ?1 a+ r0 ?
7 x6 e' a/ T- z& J/ V; H+ o& ^
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-12 00:05 , Processed in 0.022631 second(s), 23 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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