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

Java访问Ceph数据

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2023-2-21 15:00:18 | 显示全部楼层 |阅读模式
1. 部署LIBRADOS环境
6 N! }* t( b& T$ D7 B& G客户端应用程序需要librados才能连接到Ceph存储集群。
  ~6 X6 t4 n" ]( Y+ m: q9 |* ]2 b$ H7 o1 n, W
1.1 安装jna.jar' c0 J1 Q& t3 v* a0 Z: t
Debian/Ubuntu环境下执行以下命令+ K) A( R$ {+ Y' T$ u" m
! x8 V5 @. e0 M/ h. G) Z  u
sudo apt-get install libjna-java
( v# L/ A4 h$ c7 x3 i7 x$ X+ f& ^+ P
% o  ^, S  e7 _2 j
CentOS/RHEL环境下执行以下命令
3 K, |! t/ W# a0 s. i) i- F$ k2 Y3 e6 r) i6 ~: o# W& B
sudo yum install jna
6 e3 ]# J, K9 G1 n: _% Z, Y$ V+ M2 @' i0 D: h
JAR文件位于/usr/share/java.& r; x8 p3 d) d% j

7 J1 n  Z8 ?: i3 `& i9 Y1.2 克隆rados-java代码库
9 q+ a1 P! v: T  ^6 @& s( q4 {git clone --recursive https://github.com/ceph/rados-java.git
% W# A5 Z* d1 u' V$ J5 X# a  A4 C+ @6 M/ I5 q
1.3 编译rados-java代码:4 H6 z/ L- g9 ^
cd rados-java
# F6 r/ r# p* }! W7 _( N6 |ant
, ~% n) X! p5 Q9 b1 G2 K- S9 S. M, h
, h4 I6 l  i# R6 a
2 c1 e2 a( K9 @+ y5 s' e2 p$ BJAR文件位于rados-java/target目录下/ X+ B' Y1 Z+ a  p( ^
0 s2 Y; K& R( N8 h* @# f( B" H& t5 S
1.4 关联路径/ C6 k: H. ]: e2 D$ T
复制该JAR文件到公共目录 (例如 /usr/share/java) ,并且确认该文件和JNA JAR在你的JVM’s classpath目录中. 举个例子,你可以按照以下的方法来关联路径:
3 o4 G2 n  t! v+ _0 x5 D/ T$ T4 g) z) @# m0 {, I/ X7 |6 n- M
sudo cp target/rados-0.1.3.jar /usr/share/java/rados-0.1.3.jar/ P% w9 B5 u; X% c( d
sudo ln -s /usr/share/java/jna-3.2.7.jar /usr/lib/jvm/default-java/jre/lib/ext/jna-3.2.7.jar
6 E. K5 m' q  J+ gsudo ln -s /usr/share/java/rados-0.1.3.jar  /usr/lib/jvm/default-java/jre/lib/ext/rados-0.1.3.jar# x4 R  Q& J( H7 T" L* y3 Q! G
7 h! L* D& [- h% k) M& J

, F- @- T' t( q) F% U编译文档可执行以下的命令:
" b+ O$ p5 _8 ]: d, q& M! H( u& Y& }9 h' I. A6 k& l
ant docs" w3 x8 I  R6 l* P8 b8 y: {
. I" }" I9 Q" z2 Y: |# X; p
2. 配置群集句柄5 P0 V+ e* S0 @& |* D4 `) N
一个Ceph的客户端通过librados,直接与交互的OSD来存储和检索数据。要与OSD交互,客户端应用程序必须调用 librados 并连接到Ceph Monitor。连接后,librados从Ceph Monitor中检索 Cluster Map。当客户端应用程序想要读取或写入数据时,它会创建I/O上下文并绑定到池。该池具有关联的规则集,该规则集定义了如何将数据放入存储群集中。通过I/O上下文,客户端向librados提供对象名称,它获取对象名称和集群映射(即集群的拓扑)并计算用于定位数据的放置组和OSD。然后客户端应用程序可以读取或写入数据。客户端应用程序无需直接了解群集的拓扑。3 I6 \% M1 j# S

4 D# p9 W+ a$ k6 zCeph存储集群句柄封装了客户端配置,包括:
8 K/ y1 Q/ U. {! y) E3 T5 d. L# U  c! _) w2 l$ I, O
使用用户ID的rados_create() 或使用用户名称的rados_create2() (推荐使用此方法).# G: \2 N0 `. ~
cephx认证密钥
# E  b, c% G7 E监视器ID和IP地址4 T& ?! D+ a  l# }
记录级别
8 r5 a7 |& T; a3 T5 D& B( Q7 l调试级别, _7 u+ m- Y! y/ x0 j$ H4 n
因此,从您的应用程序使用群集的第一步是:1)创建应用程序将用于连接到存储群集的群集句柄,然后2)使用该句柄进行连接。要连接到群集,应用程序必须提供监视器地址,用户名和身份验证密钥(默认情况下启用cephx)。
2 _- W8 C2 ^! A3 G' S/ f
8 U+ d  @. h' X' i0 i注意 与不同的Ceph存储集群 - 或与不同用户的同一集群 - 交互需要不同的集群句柄。. M: S! h9 a! n2 s9 f! k$ g5 r
& v% R% s7 N* m5 P6 D7 _6 R
RADOS提供了多种设置所需值的方法。对于监视器和加密密钥设置,一种处理它们的简单方法是确保您的Ceph配置文件包含密钥环文件的密钥环路径和至少一个监视器地址(例如,mon 主机)。例如:- ^, [# e+ D; u8 i( @
( j) _+ c- m9 P) Y! r2 H6 n
[global] 4 k2 ^2 o' C# B" |5 h" g
mon host = 192.168.11.1
0 Q+ m- a( Y* ^0 O% tkeyring = /etc/ceph/ceph.client.admin.keyring! D7 z% K- i5 m0 R' X! ^
6 }/ h" v* z6 E! ^2 `$ U, u% z
0 H1 Y$ @( g2 g1 Q) C) R% D2 a
创建句柄后,可以读取Ceph配置文件以配置句柄。还可以将参数传递给您的应用程序,并使用函数解析它们以解析命令行参数(例如,rados_conf_parse_argv()),或解析Ceph环境变量(例如,rados_conf_parse_env())。某些包装器无法实现便捷方法,因此需要实现这些功能。下图提供了初始连接的高级流程。0 P- u0 A( {& i( a, x) ~, b

$ g. V7 A! P) Y连接后,应用程序可以仅使用群集句柄调用影响整个群集的功能。例如,一旦有了集群句柄,您就可以:
( V" b% v2 v5 j3 T6 _! S" d
( _& T0 @* E0 P1 a. ~获取群集统计信息
1 z% R/ p9 _# }* _2 |5 N; i' _使用池操作(存在,创建,列表,删除)
; w+ y! V. H/ a( D获取并设置配置
9 P. k( Y# l' B0 p5 y  {' |Ceph的一个强大功能是能够绑定到不同的池。每个池可能具有不同数量的放置组,对象副本和复制策略。例如,可以将池设置为“热”池,其将SSD用于常用对象或使用擦除编码的“冷”池。* Q( [, }1 x9 o1 n  r# |" `
Java要求你指定用户ID(admin)或用户名(client.admin),并使用默认的ceph cluster name。Java绑定将基于C ++的错误转换为异常。8 p2 z4 p2 z# U! b; S

4 U9 T; [8 O- i- Timport com.ceph.rados.Rados;
# x$ v# E3 h8 I# f* |8 Eimport com.ceph.rados.RadosException;
% u  [7 j7 k* s
# i2 F  v; U# j& w& K9 Qimport java.io.File;
, G/ g* ~$ S5 j  P
- n/ S5 c4 Q/ ~public class CephClient {
$ K0 @4 M, [- j" R+ p0 B7 B        public static void main (String args[]){3 H* [$ @3 v* \. v3 t. i1 C

+ Z- K! I$ }5 O0 [/ x4 s) Q1 U                try {: y3 T! |. ]2 \$ [% Y
                        Rados cluster = new Rados("admin");4 J2 P( `/ p7 D3 f* U: x5 Q
                        System.out.println("Created cluster handle.");& F& }! `6 i6 n( a' h; |: P/ |# E9 J9 H

% O. V( o4 `' C                        File f = new File("/etc/ceph/ceph.conf");
: C; d" P( _" R2 B                        cluster.confReadFile(f);
. ^9 T) \2 A$ P/ T- @& D                        System.out.println("Read the configuration file.");) n7 G7 {: j3 j$ k
; N# Z- _6 _0 B- y# e! B; H, b
                        cluster.connect();
; a. t. o7 V7 P3 J                        System.out.println("Connected to the cluster.");
8 D8 h! l, o  b) u, C+ U: O! v5 N% G( j! l' a$ T
                } catch (RadosException e) {
- _7 \2 B/ L- e# }. S% t5 A                        System.out.println(e.getMessage() + ": " + e.getReturnValue());. f( [& a- m" t0 b4 ^$ e
                }
0 e+ [* E9 u/ K8 x) ]( o, j        }
6 l. @% s- ?8 F. L( v: H2 T}6 _; j9 s# h1 d

( y2 [5 H( _% h) I$ @9 m& L' x, ]
8 i7 {$ F, B% N6 I" v% K编译源代码; 然后,运行。如果你已经把连接Ceph的JAR文件复制到/usr/share/java并软连接到扩展路径, 就无需设置classpath. 如下运行:
5 M7 m5 e# Q6 U9 s
- F6 O3 n! p' u2 _0 k5 B1 Gjavac CephClient.java
* u2 n3 S! G. W  D, j* {( N$ ~java CephClient
/ F! @( X8 i# w) y5 T4 \! j; ?) y9 a5 H$ o; B. A
  \8 D. Z) {5 U/ y
3. 创建I/O上下文
  |' H( o) r& C+ A8 s一旦应用程序具有集群句柄和与Ceph存储集群的连接,就可以创建I/O上下文并开始读取和写入数据。I/O上下文将连接绑定到特定池。用户必须具有适当的 CAPS权限才能访问指定的池。例如,具有读访问权但不具有写访问权的用户将只能读取数据。I/O上下文功能包括:
) S) ?7 ?- w: z- d4 q+ y
/ t/ m/ P" l; X0 \写/读数据和扩展属性0 [! J- T+ {. o# H+ p4 d
列出并迭代对象和扩展属性$ h, {. b% M  L% X% g
快照池,列表快照等
- [* ?5 v; @. S/ W3 D! gRADOS使应用程序可以同步和异步交互。一旦应用程序具有I/O上下文,读/写操作只需要知道object / xattr名称。封装在librados中的CRUSH算法使用群集映射来识别适当的OSD。OSD守护程序处理复制,如Smart Daemons启用超大规模中所述。所述librados库也映射对象来展示位置组,如在 计算PG的ID。6 ]0 ?9 a/ n' K" ^4 F
/ l4 w9 x, B6 K
以下示例使用默认数据池。但是,也可以使用API​​列出池,确保它们存在,或者创建和删除池。对于写操作,这些示例说明了如何使用同步模式。对于读取操作,这些示例说明了如何使用异步模式。* V* J1 P% m5 r% {. d! P
6 K( ^6 C, l* P4 U+ z
注意 使用此API删除池时请小心。如果删除池,池中的池和所有数据将丢失。
8 @9 C' h( H! r2 ]. ^1
8 w, X! \3 v- n, S( E3.1 写入数据代码
8 S. W1 A' p8 Y1 k) {import com.ceph.rados.Rados;
% x$ z. Q; S8 ^- i) nimport com.ceph.rados.RadosException;/ J9 ?- o/ ^7 v/ Q5 @
! S  u8 ]$ K, z& u# ?- b# u# n
import java.io.File;8 E& X$ W. O) p9 `
import com.ceph.rados.IoCTX;
5 A& [9 J$ _5 ^8 D0 T- L4 F4 p, I- w9 ]5 [0 A% y
public class CephClient {: L3 x* P& j. u; W
        public static void main (String args[]){! f9 [/ _/ C" G2 ^) k# z2 W
% e. K# Z: k& D9 {6 G5 s
                try {' P' d) o" B6 y* Z& t2 {0 h
                        Rados cluster = new Rados("admin");& z  G  t) Z4 t( g' F6 J8 E# o
                        System.out.println("Created cluster handle.");
6 @1 D& E' a; u. E6 N& G6 }% a- ^. h) S                                                //利用配置文件连接ceph
) [7 V: f8 ?: p- K                        File f = new File("/etc/ceph/ceph.conf");- ?# y# q6 T$ l$ J, Z6 B5 H& I
                        cluster.confReadFile(f);% R* V2 O) v8 M
                        System.out.println("Read the configuration file.");
8 ]; C8 `3 _# G, R* W5 s0 t: |# d9 Q! j: G, v+ w' p
                        cluster.connect();& i4 {# l+ [: D
                        System.out.println("Connected to the cluster.");+ B1 o9 i8 r8 `5 M

) i- \6 I$ o+ l  l3 N$ W5 I2 h                        IoCTX io = cluster.ioCtxCreate("data");$ f+ g9 l' G: n! C$ @# M/ @& b

1 n6 @8 j2 }, |# k) K8 L                        String oidone = "hw";
, A* _7 m8 Y- y9 i) ~                        String contentone = "Hello World!";
! d+ ]: }  f$ z' j$ t                        io.write(oidone, contentone);6 [- b5 q2 `/ P- [% ^6 Y
! V2 w1 M- O1 d) h0 e. ?3 W
                        String oidtwo = "bm";
% D. i8 Z1 M  h! g" Q) A                        String contenttwo = "Bonjour tout le monde!";, R' o9 Z7 K$ W
                        io.write(oidtwo, contenttwo);- `  t2 k0 B" ^2 T" i3 i+ C
  E: I0 k2 E1 [2 ]
                        String[] objects = io.listObjects();" F) m" N* b! E* [
                        for (String object: objects)& r4 C+ N' S1 s" d* ]0 R7 x. j& S
                                System.out.println(object);
  }2 E- R  n3 T/ p! \1 J. ~8 f/ K0 K% d7 H. H! ]; {1 L( A
                        io.remove(oidone);+ w" ?' U  l. j+ i& \5 s6 y' v! @
                        io.remove(oidtwo);1 t3 i, c' T1 a. c
% w6 f/ B# A9 T( p9 Q2 f
                        cluster.ioCtxDestroy(io);( R# _8 j0 V* v# n$ I5 z
: D0 b( R/ H4 N
                } catch (RadosException e) {
; R2 n2 Y+ |" f8 I  u- h# R1 W                        System.out.println(e.getMessage() + ": " + e.getReturnValue());
! H3 N- X: K1 Z  V4 i& j                }
/ S' x- m/ L: s        }  Q7 ^4 ]; L! h7 N! n9 w. S, T5 o) V- [
}
' s! E. i6 t# N1 o# a" [. X# {# o0 G: i7 `2 s* K# G" Y
# i  C, d- Y- X* U
3.2 一些基本操作
. u2 z* \. |7 N, x: R4 rpackage com.ceph.rbd;
( @' }- {3 V2 i0 `. |: {
2 \+ k  e+ c( c* P( ~2 Fimport java.io.File;
6 F- T, h: J9 ~" }! Bimport java.util.Arrays;0 Q9 Q1 O! ?% r3 P+ M! W4 z
import java.util.List;" _( x5 y1 S* g+ A. Z! a( c% U  ~

; }7 G3 A2 M7 B  o7 Kimport com.ceph.rados.IoCTX;
( N+ C, f, w0 ?  |1 Kimport com.ceph.rados.Rados;
7 X- U" B. E" n) t& h& Kimport com.ceph.rados.exceptions.RadosException;
" R# ]$ U& F9 Y* u: Qimport com.ceph.rbd.jna.RbdImageInfo;
0 T9 U! @+ U0 o  ~) }! n( O/ ^4 aimport com.ceph.rbd.jna.RbdSnapInfo;4 w! P% s5 D2 T( O
1 u$ V- P) P6 O! U/ H
public class RbdDao {
7 I. q( |+ a! K0 f4 }+ p. I: L- K7 m  N
    private static Rados rados;
* @% W& j) G) \2 d/ Y    private static IoCTX ioctx;
: ^3 _, c- ]! Y3 _( a) \    private static Rbd rbd;" _3 N" y2 f" N/ U
     /**, M2 d$ o  P3 m" s3 g: g- [
      * 连接上ceph环境
4 Y: {3 z" E1 s+ |% ^& D, X      */5 f% v. U  R. N& P+ I; i7 Q
     public static void connectCeph(){
# h* R, z5 W" d) n! I& j( }1 Y           try {1 N, [8 ], I3 S
                           //利用参数连接Ceph
2 c& ~3 T# v3 X1 p. x                rados = new Rados("admin");
3 u5 r  S" Z: J0 `" K+ s9 n& u0 l                rados.confSet("mon_host", "172.16.60.41");+ W" \- e$ Y* X/ \/ k7 e
                rados.confSet("key", "AQCdP9pYGI4jBBAAc96J8/OconCkVKWPBNU2vg==");7 ~) |& L" ~- Y+ i% ^! e
                rados.connect();
; T) y( X) a- k" i! ]* _, ~. L                ioctx = rados.ioCtxCreate("rbd");8 B6 Q  N+ b2 i2 V
                rbd = new Rbd(ioctx);
! j: N9 S+ \; w' Q4 ^                System.out.println("successs connetc");
1 P6 G) w5 C- k6 t% c# U          } catch (Exception e) {
$ ~' T; L* P# O+ j6 i3 R- M              e.printStackTrace();
  p2 k4 R5 d0 K' d4 {8 p7 H1 B. M- e            // TODO: handle exception3 w/ B  g7 O1 X$ g
         }
+ f% t' K( o, d5 \8 @     }
& u1 j; f$ C- _2 Y; u
( w4 n$ Y) U) h0 r* s     /**
' t( p6 c$ ]7 h4 n: s      * 返回所有的image,并展示其详细信息6 S9 b$ U- N2 {5 N0 G: ?
      * @return
" i& U: l" B3 A) R2 F$ C8 {      */
7 L) U/ ^, h8 J! M: Z# F& D     public static List<String> imageList(){5 [* ^# E5 R- ?+ R! ?8 H/ B- `# @
          List<String> imageList=null;( V6 f! }& M% `! k* Y  k" n& a
          try {6 W; {! k' o! B) U
            imageList = Arrays.asList(rbd.list());
0 D% c; J( g, I8 N6 p            for(String s:imageList){
8 B! N9 L" A5 I& r% a+ G- t                showDetailOfImage(s);
5 C0 h8 F+ w& E1 a% J" L% v! Q            }
1 j' u/ {9 X- g, n0 i. }2 j+ E        } catch (RbdException e) {
: F* Q: }6 ^: `8 T            // TODO Auto-generated catch block7 Y! d: `9 X" T1 e; }" j
            e.printStackTrace();
8 D5 R4 _: ^1 r, p) k' I        }% J6 V/ I& }, X% \. j0 i& `8 H8 @
          return imageList;6 E% Q+ f% b5 }" @5 W0 p/ Q2 I3 B
     }4 X* N0 ?) n6 |' z

' A+ ~! K2 ~$ S1 M1 e( ]2 S     /**9 ]6 N, d4 i4 d  g4 H$ n% f
      * 显示image的详细信息
" t1 a! P  P1 X      * @param imageName
+ o5 N4 G& q4 {9 X      */, ^* q9 j6 K2 S, M" r0 K
     public static void showDetailOfImage(String imageName){1 C6 K# y% x) o9 l. }) M
         RbdImage image;9 m  ~$ `3 L9 ~
        try {5 v- F# x6 W" j. k  `3 |2 I' s
              image = rbd.open(imageName);
* J5 ~' @  i) T( x$ t  {( b9 A              RbdImageInfo info = image.stat();; ~( E# V, x& Z8 m
              System.out.println("=================================================================");
$ j. ^- v7 k/ c' x8 k: e$ ]1 q              System.out.println("imageName:    "+imageName);% q9 s5 Q$ o$ e: N* Z. ]; r/ q
              System.out.println("imageSize:    "+info.size);
5 h3 N1 Y! D- Y8 H/ h2 P. `8 l              System.out.println("order:   "+info.order);$ Y' M" J: W9 r' T+ J7 ~/ M
              rbd.close(image);4 J, j# |1 z+ b$ c# d7 w
        } catch (RbdException e) {
. X0 h  a5 m+ I$ y, s            // TODO Auto-generated catch block4 Y0 y8 k7 d5 t2 D. k" {5 ?3 e4 n
            e.printStackTrace();1 E1 Y& P$ I' x# ?
        }/ `3 P/ P' q' J4 J& [2 h+ T
& C/ n) K! s* J3 s: j
     }$ I& w7 H0 q8 H* x  U, H
7 B: Z# _8 J$ A& n! y
     /**7 b- A% v2 K9 |5 ]
      * 以格式1创建image
; f+ Q2 B& C2 U0 O      * @param imageName 名称
: O: X/ c5 n' V/ w. Y      * @param imageSize 大小
0 R5 P! [0 W( u. k0 i  ?3 ~      */
) g6 B# q  H7 b; o7 R9 G  D     public static void createRbd_format1(String imageName, long imageSize){
- A# E6 q! q) m6 X            try {) {1 k5 H, E7 z0 t# b; Z! b/ `$ T+ x
                rbd.create(imageName, imageSize);
5 O" r) C- P* x% h, N2 _" ]                RbdImage image = rbd.open(imageName);6 ^" g# m: Y( B+ k% o( b4 n
                boolean oldFormat = image.isOldFormat();
. v: p; o6 ~3 j" p7 c# G                System.out.println("imageFormat:==========================="+oldFormat);8 x6 C7 L0 Y! R* M$ }1 k- ^6 x
9 [9 r! p, ^2 O
                rbd.close(image);& S& s- H' N# M7 ]1 N
            } catch (RbdException e) {
4 d) x2 _0 F) |                System.out.println(e.getMessage() + ": " + e.getReturnValue());
0 e! J+ N9 w5 k3 |5 N+ b) R8 k* u            }, O# A4 E  G* z5 W! D: O
     }5 C& ^0 ^) p7 O
3 L9 O8 k0 {; R. O4 d$ {% v) T6 ?
     /**, k  G' V  p$ z8 r( l2 Y8 p  N
      * 以格式2创建image,ceph 仅支持克隆 format 2 映像(即用 rbd create –format 2 创建的),而且内核 rbd 模块还不支持。) y& a# W8 W; K7 o, P3 ?8 M
  所以现在你 只能用 QEMU/KVM 或 librbd直接访问克隆品
6 ~. F5 \9 ^: l% r7 y5 G( S/ _      * @param imageName 名称
* O0 M. ?4 l$ s1 v      * @param imageSize 大小! i4 h3 w' X" E+ A$ ^. ~$ D, r. {7 s
      */- v( C" o1 ?* F. I
     public static void createRbd_format2(String imageName, long imageSize){
' z( I& q3 y5 O! n5 E/ p0 j            try {9 z3 X+ _+ j, L! {6 ?2 r2 X
                int features = (1<<0);' N7 X. i  W+ ?4 r6 X% h( D: J% W
                System.out.println("features=============="+features);
! T  P6 E9 a. U9 h% @" P                rbd.create(imageName, imageSize,features, 0);8 m, l: L; L2 W3 {$ N
                RbdImage image = rbd.open(imageName);  @* ^5 t3 T6 b0 S: d+ J
                boolean oldFormat = image.isOldFormat();
3 J. T( O' e7 U                System.out.println("imageFormat:==========================="+oldFormat);               ( l6 z* i1 g/ R5 Z; P1 Z- c2 k
                rbd.close(image);6 F# y1 P# J9 u7 \
                image.flatten();
; Y- f' R  g7 m% v            } catch (RbdException e) {
' D9 y) z, I  @8 [) z) d                System.out.println(e.getMessage() + ": " + e.getReturnValue());
5 \4 `+ g! R4 E: \8 _            }
& B8 }; N0 Z$ L7 v6 a     }
. `, C4 W1 _$ c/ z6 Q8 w( Q, o0 s
. W& |0 [7 I* {     /**
* g  K+ Z- j: Q8 ~( C) L; R: k% x      * 方法创建一个image并对重设置大小为初始化大小的2倍
: E; a/ t* J; w$ o      * @param imageName' B! `" B& `. g2 A; N7 y- _4 ~
      */
9 g4 U( K5 T6 ]0 q: b     public static void resizeImage(String imageName){
2 k; s; x& ?! h4 ]6 R            long initialSize = 10485760;0 b0 y; w" Q6 r, w
            long newSize = initialSize * 2;( K( e2 T- @5 n+ b8 V2 G
            try {& x4 m3 ]: [2 \2 _6 P3 B
                int features = (1<<0);- i  i% P7 c( \% X, q' U$ Q; k
                System.out.println("features=============="+features);
# d, p  d/ m! [- `6 X                rbd.create(imageName, initialSize,features, 0);
# z( y9 V' _# J( q! L$ x$ e                RbdImage image = rbd.open(imageName);9 h$ k5 [8 x- A3 p/ N
                image.resize(newSize);
4 q8 `2 C# z' y% \; e                rbd.close(image);' x8 f6 D6 q& H( W7 C
            } catch (RbdException e) {* D# S4 T( v8 n' F
                System.out.println(e.getMessage() + ": " + e.getReturnValue());1 @: y$ O6 p& I" S' w
            }
9 y( b$ y8 `+ q- f7 L, s7 D     }
9 Y9 i, f/ r: l6 x
9 o7 E, Y( J' [. f8 c+ C. n     /**
2 `- J+ {5 _+ r5 p6 Z! }      * 创建映像的快照" A$ a$ p+ c0 `- y; h
      * @param imageName 映像名称+ A5 N( _4 t9 H$ g
      * @param snapName 快照名称
5 u" w4 a- `( u( ^6 a      */
8 `0 l/ Q3 z; k' a; W     public static void createSnap(String imageName,String snapName){, q  w3 ^, M8 ]/ `# a( C2 |
         try {3 N# u% h7 [: q- K
            RbdImage image = rbd.open(imageName);
: C4 I1 O  L, F* O, H            //创建快照
' ]; u- ]' H. R- r            image.snapCreate(snapName);
( {" `# }4 G# f9 h0 ]            //保护快照可以防止快照被删除
) Q8 N3 P7 L9 d. x* A: h6 Q            image.snapProtect(snapName);
9 c, H# F4 P' ]& [4 l            //返回一个image的所有快照
+ r/ a( \' ^' ^; u( x* Z, \: D4 d            List<RbdSnapInfo> snaps = image.snapList();# F$ m( q, Q5 J) X
            for(RbdSnapInfo rbds:snaps){
$ R- ^6 ~" _3 `/ x" O) q3 S                System.out.println("快照名称:"+rbds.name);
& W8 V! D: O! R1 M& H; F0 y                System.out.println("快照大小:"+rbds.size);- o, C; l3 x' B  P$ @' T
            }
/ Q5 o0 \( k- \& r$ W        } catch (RbdException e) {
0 W+ G) |2 y0 A" n            // TODO Auto-generated catch block! L, G* A( B6 b/ R, ?
            e.printStackTrace();
, d8 S% ^8 P6 h6 ]& V        }* R8 b* Y9 X2 G0 L
     }& @7 C0 k0 W" `0 R

$ J# y; l. V+ M" Q. a2 h     /**# G4 |- F( w/ V, K' L# R" f
      * 通过快照克隆出新的image& `6 Y  l, d6 v# b- D+ |# @8 z
      * @param parentImageName 快照对应的image名称2 }7 X, b4 X$ R
      * @param snapName 快照的名称
  `. T; `8 j4 K* G' |7 F      * @param newImageName 生成的新的image的名称+ f! X! H: r/ E# F
      */
$ i  L7 c0 P. Y' x: c$ Y     public static void copySnapToNewImage(String parentImageName,String snapName,String newImageName){
# ^, a6 _) {0 x" _         int features = (1<<0);
. V- D$ U! \" p; R6 a. w         try {
' F0 p5 ?2 c! s0 I* c4 t            rbd.clone(parentImageName, snapName, ioctx, newImageName, features, 0);
9 z8 Q  _% B0 D' Q        } catch (RbdException e) {
; F6 V3 b- W8 D* q            // TODO Auto-generated catch block/ Z# V! c: G6 ~* f* G
            e.printStackTrace();
. N. n* R' L+ ~" q9 s- ^        }8 }- b/ @. [$ a( [( r
     }; p3 N! v8 Q, l1 ~0 O8 V$ U0 M

; h6 y+ ?9 w, b     /**
" S7 ~/ ~$ r* J( Y  b$ E4 _1 G      * 删除某个image的名叫 snapName的快照,需要注意的是要删除快照,必须保证快照没有copy的子image,否则会删除失败。
/ G; s. u: s4 q, i0 m: Z      * @param imageName  M: F1 J" ~# P- c! e* w2 \/ S) s
      * @param snapName! n" i6 \! Q" W3 \2 P/ K; f
      */" r2 l; K( f. Z, }/ B
     public static void deleteSnap(String imageName,String snapName){
, e+ H% z1 R4 ]/ [8 r& s         try {8 W* o( x. B9 U: Z
            RbdImage image = rbd.open(imageName);
! u. ~7 d0 e! F/ b5 M1 s' m            image.snapUnprotect(snapName);
% Y" H2 }4 S$ u/ Y/ g% x            image.snapRemove(snapName);* T& |, K' W$ c2 ^& X! Z
        } catch (RbdException e) {
# m4 X/ Z* y6 ~0 V            // TODO Auto-generated catch block7 R. @- X9 x- L$ z5 l5 S* r9 |1 {
            e.printStackTrace();
9 Z$ o3 e# S3 j3 Q3 J/ T- k+ N; o        }
( u2 j" U1 t! }/ V' _& y     }
1 l- T! k6 ^, \7 F% Y" c  }
) C4 |2 E5 [7 r$ V1 {/ R3 W$ [) n     /**
  I: ?+ s2 m: M" Y* x. Z3 c      * 删除某一个image0 k0 K& T8 {9 h
      * @param r3 j$ k! k) l3 \
      * @param io2 i/ R8 o  S2 S2 ~6 @
      * @param imageName& }: b- t1 g. r$ ?; Z7 D6 j; e# w
      * @throws RadosException4 w; o# Z. x  ^4 F* a
      * @throws RbdException
5 |( q5 ~3 ]% h# D$ H      */) i0 d5 u& K& G$ P
    public static void cleanupImage(Rados r, IoCTX io, String imageName) {
  C% M( Z1 f* u2 w# j+ u        try {! g( f2 m5 V/ q: F
            if (r != null) {
" D/ ?) V; Q/ k  ]% d, _                if (io != null) {
' Q2 I$ ?; q; |1 B4 v# q                    Rbd rbd = new Rbd(ioctx);
) ~1 ?5 W3 ]* ^0 |8 R                    RbdImage image = rbd.open(imageName);' H/ S. P8 q0 W5 {2 z9 @7 Y7 F
                    rbd.close(image);" d- V0 K  n: X. Q9 Q9 n: V
                    rbd.remove(imageName);
  o! n5 M- l* D, {                }
/ V( {8 u$ ~" y, e+ E( w            }( @0 c6 d5 @) X! |1 q! M. w
        } catch (Exception e) {
9 N+ H) I6 x4 W$ j, F4 w" I            // TODO: handle exception
- ^' P, ~2 b, B1 [% H        }  # ?0 J9 T! `2 A4 F
     }
( Z5 \  v8 L! X
" M7 p9 R# F0 A+ ]  {
' o6 i) X: F. j! {5 T6 C. Q     public static void main(String[] args){2 c' J: S4 f" b9 R/ C4 {; p
         connectCeph();( }" q4 h3 L4 B* M
         //createRbd_format1("mysql-hzb-2",10737418240l);& ^" _4 |. W+ r2 t2 v
        //createRbd_format2("imageformat2",10485760);" D2 `  n# h7 s% M  S! n' z
        //cleanupImage(rados,ioctx,"mysql-hzb");1 r2 o0 V) X, N# s6 p5 ?% Y4 G( N: Y
         //resizeImage("mysql-hzb");
# M1 _* T! m$ f) o! [
7 r: V! ?$ q8 Z' ~, e        // createSnap("imageformat3","imageformat3-snap");
9 z; |7 F7 ~$ @: L        //copySnapToNewImage("imageformat3","imageformat3-snap","imageformat3-copy");
/ h0 f! E# i( @" U         //deleteSnap("imageformat3","imageformat3-snap");
% \. N8 J" F& e5 S5 c4 d' e) e/ K        imageList();- x( l! `( ~5 T# |! r# c. l) O) J
     }; A( c, s+ S1 r, N, ?, T! b. m
}
$ a; {1 K  b; u; M) E
; Y/ \- G9 L" a0 W$ u- r- d$ O
! Q" _8 J% ]0 u4 l6 U& x
4 }0 _5 K- _4 I2 t: w3 B7 ]" _0 q2 A5 {! V
3.3 IoCTX源代码. _8 H  q) n1 f4 g  C5 s
/*- |# r6 j( R' A8 h* X
* RADOS Java - Java bindings for librados
  D( r: P! x+ A) U) S  Y4 D ** v) a  O1 M; p/ i, l
* Copyright (C) 2013 Wido den Hollander <wido@42on.com>+ T' e4 f$ x- y
* Copyright (C) 2014 1&1 - Behar Veliqi <behar.veliqi@1und1.de>
& w: A6 o! ?2 @# M$ N; W3 a *
7 o. e- q# G/ m$ I3 H: M * Licensed under the Apache License, Version 2.0 (the "License");3 X: D; \$ f: [
* you may not use this file except in compliance with4 ]/ B9 j3 D7 K/ z) n- Z' m
* the License. You may obtain a copy of the License at) g& R# f6 j" F' V# F4 l8 h
*
2 W2 H) H: z; z: A *     http://www.apache.org/licenses/LICENSE-2.06 X. _* R# Z# E! I8 I, v$ d8 P
*" E  r' P8 R# n0 l# y7 E$ V
* Unless required by applicable law or agreed to in writing,
* i: _& e" h7 N" Y9 Y * software distributed under the License is distributed on9 K+ Q1 ^0 ~$ R8 q8 v- v
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,' l8 V4 G# V+ C! [% g8 p
* either express or implied. See the License for the specific
) d. a$ k) _/ _! |- Z' B) ]& C) P * language governing permissions and limitations under the License.7 n- o& E: k# |4 y) L7 O; }! h$ U
*/( Z( \' U2 R/ b% N, i
3 T  K5 z( E. ]. G  ~" h8 K
package com.ceph.rados;
! O: R5 r7 m6 D. w+ G. ~& Z$ q2 R% s( U1 B. X- w; `
import static com.ceph.rados.Library.rados;/ X' W5 k# X( P' _. M: ?" F

/ O/ y5 q, U8 Y# R0 ^7 W8 S' k& v- J  _import java.io.Closeable;
' C' u! ?/ P. o" `$ R8 vimport java.io.IOException;1 k. Y# g' E' A6 L$ }: H
import java.util.ArrayList;+ b5 w& Z8 M  Q7 ]) ]' h! n
import java.util.HashMap;) _3 c# ?6 \8 L( K
import java.util.List;
/ K" C! m" R# k6 N% r5 I: @import java.util.Map;
. B4 P3 ^% p1 u) T. yimport java.util.concurrent.Callable;
/ [: `6 H/ X1 e9 X: A: B; z6 U! X* Y, @; y; V$ I# A% e7 t- a9 g& G
import com.ceph.rados.exceptions.RadosException;
0 l7 S( N0 j$ b6 m$ d0 ^2 Yimport com.ceph.rados.jna.RadosObjectInfo;4 j: A) F) R; b8 o& F' Y
import com.ceph.rados.jna.RadosPoolInfo;
! h% y; Q: ?& k9 i+ J! r+ Cimport com.sun.jna.Memory;
' r) E! H7 l. L! }4 }import com.sun.jna.Native;
  \, I$ ^* m6 e# t' n& r" I8 Qimport com.sun.jna.Pointer;' l! ?# J* k8 P& P! _5 ^4 n1 E/ u# `
import com.sun.jna.ptr.IntByReference;
6 ?! e+ y' R. p, Q% S2 ]5 P1 limport com.sun.jna.ptr.LongByReference;- L1 H) e* m+ w4 A& D
import com.sun.jna.ptr.PointerByReference;8 O% y  p% j9 q/ C9 d1 r
! U, [! L. r* ~7 E$ \0 \7 ^" x
public class IoCTX extends RadosBase implements Closeable {
$ P# I& T4 n+ y  ]
! k) \4 N$ C5 C$ |$ L    private static final int EXT_ATTR_MAX_LEN = 4096;
4 o) O/ G) n5 m( f
+ r& F4 W7 a3 _& l+ N: k; ?* O: p0 ~* C    private Pointer ioCtxPtr;
4 m1 A5 `. E* ^) T" S* }) N- k
1 h0 u% R5 |2 p8 y3 d0 _( X1 T$ O( x+ w    /**4 t- H, @8 y; `
     * Create a new IO Context object
3 D, M, j+ A* b4 H     *
6 f( r1 A- |. o( O- ]1 U     * This constructor should never be called, IO Context
: r3 |5 b) B: x6 T' u7 X  y4 r2 |  @     * objects are created by the RADOS class and returned
' q, J' K% R- n; `2 a     * when creating a IO Context there7 ~6 ?- V# t& G4 w
    */) y: y9 e+ T+ H) Z; h! I. A
    public IoCTX(Pointer p) {
2 W' p) G" G  [( w7 K2 w: [        this.ioCtxPtr = p;) L3 N( v& @  L3 \# y; `0 I! F1 `5 a
    }4 Q+ M& X0 I& U$ n: q2 q% t/ B

4 ]1 s! ^. `8 I) N    /**
" x! b  D8 p/ R) T, T     * Return the pointer to the IO Context
! r! t' ~) t8 F! J4 c. A     *
; W5 F' ~3 x; B  D     * This method is used internally and by the RADOS class8 Q0 a/ B9 K, `% R$ ]
     * to destroy a IO Context
" ~5 Y- i+ M+ g' y3 h( i     *7 c" Y* S+ l) N* n1 v: K9 Y
     * @return Pointer
% d' U6 N. S+ A! x* W' _0 T     */2 R. G' J. x+ ~9 T
    public Pointer getPointer() {
9 p* f( \, {8 V        return this.ioCtxPtr.getPointer(0);
$ x2 v8 |/ u$ L& u7 @    }
# d7 }, i" P+ G, X* I$ T3 g* A1 r5 t1 H: n0 W
    /**( t' a3 k3 ~6 N, V
     * Set the namespace for objects within an IO context.
+ O* e& ?2 ?! N1 H& Q# z- ^     *' w0 P( m) P2 J& Z
     * The namespace specification further refines a pool into different domains. The mapping of objects to PGs is also based on this value.
% b  _: o* `7 _- D! e/ I% n8 a     *0 O; }5 i% F3 N! P) u! ^
     * @param namespace The name to use as the namespace, or NULL use the default namespace.0 |1 Y' \4 s" N" z
     */) B3 T$ A* W* U4 S  s
    public void setNamespace(String namespace) {
/ O+ \7 }, U: e* Z, }7 M8 c        rados.rados_ioctx_set_namespace(getPointer(), namespace);! k. r# W' g' U9 A$ e( v2 }/ r3 S
    }9 r. i1 a$ X6 m* t  p

; m. A+ w3 H8 {    /**
5 f! v" G2 [5 X     * Get the pool ID of this context
  @; n6 x- W% M4 {7 g6 w( N     *2 N  U; C) w! b( J8 K
     * @return long- o1 s" S: `2 Z. p* m
     */1 i3 Y* v4 S1 P' {, s# y
    public long getId() {
8 @! [$ c5 v9 B        return rados.rados_ioctx_get_id(this.getPointer());
. J5 ]* i6 h1 [5 n: v    }- _4 a6 B4 b% w3 Q* P1 M
8 _1 A" m: N. M3 q% u7 e
    /**
1 D/ c0 L$ y$ h' s5 {+ M0 s: v7 @     * Set the associated auid owner of the current pool' Q8 |6 }( c0 c# |6 B3 W/ f& O8 J
     *
# j6 J1 f' E( v3 Y1 c2 ^     * @param auid
- h, B4 x9 \7 L$ k" g2 k1 [     *           The new auid( o1 d1 i! U+ z5 p2 ~
     * @throws RadosException& `( o- k  V2 ~! D/ R% O; g
     */& f/ I: K& y9 ?* u7 y/ J# |+ c
    public void setAuid(final long auid) throws RadosException {
, c+ Q, `, O8 Z. G3 t# E* J        handleReturnCode(new Callable<Integer>() {8 V5 o! b" Y  a2 [  W3 I  B* C
            @Override
- j0 u6 a5 e7 _/ r- a$ F+ {7 r            public Integer call() throws Exception {
/ W/ _4 J( v0 H- L                return rados.rados_ioctx_pool_set_auid(getPointer(), auid);* m: ?9 b+ V4 j
            }7 M- M1 {' X3 n1 |  X& w1 K
        }, "Failed to set the auid to %s", auid);! P8 i% N  n- q2 \* G
    }
  X# j* g( m9 [; e* t7 L9 @9 ?/ \. I" S5 S$ @7 N0 w
    /**, _" v. }# T8 [) _4 F7 \* h
     * Get the associated auid owner of the current pool
% _) H' V  y9 S+ ^! v2 m: J& H3 S     *) a; R: s7 U/ t" u( n, E
     * @return long
6 f! v- d3 L. Z: l. a     * @throws RadosException" K8 y6 o  h# ~% W+ w- A8 u1 y/ y
     */- s: j# U' _$ W
    public long getAuid() throws RadosException {
" B# L3 b9 [; s        final LongByReference auid = new LongByReference();  X% D9 \! r1 a% O" B$ n* k7 Q1 R

/ u9 M* N; d8 m! j1 H        handleReturnCode(new Callable<Integer>() {) p" [. o# ~: A1 Z5 e2 {; `
            @Override5 Z& h6 |1 y. R. {* f& q
            public Integer call() throws Exception {4 K1 A# W0 J4 U, G* C% y9 h
                return rados.rados_ioctx_pool_get_auid(getPointer(), auid);+ J* ^. k2 c' C8 F9 l
            }
  K5 k: f6 Q6 d: p* n* [" B        }, "Failed to get the auid");3 P8 |& D- k2 ~7 i% \
. j. \; I# ~0 N- G+ f
        return auid.getValue();
. U. o& V- n% d6 K: P8 |& ]    }
1 w$ s* F- }5 G; S, @( k
% X  Z1 h. [, x' `& S    /**
$ B& Z4 `) o  u     * Get the pool name of the context$ e1 J, U! _- }
     *
  z/ [( N! K) `5 P( s8 C  ^     * @return String
& C5 P( I1 t( _     * @throws RadosException
$ V$ B- O( [. [! V* Q; l; G* n     */6 y' x2 `9 ]% T$ T: X
    public String getPoolName() throws RadosException {
' q& `' c; V( v% [/ d        final byte[] buf = new byte[1024];  P' ^0 O* r! S, u
        handleReturnCode(new Callable<Integer>() {/ h3 w! S, e) _+ N, H1 \& ~) M
            @Override
% _! V; @& g" A9 n            public Integer call() throws Exception {
0 v2 b6 v) V: K6 A                return rados.rados_ioctx_get_pool_name(getPointer(), buf, buf.length);9 `, q/ W' d( R3 C- {. W8 Z
            }
, z. F3 d! B8 ~3 w3 K        }, "Failed to get the pool name");* J$ c6 u. _" E" E
        return Native.toString(buf);
6 h0 p  G0 T0 _( j    }( \" j( u4 p) K) B4 O- a
2 K7 H! |6 ?" S! O, c' B( |2 j; g( _
    /**
1 B% I0 c. g% Q     * Set the locator key: ?/ {% B; G9 o; ~/ c. s( s
     *
7 k' Q, M0 x. L! A  i7 x0 I     * @param key) C# A" E* i7 E/ E5 D1 f
     *          The new locator key or NULL to remove a previous one
# W! ~4 w; w/ q9 J     */6 ~2 ^# n, r4 T# A
    public void locatorSetKey(String key) {- l" K& v8 |4 D
        rados.rados_ioctx_locator_set_key(this.getPointer(), key);1 I2 z9 d' O! i& ]& x0 V
    }7 i8 U& w5 Y! G
; J' a8 b0 m3 j' b$ e( R
    /**; F6 X( G0 h- u# B4 H8 m7 O: |
     * List all objects in a pool
: i* y$ N( h5 w6 F     *
0 }( _4 e( \) j# q. ?     * @return String[]& e: T8 D  G& ~3 l6 e5 g% Z. b
     * @throws RadosException$ e: X% @4 Q, d" c
     */  x6 k+ {; [* }8 c) w
    public String[] listObjects() throws RadosException {0 e2 a% S% J7 G3 w0 p( N
        Pointer entry = new Memory(Pointer.SIZE);
! ^3 I7 }+ ?. u" c, S1 ?5 n, L! q        List<String> objects = new ArrayList<String>();" R* ?" A# b0 L3 `
        final Pointer list = new Memory(Pointer.SIZE);; p7 X" g$ s' ^1 Y+ r0 J

! V( g- Z& C. L( u& P2 v        handleReturnCode(new Callable<Integer>() {7 u% n) i6 A- a: e* u' V
            @Override
6 ]& l  ?) X& c4 F% ~. P/ G* y            public Integer call() throws Exception {3 n# Y% C5 g( R+ V" q9 ?. R! L
                return rados.rados_nobjects_list_open(getPointer(), list);4 ~1 {! L  c/ F; b& [# H
            }
; W2 I3 J1 J6 F2 w' z; d3 @        }, "Failed starting to list all objects");
4 j, K, v2 ^, V. f) s$ _, Q( M, i8 b; h4 L! J
        while (rados.rados_nobjects_list_next(list.getPointer(0), entry, null, null) == 0) {0 k) n  ~) t9 L6 [1 L/ o
            objects.add(entry.getPointer(0).getString(0));3 \3 Y5 b4 ^; [1 t. \# W7 i$ E
        }
, e8 A1 s4 j1 T- d- \0 J
6 e  A7 n* Z' h- y7 E+ S# x( Z        rados.rados_nobjects_list_close(list.getPointer(0));
$ M6 i4 m# V6 ^& ^) t4 c
) Q$ C' q+ ?7 O3 _. U, _; M        return objects.toArray(new String[objects.size()]);
) @# N1 N3 Q* h    }
* K7 [# _4 E, z& G
/ i9 T! z. l: [8 j2 w5 Y    /**
7 m  ?+ _' w0 n8 D+ ~1 w     * List all objects in a pool by piece. Useful if a lot of objects are in the pool and do not6 J3 o* a4 S, S( |* K7 W& d3 |" j
     * fit in memory through listObjects() method. x6 T/ f& s. ~. k
     * @param limit
4 q5 T+ ]9 ^  J7 F' k+ q     * @return a ListCtx from which nextObjects()/nextObjects(skip) and getObjects() could be called
5 Q7 C5 U  d: C$ N; m* p     * @throws RadosException
" _+ Q) Z. g( ~. S$ ?' @     */* m6 ^, A. r3 n% v3 X1 }( R
    public ListCtx listObjectsPartial(int limit) throws RadosException {3 d, k. r4 h' j2 |. h0 y
        Pointer list = new Memory(Pointer.SIZE);
+ }: c% }0 B2 q2 t7 Z7 u( ^( c5 T( t5 `" {, m
        int r = rados.rados_nobjects_list_open(this.getPointer(), list);. A5 z* [; |+ o+ J  |
        if (r < 0) {
2 E1 m% T/ p* P$ K            throw new RadosException("Failed listing all objects", r);) f9 y) k7 `+ S+ J; e
        }
! V) v7 v, ^+ H. W; {: [) w# G2 k        return new ListCtx(limit, list);& C# n2 c& W4 e+ ?' k
    }
, i8 F/ \7 G: S, J+ I7 [
8 @6 G. j  V5 p# |& T    /**
0 c; ^9 }2 A) W4 m% m     * Write to an object
& v- q4 L8 r* p/ s6 G' D$ J     *
) S1 v9 P3 x+ Q' E/ m; B     * @param oid! o) g0 t5 X& J$ @! D: U
     *          The object to write to
1 z' |2 R) I% X1 }& K) G7 ?$ v2 Y     * @param buf" ~# J! J: v! W: w. W. X# P% p
     *          The content to write) |! Y4 {) f* f2 u+ |6 R
     * @param offset
) @! w8 p, B' `/ o$ y! ^) S8 G     *          The offset when writing8 s& C5 M; P- W) j
     * @throws RadosException
1 u- H9 e1 H$ m  ~- ~4 r/ v     */" m- {3 }6 n5 L! R" {, A; K- D' ]
    public void write(final String oid, final byte[] buf, final long offset) throws RadosException, IllegalArgumentException {
; U/ s0 k# f5 X6 v: L" ]        if (offset < 0) {
3 x/ e6 S- F# `* u& B3 N# k5 H8 `( z            throw new IllegalArgumentException("Offset shouldn't be a negative value");
5 b# _& D/ e3 U# W3 [        }
' \/ S+ I- P8 `" f1 H. `        handleReturnCode(new Callable<Integer>() {. }2 s- o% t/ D) b
            @Override
  U  K3 x6 B% F4 _$ x; V7 ]! ~            public Integer call() throws Exception {! _& J, c1 H: D0 f/ [# c! J
                return rados.rados_write(getPointer(), oid, buf, buf.length, offset);
5 V8 N2 O; O( _& C, A/ y) a! H            }6 s. f, a2 N& |7 m
        }, "Failed writing %s bytes with offset %s to %s", buf.length, offset, oid);
  N* U0 w9 P' |  @7 e    }& Z1 y6 L2 s0 m6 K& e

1 O) ~7 r8 f5 `, P0 c- s    /**
" ~& T4 y' ^0 X! `: s     * Write to an object without an offset5 Q  S# h. N, W% M
     *3 h' N" n" a' J$ f- t
     * @param oid# B! V2 j! w2 e; Q% r, f( G
     *          The object to write to
& u6 y3 b/ d$ P) Q" [     * @param buf2 J* F! {4 u7 j9 D( Z- H
     *          The content to write
" x9 ]6 U) E0 f: ]; d     * @throws RadosException; S) z0 D6 A, k4 L9 C& e
     */
; A- x; `+ K  j7 `; k  u# ~    public void write(String oid, byte[] buf) throws RadosException {8 P- z( H5 U0 n) z: k6 ]  J
        this.writeFull(oid, buf, buf.length);& S# N% H9 t% `7 x+ h1 w7 r
    }. q& X- ?1 u6 C0 F( C6 [

# X6 e, j5 G7 F  z  N5 a; ?    /**3 e' k# a& z, p. n4 G# D' G1 q
     * Write an entire object( ^% L% {/ n$ D3 @' e5 Y, L
     * The object is filled with the provided data. If the object exists, it is atomically truncated and then written., f9 X, g( R% _3 B+ C9 ?# M
     *+ |( g. b$ s7 U& S# |" x9 ?
     * @param oid1 O* v) G( z& M, ~  E
     *          The object to write to- s: g5 y) M, H: V
     * @param buf( c$ I: |; a# [- {
     *          The content to write
. H" Z& h/ p# l9 u1 U2 U/ |     * @param len
! f# D' D4 }4 D' B2 T     *          The length of the data to write
; f3 ?  i( Y, I3 v, s- f2 i; q4 r     * @throws RadosException* Y; J7 p9 s! D' c7 M
     */5 x3 W# }. G; g. P( h; M
    public void writeFull(final String oid, final byte[] buf, final int len) throws RadosException {$ R5 n1 t! {0 l7 j* J  d) s! g0 @! r- {
        handleReturnCode(new Callable<Integer>() {
6 A! x" T+ h' K            @Override/ K7 j8 k# I4 _- U, p/ A3 s0 F
            public Integer call() throws Exception {; D! q" R* C( W: Q
                return rados.rados_write_full(getPointer(), oid, buf, len);
0 F6 v+ a+ B0 H6 E/ c- x( ?            }) m  F+ _/ M7 S2 J7 K- s
        }, "Failed to write %s bytes to %s", len, oid);# a3 A' @, ~- R  e: `2 e3 Y; C+ n2 i
    }
7 O4 k9 }; X7 h5 k& s* _$ J' q$ C) W$ ]: i/ x! X
    /**
, A  B, d( ?% e- l: b     * Write to an object without an offset
$ u) _( C( A5 A9 _* h     *
4 t& U: _/ S) B2 a" {) ~     * @param oid& G& q: v' t6 n9 W) ]3 }) I
     *          The object to write to
, l) V' P- v% i6 F     * @param buf
$ e7 [& w2 v4 N. N4 G( k     *          The content to write
: n- e+ R4 V& @* l+ c( q0 V     * @param offset
" n" V' V/ F. q( S# k     *          The offset when writing, b1 d: L6 n( l2 @; |" m) n
     * @throws RadosException2 V; B  G9 A1 t# m7 w& H
     */' {" a9 d1 Z* h8 u2 d+ b
    public void write(String oid, String buf, long offset) throws RadosException {6 }' u0 S( Q# \5 [) E
        this.write(oid, buf.getBytes(), offset);
' X, P/ g& [8 C0 L% d8 Z4 R    }
- m0 I( k7 j5 m8 x+ ~2 U% H- m/ b$ F9 ]/ u9 V
    /**
8 w7 X0 w# Y. H, _+ e     * Write to an object without an offset8 Q, c! b/ Z" {: j8 W0 B* f9 I
     *
$ W( a7 s" B1 h     * @param oid
+ J4 Z& [0 C! h1 r9 _6 ?     *          The object to write to% C/ a2 M4 U2 o2 [. e
     * @param buf
3 y+ F4 W6 d* b6 ]     *          The content to write
: f! w( j! Q( d9 y* K3 T3 ^     * @throws RadosException7 ?( ]; o7 K( R/ i6 r7 [
     */0 L8 G. E9 N' C
    public void write(String oid, String buf) throws RadosException {3 c; s) C' t" ^/ |
        this.write(oid, buf.getBytes());
1 U$ t: A; @% G4 n3 x' J    }
  E  F4 s1 h1 _( Y( r/ Q- j
& y+ M% q  i2 ^3 h. E6 i/ O    /**
6 r5 `# D1 `& [1 y: O5 q/ v     * Asynchronously write to an object
/ ?+ ]1 d  D" q     *0 c& e; M& u. |; j. f: A+ |
     * @param oid
6 P# \1 X8 a8 H8 A3 O     *          The object to write to
; |0 y  }: V# \( C2 h9 [7 ~; T     * @param completion% I# D- f  h1 Q! v/ Q* J1 Y& |
     *          The completion instructions
$ P9 }! X+ j4 W8 W     * @param buf9 _, x4 V* p4 s  h
     *          The content to write$ i" {2 e! p9 ]3 e4 B5 ^
     * @param offset
# }) E) {# }6 }- C4 D     *          The offset when writing* H6 Z$ b. r9 Q5 H; f
     * @throws RadosException' `8 y- v8 }. x- G$ g; b/ t- L
     */
7 ~: [0 g& ?* B: o    public void aioWrite(final String oid, final Completion completion, final byte[] buf, final long offset) throws RadosException, IllegalArgumentException {
' r% }% e; u8 B+ v; G! ~" l        if (offset < 0) {! {) _+ W6 s( [( m  U, {
            throw new IllegalArgumentException("Offset shouldn't be a negative value");8 j6 d( w# Q8 |& q; Y' z
        }
! H  _; X/ @6 u6 \* w! E0 j        handleReturnCode(new Callable<Integer>() {7 p0 d' R: d9 B; ~
            @Override/ s! A# f. @8 k" v
            public Integer call() throws Exception {: m6 D4 \* ?3 c0 O) X
                return rados.rados_aio_write(getPointer(), oid, completion.getPointer(), buf, buf.length, offset);
: G( ], o. b8 e            }
  ?, I( ]8 V( Z& f" K8 A1 P        }, "Failed AIO writing %s bytes with offset %s to %s", buf.length, offset, oid);4 r% D8 i% {" J" L( Q# b, Q1 m5 _/ l
    }
' o; ?+ k/ v( S1 N% o
1 t& t1 _8 o' N) Z4 b    /**1 c' V4 E6 K2 T- O. q0 U( `* D2 i
     * Asynchronously write to an object without an offset; h+ S# i+ A* j; U! }5 @$ X5 h
     *5 {/ v% H9 R- V# z4 k+ T3 K) c1 R3 t
     * @param oid; a$ E) N$ D9 V" Y% E7 l$ `
     *          The object to write to9 x. K+ `' W) U6 X6 J$ q& e
     * @param completion+ J& Y4 K5 S0 j1 t+ D( _
     *          The completion instructions
$ E  ?  o7 W+ H: c     * @param buf
6 T! r0 w8 @0 u3 o, |     *          The content to write
# u3 L! o! n: n' c7 x     * @throws RadosException. ?4 L6 f/ r! x' q/ U
     */
$ W5 s3 Q& F7 g7 i3 B! Q    public void aioWrite(String oid, final Completion completion, byte[] buf) throws RadosException {
9 C6 ?+ g& H# ?' t        this.aioWriteFull(oid, completion, buf, buf.length);
& {5 D: \' k" J% t$ q    }# H2 D3 `0 X1 X/ f# j$ d

0 r6 f8 w! n" m3 f    /**
  w) F$ z' e+ N% ~8 h" m4 E# @0 u; \- ?     * Asynchronously write an entire object- G) r5 t8 P% e1 [) }
     * The object is filled with the provided data. If the object exists, it is atomically truncated and then written.
$ \3 s- _) Y5 l0 t  f2 M     *
: l! ?; `3 s( \: O( i* c; h6 n  }     * @param oid
$ b+ M9 p- ^0 @! b4 a: C     *          The object to write to
+ ~8 e7 }: ?, [# I& r  T5 H     * @param completion
8 Y2 R, i" z$ ~9 [  a$ L     *          The completion instructions
( _' s0 C; b7 W2 \# s     * @param buf
$ @$ T, x1 |! C: D/ A" B* k+ V4 q7 e     *          The content to write0 g4 W3 f4 u" e% e! N
     * @param len' L/ y2 X2 v2 n) U
     *          The length of the data to write
4 O1 l0 m7 Z  S5 T3 P     * @throws RadosException
3 C3 l  ]+ v; i     */' H8 O8 M* R7 J# ?4 E! \
    public void aioWriteFull(final String oid, final Completion completion, final byte[] buf, final int len) throws RadosException {' o& X1 k+ O4 M$ ]/ w9 X
        handleReturnCode(new Callable<Integer>() {
) a7 e1 |! g7 q% H/ A            @Override0 x0 P3 z* @( U1 U; X8 O+ ~
            public Integer call() throws Exception {
/ i+ l8 l. N% G+ t: F                return rados.rados_aio_write_full(getPointer(), oid, completion.getPointer(), buf, len);
  Z$ w7 z8 O& S, a$ Z            }% p% }: E4 b  _+ {4 Q/ }
        }, "Failed to AIO write %s bytes to %s", len, oid);
2 n: f; C+ @  j$ }8 l    }
+ a8 T- m, }" T" r* s7 k3 ~
" u" h  |9 _7 r' }( O    /**5 m  X4 j6 L, e9 e$ Y$ A" J- @% ^
     * Asynchronously write to an object without an offset  |: e+ m. a% F7 [& L; X5 `% U
     *: m& B  A( Y8 X/ J1 Q
     * @param oid5 h5 R; d5 G  u) j0 q
     *          The object to write to
/ G( M7 A( N" Z; R. W/ F     * @param completion
- {; v; A. a) D5 |, J     *          The completion instructions6 h2 S6 R( n) o% }' X
     * @param buf$ M9 M, e% h0 ]. e8 H! p  F$ \
     *          The content to write8 J; f; s4 i+ ?, f
     * @param offset
$ o, m7 L9 u$ O0 J     *          The offset when writing
# y% y) x4 r" w' W5 }     * @throws RadosException5 J  L; ]5 d. {: `
     */
; z% K) e9 i1 M' K, L. u$ C/ f* d    public void aioWrite(String oid, final Completion completion, String buf, long offset) throws RadosException {' l" m) L) v& L# H2 X+ r$ k
        this.aioWrite(oid, completion, buf.getBytes(), offset);/ [* Q3 t1 d$ x7 C" I- J
    }
% i3 l5 c5 S# \) A8 H' Y0 b& z1 r1 i2 ^% U; c0 V7 b( n/ S% ]; ~
    /**6 D: a& F4 m  W- J
     * Asynchronously write to an object without an offset7 j; V" \2 h( H- I3 O, C
     *0 _% D8 ?+ V% u1 u' a# ~# G- T
     * @param oid
7 R2 ^0 r9 X+ R' A     *          The object to write to9 y" H2 y9 Z# c) E5 t
     * @param completion! b# q! Y- Q$ H8 }: D$ [# ~' \
     *          The completion instructions9 O* s& \1 z+ A& V' E8 U5 g+ a
     * @param buf
6 J2 `4 c# F; z4 A1 T3 `1 N     *          The content to write( c8 c6 y5 x2 o3 z9 @1 Q$ V( n1 x
     * @throws RadosException
8 e$ {, v2 h. j5 M" S3 |2 ~1 p     */* i) S' k2 j, O* P2 w
    public void aioWrite(String oid, final Completion completion, String buf) throws RadosException {
5 |$ U. U8 P- z0 C        this.aioWrite(oid, completion, buf.getBytes());' v- g& R* r0 y
    }( s  j+ k0 o; |* G. A' P

' F2 F* a5 j- i  @3 ^3 J  T    /**
5 e  S; v1 N; d  j9 b  Z* g: O     * Block until all pending writes in an io context are safe.
3 D% R7 C2 [  j; s9 G  H" m; D1 Y     *
2 |% E  ^, S: M6 u3 e# p     * 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.! |- h3 b" G) n5 d) q
     * @throws RadosException
( O% w0 Y- W0 O% t9 C( ]     */
. _- u) G- O) s9 Z$ X: a* g    public void aioFlush() throws RadosException {
# R( P' u  `6 d: q9 m% N4 c2 V        handleReturnCode(new Callable<Integer>() {
$ H/ D, t' Z3 e7 ?0 p+ u8 M9 S            @Override! D1 j0 e- s$ Q# X9 z" M# G) o
            public Integer call() throws Exception {
! V  W$ X3 ]2 B/ p+ q                return rados.rados_aio_flush(getPointer());
: c' X, z3 D: ]  ?            }2 H2 p9 G2 O! [: B
        }, "Failed to AIO flush");
5 H1 H  H6 g4 R" R8 A$ J    }
; f7 |; P: a2 y% r5 @4 Y3 N" T' `/ r3 D) W
    /**
; p: b6 w% M  t. \     * Remove an object) o/ v+ ~! h) u& D
     *; O) W9 V" d+ `2 I& Q0 j* M9 Y
     * @param oid
* Y5 i' P8 I( R3 d; K: q, \, p" t     *          The object to remove  v" F# {" B5 c5 [5 Y" j
     * @throws RadosException
: p9 X, C& p! U0 C7 Q9 c" u     */
7 k8 x2 k* K1 e+ e& t5 }    public void remove(final String oid) throws RadosException {
2 _7 I$ ^2 w$ g5 m        handleReturnCode(new Callable<Integer>() {1 s& y' R5 R! q4 z
            @Override. P" @$ C  A: f/ l
            public Integer call() throws Exception {  l9 f; T9 H7 F2 h. K& s# {( @$ w
                return rados.rados_remove(getPointer(), oid);
+ V. n+ v1 Z5 n3 ~/ f            }; d/ q1 O: x3 z$ s
        }, "Failed removing object %s", oid);0 _* N% a0 f  p& s- i- {
    }& A% U9 p- T: _; B

$ h; [1 n4 r3 ]- C. U! }" K    /**
: M. X$ X: t/ F6 t+ |     * Read data from an object
0 e1 T1 H" N# W* H8 W& W5 G: p' x8 J     *
8 J  v4 j, J: d     * @param oid
1 K, z( }  Y& ^8 W5 w! s     *          The object's name9 }( ]) P  p1 Q3 G5 k( x1 G
     * @param length
5 L3 }/ l' e. l" W% B1 ^     *          Amount of bytes to read
+ B: m1 v: N* t7 C; Z- q% Q     * @param offset; m6 q% `9 H8 r: z; D4 A7 [
     *          The offset where to start reading
/ t5 }" ~) B! ?% [# I: G3 k: N1 L     * @param buf
7 S3 k& g; F2 P8 T  ]/ n1 T! V9 r. A     *          The buffer to store the result$ J4 H! M0 L) e2 c" g
     * @return Number of bytes read or negative on error/ b* ~; P0 x- @3 X3 S8 f! z
     * @throws RadosException+ g( M& J/ A& y
     */  c0 m$ `3 a  P6 m& m1 j
    public int read(final String oid, final int length, final long offset, final byte[] buf)
) H* e- z  Z# j! ]# L) q            throws RadosException {
' R" F7 o# t0 ?8 C" e1 J; o        if (length < 0) {2 q+ e4 v' ?: d: Z; g8 N
            throw new IllegalArgumentException("Length shouldn't be a negative value");+ p4 ?; d- O0 |1 t9 T4 X' V/ P
        }
4 E( C; x: i& D& P' d1 k        if (offset < 0) {
+ a. Q/ W/ Y& r- I, `& Z' a            throw new IllegalArgumentException("Offset shouldn't be a negative value");
  M  e0 X  F6 B# m4 e7 J        }
$ Y- O( x1 `9 {  Q9 o
/ X5 P- S3 L# y+ U8 M0 F        return handleReturnCode(new Callable<Integer>() {
+ D' ^$ ^+ C5 ^' p            @Override, Y1 F9 Q9 I( i4 y* p; Y9 Y  v
            public Integer call() throws Exception {/ T( X, ?+ U% m. H' y
                return rados.rados_read(getPointer(), oid, buf, length, offset);8 S! e3 l3 s% Q' b9 H! Y
            }
0 r! i0 N* Q' o( y: X        }, "Failed to read object %s using offset %s and length %s", oid, offset, length);4 e" h! F2 N; c
    }- C1 f$ \5 f3 P/ @/ l9 z" _
) Z4 c4 F3 F/ h7 ]6 a: F
    /**( @( M& P3 a+ H" [( s
     * Resize an object
& M8 i+ P% {$ q' ^9 w1 l) ?     *3 |, S0 Q% P3 o
     * @param oid
+ r9 U9 R# o3 ^- j2 _- k) \     *           The object to resize& x* b% P# @( y0 E7 B' L
     * @param size+ C/ m3 x( U& t# g9 t) N
     *          The new length of the object.  If this enlarges the object,
* ]" G+ V+ {6 y1 B     *          the new area is logically filled with# I8 _: o$ Y6 P8 t
     *          zeroes. If this shrinks the object, the excess data is removed.
6 w/ i6 f0 R/ U& E1 w  H     * @throws RadosException
+ v5 w' {, k9 ]2 i( X% j2 G     */
) }$ \% o& e" s    public void truncate(final String oid, final long size) throws RadosException {# @! F& p+ X  V" U1 U
        if (size < 0) {# U0 R' D$ k; R9 ]3 Y$ R- J/ ?9 S
            throw new IllegalArgumentException("Size shouldn't be a negative value");
! {& m0 }0 t. T3 [0 q0 K        }  A9 T9 z! X# K0 z: N
        handleReturnCode(new Callable<Integer>() {
9 M4 N1 ~) X# B  d4 }" u            @Override
6 I7 C- X5 R! z& s; I: A            public Integer call() throws Exception {
" s# Y1 W5 C/ r0 P                return rados.rados_trunc(getPointer(), oid, size);
& [: ~0 I  G+ h8 n            }* i1 f. l% w. d
        }, "Failed resizing objects %s to %s bytes", oid, size);/ m) [4 K6 W4 |8 G- U2 o. R
    }
$ i! d. k+ G# V) j" a0 F* I& L. x  [( c' i
    /**/ S0 f. e; Z0 k- ^6 ^3 k( C
     * Append data to an object. u; O4 t1 J+ y
     *
" z% K/ w7 a& @! Q" B( X0 h     * @param oid" D8 C1 L, T4 L1 g! }. k1 j
     *           The name to append to( J+ s# l! U% ]1 d% J& I% S
     * @param buf
7 E" v- L- z' ~     *           The data to append
7 N9 J, Y& l6 A     * @throws RadosException
9 @# \+ w) G, A- p/ F     */
* l5 \2 l& R8 ~1 A! [: C    public void append(String oid, byte[] buf) throws RadosException {9 B  E8 h7 ~' {8 T1 \7 r% X2 j
        this.append(oid, buf, buf.length);
+ n( U$ o" q5 k0 c    }
5 F" v. I% Y. w0 d0 P
" J& w) G; R7 j6 j    /*** C) _/ @4 s. Y& _. p
     */ ^" j# o# E8 R% N3 }7 y
     * @param oid; y/ c* q' U& P/ d) s1 J& {* g* ?
     *           The name to append to
* G) Q- s5 A4 x8 C     * @param buf
% U$ H; x5 b$ p  E# q6 S' P     *           The data to append
+ A1 P1 F1 w" f9 Y' C! V     * @param len( Y$ I1 j. \& G
     *           The number of bytes to write from buf3 p9 ^% ]9 ]7 n# n# @/ I# y8 t2 d
     * @throws RadosException! t" C' y3 Y3 e! F& c
     */
0 M# m9 g# d# f2 N    public void append(final String oid, final byte[] buf, final int len) throws RadosException {
5 W; J" j1 B* h! m        handleReturnCode(new Callable<Integer>() {# P4 v0 n7 j* j9 X- E
            @Override
* F9 ~( E9 w6 ]5 }/ G# H            public Integer call() throws Exception {: Y- B2 n% }6 ^2 i$ t
                return rados.rados_append(getPointer(), oid, buf, len);  u% Y+ s+ x7 s' m! X# x
            }
' W; E4 Y8 K( H" G4 A& J) C4 V1 F        }, "Failed appending %s bytes to object %s", len, oid);  L/ e* E8 J1 k  q
    }
7 n+ G7 O; K# y8 i
$ @1 Q0 y  O* b    /**
  q9 a7 Y3 `4 ^" S$ I+ Z     * Append data to an object! g/ V" c: |4 \7 ~( Q+ D+ L, [  k8 t
     *1 E6 B4 V, E$ F& _
     * @param oid
, C. N& O! @0 R1 p7 r1 _     *           The name to append to6 S+ Y, P  I4 Y% y
     * @param buf
$ P% N& d9 b$ a# g8 R+ e     *           The data to append& j5 q( w5 ^0 g* y
     * @throws RadosException
2 [0 E5 @' S5 ]+ h4 _     */4 X" s  ~9 Z6 V9 U  v9 `
    public void append(String oid, String buf) throws RadosException {( H6 [: Y+ G+ D! i8 r% f! S
        this.append(oid, buf.getBytes());! ?/ J/ `, v3 j/ d) a4 A/ y3 T
    }8 a" i" t' p, J
% o6 b% t2 P- {6 E
    /**2 Y9 \: k& b+ D
    * Efficiently copy a portion of one object to another; V4 Z! g, W$ Y8 |5 B
    *( ~+ O0 ]4 \6 N; ?1 ?; v
    * If the underlying filesystem on the OSD supports it, this will be a
) x4 @3 I7 o) S; D- n2 k' |! ~    * copy-on-write clone.0 G  g$ F) x5 n0 t, j$ G
    *
  r$ ^; ~" Q: d3 o    * The src and dest objects must be in the same pg. To ensure this,7 ]- A- t7 c7 w: h6 `* C3 q
    * the io context should have a locator key set (see IoCTX.locatorSetKey()).; `, o( k7 v: u. D" V. y
    *
; |$ d. J, ^6 C2 s6 J# f( R    * @param dst
. u9 ~0 ]; `8 _    *          The destination object* \: ^- N" c; T7 l
    * @param dst_off
# w# A) L$ s( m4 a/ v: E' G/ h    *          The offset at the destination object
# D" ^% u% ^) D    * @param src8 Y& `+ ~  W% g; x  M: n
    *          The source object/ n* p2 q7 L. p& M+ i
    * @param src_off2 h7 F. h3 s0 d( ^: G4 z
    *          The offset at the source object4 o3 D& d4 c6 ~7 m% s
    * @param len
" r: y: W4 `- Q, p" i. K+ b/ `; Q: b    *          The amount of bytes to copy$ i- Q, {1 G0 k* X
    * @throws RadosException
. \+ u8 l7 f4 H- P# u4 d0 k    */
0 B) t" F- v# P+ o* w3 K; H    public void clone(final String dst, final long dst_off, final String src, final long src_off, final long len) throws RadosException {
2 l% g! H( e4 q0 C! n: G, L        handleReturnCode(new Callable<Integer>() {
" ^3 ^/ @: L2 a" S  P- g/ E" [            @Override
3 e& ^. ~: T- u( B6 {; e            public Integer call() throws Exception {( V, G- o6 u. j1 L2 J" c" f) v
                return rados.rados_clone_range(getPointer(), dst, dst_off, src, src_off, len);
( v# {0 n: k9 S9 U4 o3 }1 z            }
: Q5 ]1 d3 j; F" j- Y# z' E        }, "Failed to copy %s bytes from %s to %s", len, src, dst);- H- A% q3 x. e% d
    }* a" K' p; \% P/ u" |
/ ], k6 h, O* ~0 i3 h
    /**- d0 S4 V1 R. }
     * Stat an object" S! `. E8 L" N. Z( l( i' _) O
     *2 D# |* a  u7 C7 H6 _9 y$ D
     * @param oid
  n% \: e; E' t- |* n5 _     *          The name of the object
6 T. j6 y) i; R/ n2 J: p     * @return RadosObjectInfo
5 c7 A4 l0 S8 A" x: g& n: \     *           The size and mtime of the object
- B$ R" e/ N/ Q     * @throws RadosException
1 n; H, F: r  u+ Z3 A0 N% J" T* \     */
2 P: R% e0 p, R/ F. J- j    public RadosObjectInfo stat(final String oid) throws RadosException {9 o/ W3 A0 |' h" c9 F( i
        final LongByReference size = new LongByReference();
6 @' z1 E, q) z( |5 I4 `' m        final LongByReference mtime = new LongByReference();
8 l( D% r2 P3 |+ X        handleReturnCode(new Callable<Integer>() {& l5 H% R0 P( _4 {7 n3 S7 K
            @Override9 x$ I0 c) D/ R9 a5 F2 h
            public Integer call() throws Exception {
: c3 B- w/ ?! |                return rados.rados_stat(getPointer(), oid, size, mtime);
! U8 d0 n2 W! `% m: E9 b7 |$ G            }
8 t; ^0 N% u% f% c% g        }, "Failed performing a stat on object %s", oid);
  {# T6 {- D4 [$ ~: k, l        return new RadosObjectInfo(oid, size.getValue(), mtime.getValue());7 X3 L5 i0 R/ Z, d. H! ?4 h. A" d
    }
* B5 y$ O( E  u( v( E/ i: K. H( y' x4 r% g
    /**7 g  j0 z1 t' w4 W1 c7 \0 M
     * Stat the currently open pool5 g& A( O/ H( I9 X. u; P$ Z. V; o
     *3 @# n. C. O9 O) C/ G; c! [. U; K% O
     * @return RadosPoolInfo2 s" L6 l! B1 z9 f. D" A( H, O
     * @throws RadosException4 V* p! [" a. c: e2 N6 R; Z' Z, g
     */
9 u- d2 P) ?, f' `    public RadosPoolInfo poolStat() throws RadosException {8 T# a. U3 `5 l' y+ l
        final RadosPoolInfo result = new RadosPoolInfo();
: _2 M2 c/ u  t% N& P0 d2 p        handleReturnCode(new Callable<Integer>() {( I+ a$ G: e" S& w
            @Override
0 c- a1 P3 X, D$ n1 n7 ?6 c; U            public Integer call() throws Exception {
- |. s( w7 d7 g# B# T; f& O2 [$ `                return rados.rados_ioctx_pool_stat(getPointer(), result);
4 I1 T0 v' }, |1 y            }  Z8 f+ r6 W& a
        }, "Failed retrieving the pool stats");: V6 Y2 ~, @6 q% }3 n  U& b
        return result;3 \" _  y' B; p/ M) s( F  I- _# c
    }
. s8 V# a. M& D& R' j; \9 i
& ?2 [; {& M2 p% k9 [( \    /**
2 P7 ?; o& c- Y" F' C; T* r     * Create a snapshot
+ e8 w  J) l5 H( W( l4 O3 t# g) _     *1 N  a9 h9 K  s; o+ y& T- t3 _
     * @param snapname
0 d/ c3 I( c( e; j: d% e. T     *           The name of the snapshot+ c. f4 i" [* u# T2 n6 @- n2 i5 |
     * @throws RadosException
; ~6 b* }' ]1 E4 w     */
) v' O# [+ Z/ v& U2 M7 v    public void snapCreate(final String snapname) throws RadosException {; X" _) S$ m; z  a) x! s
        handleReturnCode(new Callable<Integer>() {
% m6 q! K  ^; t+ E$ Z            @Override
" K# [8 M1 n1 T+ Q! ?- X( o1 R            public Integer call() throws Exception {
' T5 \, R, R# F. ~                return rados.rados_ioctx_snap_create(getPointer(), snapname);) P  O. w7 x' B( c$ ?! Z7 Y, i
            }
) A6 M+ j9 t- c" k* D2 _        }, "Failed to create snapshot %s", snapname);
7 w- \# v. Y2 o- H  X0 ^/ H    }
* p1 d. E/ h) k5 r# u3 ]
$ s- |0 e4 X, h' C/ l( G    /**
2 R5 o& m) e9 q8 [0 E0 x     * Remove a snapshot4 t9 H5 ^/ Q5 N/ g, H2 ?- a. L4 Y+ r
     *( v$ p$ a7 w$ Q1 N; R( U9 W
     * @param snapname
* b2 T/ z) T  E5 e, }7 K     *           The name of the snapshot9 g! k- ]3 o4 f
     * @throws RadosException
9 Z, B! U% e% s8 T& E; p1 B     */& k2 r1 L) l' V7 o5 h0 K$ M' [
    public void snapRemove(final String snapname) throws RadosException {2 o1 N1 l7 d" Z; x% v
        handleReturnCode(new Callable<Integer>() {
; c- V$ P0 S& D) M% {            @Override5 W' G! Y9 K( d% U
            public Integer call() throws Exception {: {* W! h, k$ x  m: P
                return rados.rados_ioctx_snap_remove(getPointer(), snapname);
7 t0 @  Z! A" J0 B0 O            }& q4 F; N% Y! q- j! Y" `* r
        }, "Failed to remove snapshot %s", snapname);# j- D# e& `7 l4 h2 Z* ~
    }
6 u: Q0 K+ I  X! T
5 I- q: a/ S+ d# ~& \    /**
4 c4 X' ]/ [3 x$ K; n  ]7 D     * Get the ID of a snapshot
( L/ Q' P0 V/ @) L/ ]) ?! Z3 D  M     *
0 x2 C  o, F( r' w* w     * @param snapname
0 {* Y8 {+ |* L) W. s     *            The name of the snapshot
: Q0 B2 h- Q7 l     * @return long
" {. u# K! _; T7 J: b4 U4 U$ x     * @throws RadosException
2 b$ _7 E, x( ~$ i, i0 P7 x- i     */' T; d* o) }4 I0 z, G
    public long snapLookup(final String snapname) throws RadosException {' b7 d. Z; ]& w
        final LongByReference id = new LongByReference();
2 |" R4 e& R: d0 s        handleReturnCode(new Callable<Integer>() {$ R( t8 C& x! b- j) G, W; Z
            @Override+ y) j% C% ]5 v% ~. M4 V
            public Integer call() throws Exception {
( _1 O' s9 C; W& V  ^6 _0 u                return rados.rados_ioctx_snap_lookup(getPointer(), snapname, id);& h$ m1 `  I# p0 }7 c
            }* b; }/ F  E; X* Z) d3 R4 \* t
        }, "Failed to lookup the ID of snapshot %s", snapname);
: W. u" v$ I" q# B' g* F  h        return id.getValue();9 }, J0 P7 [8 m3 K7 \& [( R
    }
+ A9 R+ ]7 t  ^+ Y1 W* S7 P) @; {  C  H& i' R( m. x& R) s
    /**" |2 l) B( L; w
     * Get the name of a snapshot by it's ID. @1 p' _( Y9 f, P$ {
     *6 `3 ^% g6 N0 R6 C
     * @param id
; i' U' \' I6 [- s  d6 H& C     *          The ID of the snapshot" w* C: h  E, d8 V; |
     * @return String
' r5 D: W& f0 x/ ~- ?! w$ o1 ]     * @throws RadosException
% U& r' b! H6 m     */
' U6 {7 W& g0 k' P' X- p    public String snapGetName(final long id) throws RadosException {
+ D& S1 c, j2 R  N0 J        final byte[] buf = new byte[512];  ]8 _  x* V# V4 _5 X' X
        handleReturnCode(new Callable<Integer>() {
- ]& r  C% D- X            @Override
+ X/ O/ q; B" e! ~$ q' c, }            public Integer call() throws Exception {
, D7 N4 ^0 f, c                return rados.rados_ioctx_snap_get_name(getPointer(), id, buf, buf.length);
' _8 t4 P/ Z, }& q8 l. r# w            }6 u' w1 l. \1 E2 W# x3 I6 M  j" s
        }, "Failed to lookup the name of snapshot %s", id);
1 Q0 _/ A" ?# e; C2 _; y9 D  S        return new String(buf).trim();
* ~2 u3 o% K! w/ {% e( j    }% c  ~/ g0 c! M9 Q% U3 c8 J; S3 C
( Q, {/ p! R( c
    /**
) d* r( O: Z$ g# P5 R     * Get the timestamp of a snapshot
+ ~8 ~9 d: }0 ~7 F; h     *
( Q+ R, o3 H+ ^1 U     * @param id6 ?: W  F7 K4 G" X+ p9 Y/ O; X
     *         The ID of the snapshot
8 H# m7 d6 f9 V, |0 S" P     * @return long0 O0 M( n% U, x4 c5 _
     * @throws RadosException
# X# O  C* Z( p9 J6 W0 ^     */$ ]& T. ^. D6 ]1 f) Q% o9 q
    public long snapGetStamp(final long id) throws RadosException {
4 V0 o' A1 ?# C9 n# K        final LongByReference time = new LongByReference();! P# |. y5 `5 U, c0 [
        handleReturnCode(new Callable<Integer>() {
$ Y$ p& B5 L! D- q) W+ ]            @Override7 G* u6 X9 P' Q) p9 E
            public Integer call() throws Exception {7 k( I$ E( P3 S( L9 w% i7 c
                return rados.rados_ioctx_snap_get_stamp(getPointer(), id, time);& _; x1 h4 N* Z9 N7 T) O* k  D3 o
            }  Y' _& a4 y, @) B; t" O# v
        }, "Failed to retrieve the timestamp of snapshot %s", id);
1 V: _  m1 A7 ~: C: [& ~# O        return time.getValue();
" a+ d+ L" H. z6 `* K( O% ^6 o8 f    }
$ h$ b8 i2 V  G. }; X, H! F+ B
# {, d7 w1 @  B& c- {3 B% y; H3 f    /**
! d% h6 d5 b. p; i$ O. _     * List all snapshots1 R4 L7 |8 D( G' U% F8 P4 Z8 k6 v
     *
" _+ b# ^# w" K9 ^* y# I  U     * @return Long[]& R/ x% k6 A9 r8 n6 n  x
     * @throws RadosException
$ r' p% d! b* a( z9 E$ j     */. }! Y+ d0 z$ i& B( U8 P- D
    public Long[] snapList() throws RadosException {
0 E$ H' q% d! _* \- z, v% P, I        final byte[] buf = new byte[512];
. F" c, W- S/ I7 V0 }2 l: s
+ R* k# H& L2 p5 t  t        final Integer result = handleReturnCode(new Callable<Integer>() {
2 D' x1 F$ ]  j! d$ o5 K            @Override- l' h! v% Y, d7 Q! r
            public Integer call() throws Exception {2 q. Y1 W! e3 p2 ~6 Z) @
                return rados.rados_ioctx_snap_list(getPointer(), buf, buf.length);. d$ D; h4 D8 d4 Q/ u5 V
            }
; S: \5 R! ~" D3 `( q        }, "Failed to list all snapshots");# w( `3 T. y( X1 I$ e

( D: W+ u9 T3 l- g        Long[] snaps = new Long[result];
7 g: ~; h5 `! K# ]+ c        for (int i = 0; i < result; i++) {; m2 I3 n0 u& ?  d
            snaps = (long) buf;
- C7 a  k( r$ n1 n$ `4 ?" f9 a. ?        }+ y6 K/ X" e1 [
        return snaps;
4 ?5 H+ D: E4 v0 Q# X    }
. O1 j2 e, _" l( W$ ~& Z6 m9 X6 ]8 N6 o' `/ S  P
    public ReadOp readOpCreate() {5 |* `. R: x7 j, e  L
        return new ReadOp(getPointer(), rados.rados_create_read_op());( [# X! I3 H2 i- e$ I8 m7 Y
    }/ z- g- z  j( L# V$ E  S
" H# j1 A7 o3 {
    /**2 @: H/ K) i0 {& B
     * Instead of releasing the read operation directly, better use ReadOp.close
3 q+ u2 s9 u/ z& I. ]     */, `& o2 M1 V. H1 [3 ^  M
    @Deprecated
% ?: F/ H/ E# @4 h2 H    public void readOpRelease(ReadOp read_op) {
0 ^1 |9 P; N( h2 H& M- g& J        rados.rados_release_read_op(read_op.getPointer());. G) A( A( _& L0 H/ W! p/ Y
    }! R( s& n2 H# }" ~: u
8 A9 ^6 |* R! \! `
" q1 |* L1 B0 `3 K1 O- o
    /**/ ~0 w' G* y0 V3 H* ^$ z
     * Get the value of an extended attribute on an object.4 X- l# s( n1 T; t  P2 Z: [6 c
     *8 ~" w$ q) x: t% C0 i3 Z1 ?/ X
     * @param oid/ M, v" g$ p8 s; K4 z# e
     *          The name of the object
  U4 ~8 b' L: I! [8 V     * @param xattrName
' N' G4 ?, ]6 f# w& m     *          The name of the extended attribute2 w1 v& t& |6 z) L. ~' y0 f
     * @return- n, W1 l/ q( j1 w' C' [4 r
     *      The value of the extended attribute, G$ u5 O9 o7 U
     * @throws RadosException9 [9 j6 Q  A' Y. U& C7 o
     *      on failure -- common error codes:' j2 C" L  G4 X  q
     *      -34 (ERANGE)  : value exceeds buffer
$ E% D8 D) @1 t& O     *      -61 (ENODATA) : no such attribute, }4 e7 w8 [  q3 w  G0 O, S
     */
( h+ V3 p4 U! _% _    public String getExtendedAttribute(final String oid, final String xattrName) throws RadosException {) c8 x7 g( Z: x' `7 I
        final byte[] buf = new byte[EXT_ATTR_MAX_LEN];0 F# s  a9 C8 P* l$ n1 l- v
        handleReturnCode(new Callable<Integer>() {# b2 Q9 |# h: W4 N& ]
            @Override
% @: V! ~% `0 @            public Integer call() throws Exception {
" |1 y; h. s# I                return rados.rados_getxattr(getPointer(), oid, xattrName, buf, buf.length);6 h4 J  a0 p. a3 h& k
            }
' S0 e, B, ?1 v1 P% x' T& X/ o+ E# B        }, "Failed to get extended attribute %s on %s", xattrName, oid);* z4 x4 K# D& \/ v$ i( ^# A5 A
        // else...
( y+ s1 ]" z6 S0 {. s: y        return  Native.toString(buf);$ z- d( Z7 m2 R/ T% {
    }
' n8 B- ~$ L, A$ z: I# X; o
# C7 R2 G0 V* J4 j, f, D    /**: d8 s- ]1 k# V) |6 u
     * Set an extended attribute on an object.& `9 u) G! q+ Q& w  M7 ~! H4 J
     *4 {+ T. T; S+ R2 v
     * @param oid+ z# M1 H1 l5 {; g
     *          The name of the object
" s/ O! Z; t7 P     * @param xattrName" Q6 i, A3 J/ G  m
     *          The name of the extended attribute
2 g2 r. y- }; `. d     * @param val
  }: j3 [; ~5 r0 m7 ^2 i+ B     *      The value of the extended attribute9 Q& o4 @4 q, c: \* n0 C1 I
     * @throws IllegalArgumentException: K  n. D$ d$ a
     *      attribute value is too long, x2 x4 O3 R  Z
     * @throws RadosException+ V' H  {9 C- m. P
     *      on failure4 q# x$ S/ m/ Q8 I) B
     */+ t+ g- [1 a/ {! x5 S
    public void setExtendedAttribute(final String oid, final String xattrName, String val) throws IllegalArgumentException, RadosException {
6 _( k* ?* m: m0 `& T9 l; v        final byte[] buf = Native.toByteArray(val);' W: l# @9 o; J) Q
        if (buf.length > EXT_ATTR_MAX_LEN) {
+ `1 K! U7 ?, t9 Z& v( s7 |            throw new IllegalArgumentException( "Length of attribute value must not exceed " + EXT_ATTR_MAX_LEN);5 x' Q* i9 S- b* q/ F5 w0 A
        }
' c! g1 {; n2 e% ?3 X! K* c1 v        // else...5 A* j: y* {. a* v9 u( ~4 m
        handleReturnCode(new Callable<Integer>() {- [. U6 t  T* y4 @6 H" c  b
            @Override) ^, u1 k* u7 g) U- O! r
            public Integer call() throws Exception {3 Z+ k. D% V' k4 v5 Q
                return rados.rados_setxattr(getPointer(), oid, xattrName, buf, buf.length);* t" t% N6 p# A3 h
            }+ f9 @1 h- A2 b1 t. @( X' ?
        }, "Failed to set extended attribute %s on %s", xattrName, oid);0 s" ~- G+ W: v1 P& s+ j/ p
    }! J" z! e* U6 Z9 T. K
. P1 O0 C/ z$ ^$ h- x
    /**5 g. @" ~/ M6 `! A
     * Delete an extended attribute from an object.
: b- b, a3 b$ H$ u     *
( I( i5 E8 N$ @8 J! ^. R: o  V     * @param oid8 J! W" l6 m  u! [, p; Z; N0 i
     *          The name of the object
* y/ f# F" O2 ^4 j. j     * @param xattrName8 c# V! c$ a; T
     *          The name of the extended attribute# j. V3 k3 {7 q; e3 ~2 @
     * @throws RadosException
7 n1 u* }- L3 f     *      on failure5 P6 d7 J8 h- i
     */: J, [( }3 j( ?" j. E5 c# k; Y- }* R' t3 N
    public void removeExtendedAttribute(final String oid, final String xattrName) throws RadosException {
0 p3 {$ u% O3 Z        handleReturnCode(new Callable<Integer>() {
8 h6 D( m! O* D6 S' Q. e            @Override' G( w3 h. A( l8 _$ `% L' V
            public Integer call() throws Exception {
9 h8 g3 u) L# J1 W# k+ _8 ]8 Z' ?5 @  G& g                return rados.rados_rmxattr(getPointer(), oid, xattrName);
3 O& y: Q9 r" i/ k5 n2 @) s            }
+ o, |4 v& Q+ {9 u( M9 ]. h8 L$ l4 g        }, "Failed to remove extended attribute %s from %s", xattrName, oid);
" y+ e+ J# x" O: c, J5 H3 }: I   }
7 r8 v% C+ [# B% l* U9 n7 F8 X+ m- s' c  C
   /**
& L# E" c7 V6 x+ U% u% |0 \) I     * Get all extended attributes on an object.8 J3 j& V# T+ K- X
     *
. f: a- Q! {2 J     * @param oid: V" l. B2 S; d+ I' `0 C& z
     *          The name of the object, }% g: S+ V7 y5 ^# v, M! e3 f
     * @return
3 Z; r& R% h0 V     *      The map of the extended attributes% @" }) p0 T; X7 R
     * @throws RadosException# M% {: z4 d+ ?9 m$ a% u( r
     *      on failure
+ T6 h7 \( T- |' f* D     */
2 T' B- z* X0 ]; `    public Map<String, String> getExtendedAttributes(final String oid) throws RadosException {
2 i8 C1 }3 o- ^" O4 D3 Z        Map<String, String> attr_map = new HashMap<>();
; W- L) i' _' s; `! I$ E        final Pointer iterator = new Memory(Pointer.SIZE);
" \) {% W5 N) q& i1 A& ^        final PointerByReference attr_name = new PointerByReference();, O' g6 e* p- i+ M/ B2 b' r
        final PointerByReference attr_value = new PointerByReference();
4 s* x0 ^( \: a" a& M$ ?        final IntByReference attr_value_len = new IntByReference();! X& x5 s4 K# A7 o; R$ b/ z% i

9 k" N! w# r' o# M9 H        handleReturnCode(new Callable<Integer>() {  {  \/ @) i8 m& L
            @Override
0 s6 K# f, a( O! o; `9 Q7 s9 D            public Integer call() throws Exception {
) }  p0 L5 ^- d% c) `  c  k: {. D6 ^" |                return rados.rados_getxattrs(getPointer(), oid, iterator);5 O# `: O) V+ G' {
            }5 K) J/ D( J4 ~$ j
        }, "Failed starting to list all extended attributes");# u' f$ O1 i% g' e4 @( N

, a  ~0 N! B5 j9 |0 [  H        while (rados.rados_getxattrs_next(iterator.getPointer(0), attr_name, attr_value, attr_value_len) == 0
0 S3 e, C# ~2 h/ |; \  K/ K                && attr_value_len.getValue() > 0) {. x, n+ w5 s( K2 E
            int length = attr_value_len.getValue();& s% T  U' Y) H, c0 v0 Q6 ^, l- p
            String name = (attr_name.getValue() == null ? null : new String(attr_name.getValue().getString(0)));
0 Y8 Y1 C0 c2 [# n% v/ U; T            String value = (attr_value.getValue() == null ? null : new String(attr_value.getValue().getString(0)));6 b" z1 G$ d/ t1 o* v2 X
            if (length > 0 && name != null && value != null) {
* l8 f) h% C) R5 Q( @                attr_map.put(name, value);* k0 N, W- K5 a8 O. c& f
            }
) i, F: I4 ~# N  x0 B  E# Q        }% q9 u6 e' a2 m' l. ]
# O/ N' k% @- T, {$ Y; G3 @
        rados.rados_getxattrs_end(iterator.getPointer(0));# Y9 B/ Z1 |% u: h. W- @

8 A2 W! p  r" p: s        return attr_map;7 [: D$ I0 n6 J4 Y1 G6 Z$ V3 F
    }- n/ r; }  O8 U( t

" y3 i3 P2 `  ~    @Override
! U3 [4 _* T0 M9 |    public void close() throws IOException {5 _7 v0 ~3 I$ K4 m) @
        rados.rados_ioctx_destroy(getPointer());
4 z4 \! ]# E4 T* F/ m" I; O. j    }" `- U0 x. P  l
}
- ]# V4 |1 s; G' E9 ~, u0 J! a9 m" t' a2 M8 A

& w: R# S) D: h6 W' L: J# n至此,大家应该对Java访问Ceph有了彻底的认识了8 o4 }0 e) }( Q- O

1 t# O( o- M. c2 A- Y' `# A. X4 r& @- s7 d4 ?& a& A* g
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-11 23:05 , Processed in 0.022945 second(s), 23 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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