|
|
1. 部署LIBRADOS环境% G+ V& O9 O/ P* a- Z9 A$ \; N
客户端应用程序需要librados才能连接到Ceph存储集群。
( v5 F$ u" s, W k8 k* U1 `0 F4 \ X4 Y5 Y. p
1.1 安装jna.jar
+ K! Z, p" {0 M5 _9 d- _Debian/Ubuntu环境下执行以下命令! r( c% l; U: o7 d6 D* \! C$ z( @
% C) z. G( H8 v; V$ ?% m$ Jsudo apt-get install libjna-java5 S4 r1 A9 r( D, q* Y
7 N2 l- c( v. a4 W" W/ ~" R5 X
9 g K" k) {* [6 X. I/ Y( a ~CentOS/RHEL环境下执行以下命令
7 m$ ~, C6 I/ m t& O; C
7 \2 Q. A5 @: l, u y @( [# Gsudo yum install jna
1 z9 {. T8 g- G9 I# P1 Y: U% \4 I6 g; U/ ~* c. C- _
JAR文件位于/usr/share/java.
1 [, S% n! F2 B1 Q' |) P
" O) V: p) r" n8 c, T' Y1.2 克隆rados-java代码库# D0 | D& O* `$ z
git clone --recursive https://github.com/ceph/rados-java.git
/ e2 x% e: I2 [2 t s5 g6 {: V! r7 q7 k8 ?/ ?+ {" \
1.3 编译rados-java代码:
, o4 p1 A V& ^cd rados-java0 z- r* G" ?* D% D& L
ant
}/ M) u( P' I: A$ d8 C# |: m2 d3 ~6 I R4 _! i6 Z
9 B5 f+ ]9 t9 {7 X0 _% g |7 \
JAR文件位于rados-java/target目录下
& n7 s+ V8 @) i" h0 T1 v( l
- K5 a0 S1 {8 G* H+ [1.4 关联路径
9 x2 k1 c1 C7 o% h# C# K复制该JAR文件到公共目录 (例如 /usr/share/java) ,并且确认该文件和JNA JAR在你的JVM’s classpath目录中. 举个例子,你可以按照以下的方法来关联路径:
# i; g6 b+ p+ I9 k: c: Y) p# v* @9 [0 B
sudo cp target/rados-0.1.3.jar /usr/share/java/rados-0.1.3.jar6 j' y6 ^8 F, S1 W! ]
sudo ln -s /usr/share/java/jna-3.2.7.jar /usr/lib/jvm/default-java/jre/lib/ext/jna-3.2.7.jar# e2 U7 {: N) Y6 f
sudo ln -s /usr/share/java/rados-0.1.3.jar /usr/lib/jvm/default-java/jre/lib/ext/rados-0.1.3.jar
2 v+ y7 I5 l! t( i" {9 M
) B4 {, g# Z, z! S" q$ A, o0 D: l2 U2 J
编译文档可执行以下的命令:) P8 ]) h4 |/ e. H* G
! f( Y* w# n$ e' \% z2 o" z! {ant docs, d g5 R: v& K) o
8 I: ~7 H8 \5 K, R4 Q" Z
2. 配置群集句柄: h! k1 ^9 d. c# c
一个Ceph的客户端通过librados,直接与交互的OSD来存储和检索数据。要与OSD交互,客户端应用程序必须调用 librados 并连接到Ceph Monitor。连接后,librados从Ceph Monitor中检索 Cluster Map。当客户端应用程序想要读取或写入数据时,它会创建I/O上下文并绑定到池。该池具有关联的规则集,该规则集定义了如何将数据放入存储群集中。通过I/O上下文,客户端向librados提供对象名称,它获取对象名称和集群映射(即集群的拓扑)并计算用于定位数据的放置组和OSD。然后客户端应用程序可以读取或写入数据。客户端应用程序无需直接了解群集的拓扑。9 A4 M" {. P7 w' t& K
: K* n- \+ n, `/ t' qCeph存储集群句柄封装了客户端配置,包括:, Z# j+ [8 P& M" _6 B3 B0 h6 h& {
0 O5 W$ M @. _2 O4 l9 n) Z使用用户ID的rados_create() 或使用用户名称的rados_create2() (推荐使用此方法).
" B6 u! X, I5 i& z( }- M# m% Dcephx认证密钥
5 ]9 m, F E& ], E& C. Y9 b监视器ID和IP地址" x/ c0 G2 e$ L
记录级别9 `- K: R! Y* D; s# o# _
调试级别
4 L P( m. h1 G' E% G2 R因此,从您的应用程序使用群集的第一步是:1)创建应用程序将用于连接到存储群集的群集句柄,然后2)使用该句柄进行连接。要连接到群集,应用程序必须提供监视器地址,用户名和身份验证密钥(默认情况下启用cephx)。% e' ]: D5 v5 Q7 }
- a' w2 a- R2 m8 p& }1 t: ~
注意 与不同的Ceph存储集群 - 或与不同用户的同一集群 - 交互需要不同的集群句柄。) v% n+ o. @" e- F
$ g6 ~$ x4 L; P, }& I9 e( j4 Q
RADOS提供了多种设置所需值的方法。对于监视器和加密密钥设置,一种处理它们的简单方法是确保您的Ceph配置文件包含密钥环文件的密钥环路径和至少一个监视器地址(例如,mon 主机)。例如:: c+ Q5 s8 T! t$ U4 ]3 ^! P1 r
% H$ B2 q( F( A5 Z2 [3 ^[global] % F5 w" m7 a8 W% s, h) x, i$ N1 \
mon host = 192.168.11.1 5 o: r A6 g. \6 s
keyring = /etc/ceph/ceph.client.admin.keyring6 b& i1 @0 \1 C
& k$ z3 k- w* c. o8 f. L) N2 p7 I$ T
, W" g# M$ a5 o2 k* q
创建句柄后,可以读取Ceph配置文件以配置句柄。还可以将参数传递给您的应用程序,并使用函数解析它们以解析命令行参数(例如,rados_conf_parse_argv()),或解析Ceph环境变量(例如,rados_conf_parse_env())。某些包装器无法实现便捷方法,因此需要实现这些功能。下图提供了初始连接的高级流程。6 p+ h; M& U+ B! ~
; B) ^. r/ I# M3 v8 i, m连接后,应用程序可以仅使用群集句柄调用影响整个群集的功能。例如,一旦有了集群句柄,您就可以:" d* F% k# g o/ j
+ W# C5 c+ s( L! t- i* o. P& \
获取群集统计信息! K& k. z* ^! b3 z1 a0 z! x" P
使用池操作(存在,创建,列表,删除)
- [3 _6 ?# W3 T获取并设置配置
7 o* r. @' }+ ]Ceph的一个强大功能是能够绑定到不同的池。每个池可能具有不同数量的放置组,对象副本和复制策略。例如,可以将池设置为“热”池,其将SSD用于常用对象或使用擦除编码的“冷”池。
9 k. |$ L g9 |+ I3 b( Y' |Java要求你指定用户ID(admin)或用户名(client.admin),并使用默认的ceph cluster name。Java绑定将基于C ++的错误转换为异常。
* P/ Y- p$ N2 q& e2 x: M; U
- u& @& b- z- E( L4 ?6 Z5 [7 D3 {import com.ceph.rados.Rados;% a( u. a% h. X. E4 a. O
import com.ceph.rados.RadosException;
+ Q! S8 B; v# P. a5 |+ }% j
3 a7 t9 K1 k- u/ Y/ c1 y5 T# m2 Uimport java.io.File;; c3 D8 `* u7 D: O- {
# ]1 c8 z2 [6 x) t! J$ fpublic class CephClient {5 a) S0 Z6 [- z" x" k; K! t" I
public static void main (String args[]){
9 A; [! C, G; r2 j
2 c0 b! J5 D0 m try {: B/ L6 i9 c3 a
Rados cluster = new Rados("admin");
3 Z2 p% o: k0 ` System.out.println("Created cluster handle.");
5 K- p+ ~( ^6 }2 t2 P/ A) D
: r8 T$ M" S+ J3 F# J8 v3 P6 | File f = new File("/etc/ceph/ceph.conf");7 K3 \, w3 s6 E8 {% Q9 [! F: G$ e
cluster.confReadFile(f);
& p. D; F, }% M+ d4 B' p System.out.println("Read the configuration file.");
, _' ^4 u3 a7 e$ K4 K& c
$ o# A `7 j' q- T2 N0 q! h5 C cluster.connect();
8 D6 t* Y! k" T System.out.println("Connected to the cluster.");
0 k9 m$ E" R8 t) h! u" c' ^' Q; m! R2 n/ f/ G! ^% I
} catch (RadosException e) {
; _- d! ^, p, ~# j; U System.out.println(e.getMessage() + ": " + e.getReturnValue());
% ^# V: J8 y- M9 {2 L5 U" v }
6 t; P1 p" K: m( D }6 d9 b3 o- Q; ]# Y% y& M+ K2 g5 J+ N
}
: ^" c: c% ]& ]( E% ~% }, S( w, S8 D! H( O- [
% b+ F$ B+ l4 }. Y5 h编译源代码; 然后,运行。如果你已经把连接Ceph的JAR文件复制到/usr/share/java并软连接到扩展路径, 就无需设置classpath. 如下运行:( J: y/ j* P) O4 P, K( ?) A$ g
4 g- }( j `8 m: u& Gjavac CephClient.java
- g8 E- R/ C( |% Q4 ?8 {java CephClient; L" h& b: ^% O* z
! z! }$ N8 A. G1 [' \& ]
3 v g; k- \- }' Q2 V$ h; k
3. 创建I/O上下文* v4 ?% ~8 K( G K# p
一旦应用程序具有集群句柄和与Ceph存储集群的连接,就可以创建I/O上下文并开始读取和写入数据。I/O上下文将连接绑定到特定池。用户必须具有适当的 CAPS权限才能访问指定的池。例如,具有读访问权但不具有写访问权的用户将只能读取数据。I/O上下文功能包括:
# l9 A% n$ o( q O( O8 T) A* k* _( g2 }" D4 w5 B( z* v# t
写/读数据和扩展属性" ^) `5 U& { `( @' E
列出并迭代对象和扩展属性* c8 c/ g( {1 p l" D
快照池,列表快照等! F! ?8 A% M( L
RADOS使应用程序可以同步和异步交互。一旦应用程序具有I/O上下文,读/写操作只需要知道object / xattr名称。封装在librados中的CRUSH算法使用群集映射来识别适当的OSD。OSD守护程序处理复制,如Smart Daemons启用超大规模中所述。所述librados库也映射对象来展示位置组,如在 计算PG的ID。
' Y. s G1 }% }, k% u+ U* ~: W
9 ?6 X; e" W7 W+ T0 H以下示例使用默认数据池。但是,也可以使用API列出池,确保它们存在,或者创建和删除池。对于写操作,这些示例说明了如何使用同步模式。对于读取操作,这些示例说明了如何使用异步模式。, k# t6 `0 l( S( ]
[3 f6 A# a; n; t
注意 使用此API删除池时请小心。如果删除池,池中的池和所有数据将丢失。
- y3 a$ |* x# l2 x8 W9 V3 e2 X16 z8 o3 B0 V5 G$ b& @
3.1 写入数据代码* c/ R: o: x: l% x: M
import com.ceph.rados.Rados;7 g3 w, ?# a0 h4 S8 t( m/ s+ R
import com.ceph.rados.RadosException;
& Z9 g( p: b$ |# n3 H# A$ H, \2 N
$ p( i) R/ M& ~7 F# Jimport java.io.File;
. X: y. w0 F o4 H g& ]0 pimport com.ceph.rados.IoCTX;
9 l& X) u2 {$ q: W1 c$ O- k2 l* O( i" _: X
public class CephClient {
, W i, Q& e8 ^ public static void main (String args[]){1 ?" d4 X* _( x# |
* t+ r6 z8 u' }2 v7 K/ H, V try {, n( t0 C, e% k" Z6 v6 E& a
Rados cluster = new Rados("admin");, q( v+ e3 u5 G' u' F+ o0 v
System.out.println("Created cluster handle.");' W& \, G2 F- P6 o$ h7 r/ @- M' Y3 c
//利用配置文件连接ceph* }7 W1 k7 p: H" n- ^1 n
File f = new File("/etc/ceph/ceph.conf");% ~$ B8 z& a3 l" @
cluster.confReadFile(f);
8 ~0 z, w, e, w9 ?5 x, w( o System.out.println("Read the configuration file.");
% z) n$ G, e; P8 c, t* n& k0 k
+ P8 L* G8 G4 g z0 \3 N3 O# U cluster.connect();
7 H E) y6 A ]# d3 e System.out.println("Connected to the cluster.");
( j. q9 {& z: X2 b) {( T1 ^ X. K# }1 x4 G5 m
IoCTX io = cluster.ioCtxCreate("data");
- {& k+ j- R- c9 R" G( s
, s8 ^1 I1 y8 s7 ~; A. s' `/ _ String oidone = "hw";
' h8 w- x4 Z1 e% k$ s1 | String contentone = "Hello World!";
3 V4 `. x% k3 g+ ` io.write(oidone, contentone);
& ^) ~ Z* b) M5 L+ {8 o8 s0 ?5 S1 b5 ?* q6 u% _. A
String oidtwo = "bm";0 B5 ^! }! W+ q2 Y$ |- A* F% r$ i/ o
String contenttwo = "Bonjour tout le monde!";0 t# f* G: z4 C" N# R- B
io.write(oidtwo, contenttwo);
9 @$ [' V3 y+ V* U$ b% |5 y, r, L6 l3 G# _0 f
String[] objects = io.listObjects();
' X5 @* x1 [8 ` for (String object: objects)
& a6 w7 C: M; E; t8 Q3 M4 {, n System.out.println(object);
% a) u9 B- v% v' x9 x* k7 L$ `! h# C5 \: C6 I% y: i
io.remove(oidone);
- z; ?/ _+ l) f \ io.remove(oidtwo);
0 x: Y# N! y8 C# Q( k, d; I/ l
' L1 } P% P0 `* l" w cluster.ioCtxDestroy(io);
" B6 k$ z+ H& }* k$ ~9 R5 s% K9 B |0 b
} catch (RadosException e) {
% D( N1 S1 Y B/ R$ Z- q System.out.println(e.getMessage() + ": " + e.getReturnValue());
/ m1 M) M$ J" l3 n, M }- z# t+ A& H5 F3 K8 o
}
) X2 ~% B2 Z# D9 H8 `+ ~4 {# j/ N}' G9 `2 H" Q0 U1 P. c# G% y3 S. G
6 m& Z/ d! h+ A- L$ _
; H$ B3 b& T* W( G
3.2 一些基本操作
" h/ Q! D7 B3 D0 x" B3 Rpackage com.ceph.rbd;8 s* t; f( z6 N4 \% X5 e
) I- N/ J8 h9 \) A+ V3 l" O! ]! P8 eimport java.io.File;* k3 n0 q7 ^' s! {$ a0 b5 s7 U9 N7 u
import java.util.Arrays;" H1 _# v+ \. R# f4 o, J0 G
import java.util.List;
3 L6 `% I* G# g* N. l2 g
+ [# b" E- r- Q. g% H& C7 |! q9 Dimport com.ceph.rados.IoCTX;
$ K) O) R1 f- _% @- h3 G) y _# \import com.ceph.rados.Rados;
+ d' X: w% m2 S1 vimport com.ceph.rados.exceptions.RadosException;
3 \1 j+ n" G" V1 W! O( ^5 U& ?import com.ceph.rbd.jna.RbdImageInfo;
; V( s; `4 v9 v% R/ R0 gimport com.ceph.rbd.jna.RbdSnapInfo;
8 I& q: W& q* s/ p9 o2 w9 c0 l+ y7 {3 ^4 e% B0 u
public class RbdDao {% Y; v: F& E$ x7 e+ G
" L* c) x' C6 H2 R" H C
private static Rados rados; u, u4 Q- u* E5 H4 R
private static IoCTX ioctx;# e) M% {8 z8 H9 l" e! s1 r0 f) b
private static Rbd rbd;9 E/ ~# i! f; `8 t
/**
6 d+ J/ w+ l/ _7 _ * 连接上ceph环境 j5 ~1 P# v& ?8 S* Y7 B
*/3 [, i2 R; j7 W' c+ |& |
public static void connectCeph(){% E7 {6 V4 S, @$ C
try {
5 d2 c9 a8 C! s //利用参数连接Ceph, k/ L8 O* n$ n p9 Z0 [
rados = new Rados("admin");
$ M5 y1 k' _; B( d rados.confSet("mon_host", "172.16.60.41");
; K8 g' i# e' w+ ?" M# k1 D. e rados.confSet("key", "AQCdP9pYGI4jBBAAc96J8/OconCkVKWPBNU2vg==");
3 w( B* ^: z' j0 S( q rados.connect(); P. h# l9 Q" ]8 j7 p
ioctx = rados.ioCtxCreate("rbd");
" V! D* g( x7 y E. e rbd = new Rbd(ioctx); q' s5 h9 ^: G" z7 i, [) N( z
System.out.println("successs connetc");3 k( {( I$ ?7 j( K5 _: p7 T
} catch (Exception e) {
4 k% W, b' L" q# H5 h$ `% u T3 } e.printStackTrace();3 N( o4 p) Z9 x2 J7 J2 N5 E3 b
// TODO: handle exception
' r5 v' z4 J4 [- @ } z3 T8 g0 L* @# j; M' J+ R) K
}
# G1 e7 M7 t, @* l# N' O. ~
2 z1 c3 m+ r$ {6 T+ }, e, x /**% F( i( j+ H9 k/ C3 h
* 返回所有的image,并展示其详细信息& n" L& n) k) J( U0 J% q
* @return
- g: J* K. _* [- ~8 |: m6 A */
. m7 _- t( m* M public static List<String> imageList(){( q m' Q1 ?) i; g
List<String> imageList=null;, y2 ^$ `: ?8 q3 g. ]) Q, d- i
try {+ a' G) F2 R% G* p8 g
imageList = Arrays.asList(rbd.list());
3 D3 f, p; r4 m0 b for(String s:imageList){
. s5 |+ F! w) [' M# X4 C showDetailOfImage(s);: Q* O G8 Y4 I6 |2 T) {
}
. p, ?! T% g2 [$ d/ l( n k8 k3 j } catch (RbdException e) {
9 W i: S2 C/ m# Q- T5 e- S // TODO Auto-generated catch block: { D9 b7 @% V, [* u
e.printStackTrace();$ W! u( Y, ~- q5 a
}
0 J. u2 S$ e0 Q1 w* C return imageList;
! w& a \8 x' F/ M/ L5 f& D# p4 m& W' _ }
) a( z8 \8 h/ o4 U: g! F) p
/ _1 q. S. h8 s3 D* D /**
6 \& M0 L/ V) \" E; u * 显示image的详细信息
7 D1 B' x. Y, B) G( M * @param imageName5 u5 T) X" e8 k
*/
$ Z* D3 z+ ]* x2 L" K% ~" }7 f public static void showDetailOfImage(String imageName){( C( C% X' M% V& M* ~
RbdImage image;3 B! A$ m t# u, a( \9 g
try {
# i( `* t2 \/ n9 ~% W image = rbd.open(imageName);
( n* W! I0 l( c/ v) V RbdImageInfo info = image.stat();
, \9 i; f4 ^. b4 R, p System.out.println("=================================================================");
" z" Q7 \% j9 ~6 o' j. i+ K+ L System.out.println("imageName: "+imageName);
' _! h( O0 t( ~4 y( t( ~ System.out.println("imageSize: "+info.size); j+ i }7 d) q+ @& ?/ T! _4 ]1 B
System.out.println("order: "+info.order);
3 k, H# X* l& j0 k. N rbd.close(image);
1 }3 U+ h' j2 a4 X7 h( w# \5 p } catch (RbdException e) {* U) \! i4 q9 B8 l' g. X$ ]0 v
// TODO Auto-generated catch block
# O" o4 K0 W7 M9 ^: q e.printStackTrace();
0 ?, X* i2 c* C. J5 _5 y# u }
% D9 L* ]+ {. ^2 s7 ]2 E
$ b4 |: B% H$ N9 r6 b }7 k6 N' D* N% q, Y2 o7 W
: ]. {' U9 i3 G0 |: Y. ^6 z5 F
/**
7 c. i+ J( ]& ^ * 以格式1创建image/ w7 S a" M7 ~' m P
* @param imageName 名称1 p1 t6 I$ a, F5 _% A& h+ Q
* @param imageSize 大小
9 J6 H" _# A6 D6 L3 N */
/ @, |+ f1 F1 E6 y0 _! ~( q public static void createRbd_format1(String imageName, long imageSize){- N% }4 i7 a. a! V* W0 g
try {
7 I9 e/ T9 W. I rbd.create(imageName, imageSize);! u1 Q( U9 F3 x8 ~
RbdImage image = rbd.open(imageName);1 X. ]" ?5 v3 t# J+ U/ K3 @
boolean oldFormat = image.isOldFormat();7 U, W9 W0 |2 C
System.out.println("imageFormat:==========================="+oldFormat);6 @' \5 Q5 P6 ]9 w0 T
' q+ U5 r* u+ J0 M3 U rbd.close(image);/ W2 f" k) g6 E3 b
} catch (RbdException e) {/ T Z% [; m0 U' o% G
System.out.println(e.getMessage() + ": " + e.getReturnValue());# ?' `- G b% @ c x) b0 A
}
5 O. F1 A7 q' J7 q7 q+ X }; E- i2 c4 y0 Q! b9 `( z$ @' j
5 F: p7 K! T) Q9 _$ g$ W2 q /**7 j+ M* E6 g) z
* 以格式2创建image,ceph 仅支持克隆 format 2 映像(即用 rbd create –format 2 创建的),而且内核 rbd 模块还不支持。
$ N: f% i1 a+ N- s 所以现在你 只能用 QEMU/KVM 或 librbd直接访问克隆品
& n( h) f1 E& Z+ [ * @param imageName 名称
( ^4 S+ ?* i& n' M' l5 @ * @param imageSize 大小( r+ X5 B0 }. F( w
*/; ~) [, `8 e7 J+ c( @
public static void createRbd_format2(String imageName, long imageSize){+ z8 _3 U+ C O& m
try {
! X5 V- c- x' a6 J9 u7 e: v9 M. [ int features = (1<<0);
6 m2 t3 H3 L+ ~- T; ~8 H! h' P System.out.println("features=============="+features);: F( I. ]3 D, j# Q! [! |( x
rbd.create(imageName, imageSize,features, 0);) R, p- O3 L2 t1 \9 a2 p. N; o
RbdImage image = rbd.open(imageName);
4 z0 M+ e$ P3 M2 Q" t+ e boolean oldFormat = image.isOldFormat();
1 X) D) z* z% F! Q System.out.println("imageFormat:==========================="+oldFormat); 5 {* w- `) Y3 W/ ^+ z# b
rbd.close(image);8 K+ h) s5 x* c) _, m6 b
image.flatten();
- o) c) v- [$ V; o( o* O } catch (RbdException e) {
* R8 j7 W% d- w! W R6 P System.out.println(e.getMessage() + ": " + e.getReturnValue());6 T2 a; h: _8 P+ o
}) s" Y, J$ R, C" `
}
" K# m5 u9 u" {) Z( W* x% b
6 m2 ?/ m# P- y6 W2 U6 ` /**! B2 L/ z- m0 L# v
* 方法创建一个image并对重设置大小为初始化大小的2倍
( v/ X7 \9 ?' c4 F8 |8 g * @param imageName4 \! E) z. t% j9 `1 v& r
*/
7 I3 b6 m( y+ a; D/ j public static void resizeImage(String imageName){8 `1 }$ Z. L; }% }4 H9 |
long initialSize = 10485760;
8 U. K: T) [9 I+ r H long newSize = initialSize * 2;
+ z7 y2 A9 x6 @- B. k6 l6 @ try {$ S1 [# q) m3 \- Z! M) J( V) f
int features = (1<<0);7 q' i5 V! \9 x, v3 `. c
System.out.println("features=============="+features);
/ a2 l4 n8 H" `) x rbd.create(imageName, initialSize,features, 0);
& U. Y, P d$ ?: |! h$ P RbdImage image = rbd.open(imageName);
3 b5 L& a9 Q* z& u image.resize(newSize);8 y# q. ^/ U7 ~" I9 g7 b; J
rbd.close(image);
+ g& q; E$ A6 q+ S1 | } catch (RbdException e) {5 ]3 B" T3 E, k. H4 B( R% }
System.out.println(e.getMessage() + ": " + e.getReturnValue());5 S) r$ S4 N# E- o! D, M0 K
}
& b/ N- I: C( q }( H6 ~' w9 S0 i2 ?% ]
^( J C8 J$ m# T6 y# k /** ]9 d3 {7 C7 A
* 创建映像的快照
+ [, u6 a7 T- V: }5 v- U! c4 t * @param imageName 映像名称
; l5 ^+ ~! v+ P& m& h1 J * @param snapName 快照名称& \6 |+ I, ^' Y+ {
*/# I8 i- `3 W) l: s7 e$ l
public static void createSnap(String imageName,String snapName){; Y) ]" y) F' P# m4 l
try {
* i* G2 B) z9 Q7 P" R% o, r% _+ n5 M& O RbdImage image = rbd.open(imageName);
) V. ^4 l5 p( m6 c" x //创建快照
% [, c W/ H7 c image.snapCreate(snapName);
& V4 r9 s' c) P; E& a ] //保护快照可以防止快照被删除
# A" @, I& R: V; K0 d7 m' h9 c image.snapProtect(snapName);7 R/ ^# ^& p& c$ D P- G& j& w
//返回一个image的所有快照9 i2 f% v$ f; b( M
List<RbdSnapInfo> snaps = image.snapList();. Q& {* l9 x+ L1 m1 U* u9 \+ J
for(RbdSnapInfo rbds:snaps){
+ O* m5 q& o4 }- G! ] System.out.println("快照名称:"+rbds.name);( J) p4 S! K+ Z3 d
System.out.println("快照大小:"+rbds.size);
% c* n x& V( ^2 m8 n6 I: }3 y }
- T8 N. F" Y; w } catch (RbdException e) {
; L( z7 [1 F2 r8 d, L9 m // TODO Auto-generated catch block
$ d! t0 k6 h. V1 n9 }. m% q e.printStackTrace();, Y M" ~. r+ P( u# H
}
- [$ _- `( l) @0 W }( e, F o4 j3 G
$ d0 |( I1 C" d _
/**5 u- v3 f( e1 R4 o1 ]- R
* 通过快照克隆出新的image( p& U2 y: n& L* |' k
* @param parentImageName 快照对应的image名称1 |% c) B! f+ z) f) v& a, {
* @param snapName 快照的名称- {: Y7 G4 i- u
* @param newImageName 生成的新的image的名称
# ~2 J: g& e% L/ p */4 M: N& P8 l! ?* `3 i8 j
public static void copySnapToNewImage(String parentImageName,String snapName,String newImageName){/ y6 K) c7 f8 _; W2 y- e8 A% o/ H
int features = (1<<0);
8 N. p8 v$ u. q) }. y try {
0 V# }0 |3 p7 X& @6 @ rbd.clone(parentImageName, snapName, ioctx, newImageName, features, 0);. ]( I. j% V) d& Q4 P
} catch (RbdException e) {
3 B0 A1 L6 a+ n. w, m) S/ Y( _- \ // TODO Auto-generated catch block$ f }4 F* L8 W* A! h% n
e.printStackTrace();4 O! u }3 w+ v, w6 k( f6 m+ [; K
}
3 t6 N d2 n7 x; _2 p }' e4 Z7 p8 B( i4 R
/ K, |# Q- [2 z4 L /**, q: v+ T: J; P# n0 `: c. G
* 删除某个image的名叫 snapName的快照,需要注意的是要删除快照,必须保证快照没有copy的子image,否则会删除失败。
: U: f8 v: e9 c% v% s * @param imageName
, i; T' |" J! m5 l+ T9 a6 y * @param snapName! ^! K; N. H3 u
*/- c A3 U3 a8 m9 H1 A
public static void deleteSnap(String imageName,String snapName){; ]7 y" W, q' {* o6 p+ }
try {; M! ^9 a, k0 I7 o- `
RbdImage image = rbd.open(imageName);$ P7 y4 k6 {5 B0 G# p: u3 R2 E
image.snapUnprotect(snapName);4 }0 O) F5 s" w8 z; P! T
image.snapRemove(snapName);
7 X1 X3 j+ a- X) x* i* V } catch (RbdException e) {
9 b- _% v6 h! b! _# n: J& n // TODO Auto-generated catch block5 p {# U4 K+ A, X P
e.printStackTrace();
' j( t5 Z* w" }6 a }
; j: C0 g$ z W6 v$ _ }: ~+ a5 L& |' s, G1 N
! ^- g" z- B9 q" d) d
/**
1 m# u! D& r8 \8 u; D5 b' t% G * 删除某一个image. z! `/ h" B$ B6 E. c
* @param r `9 f0 c7 w' x- G! t9 y
* @param io. h5 h I9 d% r1 T6 C0 i
* @param imageName5 l( K* x" p2 @2 Q* _6 m
* @throws RadosException
8 Q& B4 F* D7 K# j! f9 w- u* ` * @throws RbdException2 j0 p+ Y$ H+ r/ T) a a' @2 O$ A
*/
- H5 z% a. @* g$ m8 E public static void cleanupImage(Rados r, IoCTX io, String imageName) {; \& C+ z4 R8 J/ h3 g1 g
try {2 m+ H1 S8 Z% t+ q8 c& k7 J
if (r != null) {
{+ A3 g G( ~& B if (io != null) {
: \' @# m1 Y7 o8 _; Q" e) t Rbd rbd = new Rbd(ioctx);( c; N& G: P2 c6 ^6 g8 r+ s% v
RbdImage image = rbd.open(imageName);: o; u1 q2 M0 [9 b2 L7 x1 s
rbd.close(image);) ]( j: ^9 ?$ Y& j R, ~6 P
rbd.remove(imageName);
" x( Z# u4 U e; }% y- \* L }
4 O6 j' g1 f* d5 r2 m }3 r/ x8 \- k- s$ j- B/ ^ [
} catch (Exception e) {
7 v: [+ N5 W- @+ j" o) ]2 E7 [ // TODO: handle exception
% V% O, n; a( ^: B }
' G1 [# |0 Z5 h- g& f. ~5 I }/ o" d3 n, _& F* n0 |0 k9 P+ ]
, l9 d# s3 Z- [+ V& ^; P9 k$ p# R# F
public static void main(String[] args){
& S: k5 a: r* v* i3 M, T8 `2 r connectCeph();4 _* k/ o7 H( J6 q
//createRbd_format1("mysql-hzb-2",10737418240l);
; p' h) H8 J/ h1 O2 R) I' j //createRbd_format2("imageformat2",10485760);" G! V% F9 v3 B5 j& o8 M- J
//cleanupImage(rados,ioctx,"mysql-hzb");
0 `- V* n6 K8 i# y% n //resizeImage("mysql-hzb");- u+ E% ~* ~, ?% d( S# B0 c8 L$ b+ T
- g# V7 }5 s7 H8 n+ j, c/ \& u // createSnap("imageformat3","imageformat3-snap"); f6 {4 L( }5 v& j3 ~
//copySnapToNewImage("imageformat3","imageformat3-snap","imageformat3-copy");1 d1 y8 P, r) K8 {& c. r; ?8 Q3 b0 |
//deleteSnap("imageformat3","imageformat3-snap");
+ b) m2 {. t2 x! z# ] imageList();
. o m+ J: g" X6 |# q }( R3 [5 h ^( m9 V
}
@4 W8 a9 Q- n& l
% M5 u' M" e9 Y
5 s4 c! }- Z# a3 ]7 J2 I& v
. d. K/ s0 _% K7 x) k4 [9 F: H3 l; @, \) n1 {, y
3.3 IoCTX源代码( u" `5 B) S) n* z6 ^
/*
# C! ?' Q! ]: m ]9 _ * RADOS Java - Java bindings for librados
. l6 G. R- R; T. ^ *
6 x5 l3 r6 }" x * Copyright (C) 2013 Wido den Hollander <wido@42on.com>' }4 n9 k* U) w/ I% M/ q
* Copyright (C) 2014 1&1 - Behar Veliqi <behar.veliqi@1und1.de>: K* Z% o( o, f5 H$ |
*
6 n3 V: `4 e' J7 ?' X8 V6 D * Licensed under the Apache License, Version 2.0 (the "License");
P# V5 q; K$ p C1 D# D$ T2 D7 A * you may not use this file except in compliance with
7 c# m( r9 Y$ f" E3 q4 W& v * the License. You may obtain a copy of the License at6 p) z$ M4 q4 V& k+ }0 p
*) e! C* N6 _# |# A) _- v. d
* http://www.apache.org/licenses/LICENSE-2.0! N5 j Y; D% ?! t2 b5 P/ w7 l" o
*
1 t, g% E/ k& [7 G) b" n * Unless required by applicable law or agreed to in writing,
% o) f" V' j+ e+ V6 G * software distributed under the License is distributed on
! a0 v' r4 T/ J: T0 [5 R$ ~+ L0 L * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
' @. P5 Q+ J% S5 \$ i, I8 {- ? * either express or implied. See the License for the specific
/ h$ T" |9 m5 N5 r1 p( s' U9 F * language governing permissions and limitations under the License.
, ?' S' }0 h! ~2 n4 U$ y: J */' l( F6 s6 N; t8 \$ r
6 A& \( s# d. M- Kpackage com.ceph.rados;
, }2 p. N- b: l$ o, v) d( s
# E8 B% P: }, f6 D" B9 m7 oimport static com.ceph.rados.Library.rados;
' }3 g5 w. H+ q$ c1 f6 @, @' X5 O0 c* \* k( t& L
import java.io.Closeable;. Q$ t) A3 i. o- M# ]- {6 d* d
import java.io.IOException;9 M. o* H. [+ a4 R) Y0 T; A
import java.util.ArrayList;6 J! {8 j# w0 G1 _( N+ m1 i4 T; C% {
import java.util.HashMap;
; V( e0 M3 V! o7 z2 \5 Himport java.util.List;' s8 g. C+ v& R4 k" j
import java.util.Map;$ f7 ~8 | e6 Y; H' M
import java.util.concurrent.Callable;
7 ~- ?3 ~9 `; [+ {% [
: ~0 ?) ~- |) ^5 Y8 _0 e+ j. }import com.ceph.rados.exceptions.RadosException;( k' v* c4 h) U& y$ N# i) |. L" ^5 i
import com.ceph.rados.jna.RadosObjectInfo; L* H9 c5 X8 d `
import com.ceph.rados.jna.RadosPoolInfo;
5 N& c3 `) Y% M( Mimport com.sun.jna.Memory;! T. d6 U, i# S1 M- X2 y5 F3 |
import com.sun.jna.Native; v" a6 L3 i) @+ _$ s& a* d5 w1 n" Y6 X
import com.sun.jna.Pointer;
0 |2 U' _; b3 z. T) W5 @" Simport com.sun.jna.ptr.IntByReference;
# R6 Y: A$ g( N) ], [+ eimport com.sun.jna.ptr.LongByReference;: T4 E n& h$ P* g
import com.sun.jna.ptr.PointerByReference;
% O; J6 D. a7 u) `( J. m
% x# d$ m; C- t1 Gpublic class IoCTX extends RadosBase implements Closeable {8 U5 X+ A* [- D$ B
% r# }$ l; C, H- s7 L- F; P/ A
private static final int EXT_ATTR_MAX_LEN = 4096;- H5 P. s' a2 D. J
, R; Z9 z5 _' X9 l, E0 y! V private Pointer ioCtxPtr;
; z2 }( k0 ~9 L( E7 i3 y/ D! y0 b0 O+ z+ j( J7 O; k& j
/**
% W" s! d0 Z- z * Create a new IO Context object0 S7 G) P1 \7 p. K" ]+ @% ^ H
*
! `, P& r" s, Q! i: t, _ * This constructor should never be called, IO Context( w0 \ [: ^" a
* objects are created by the RADOS class and returned
5 @4 h* s( N8 J/ c( E0 p5 L1 s * when creating a IO Context there
9 n1 @% w8 M1 E' ~ A; Z */- ]6 l, J/ l1 |$ |: y1 ^; f4 M: ^
public IoCTX(Pointer p) {
9 H. A7 w2 T- B* n6 F2 P this.ioCtxPtr = p;: {" ]* V8 i7 U4 W" {
}
) y8 C' E. v( u s
+ I6 u# Q. Z, ?8 G1 O( ]# G1 X /**
( m" \& f+ Z4 H: w1 D3 @ * Return the pointer to the IO Context
; o* g, d( r. o2 N5 [9 J, I *
; A! ~# b9 i" v9 {5 l1 v2 g, n * This method is used internally and by the RADOS class
5 k+ O2 B7 v8 A f. g# k6 d3 F6 a! Z. K * to destroy a IO Context
{4 H# S' b- a: E8 M F- S *4 I* q) K R1 R
* @return Pointer
" g- ~! H: c/ o2 M */
2 t n* \ u: o/ l5 } public Pointer getPointer() {
3 L* B' f0 l# @0 X! z, P return this.ioCtxPtr.getPointer(0);
) s7 G$ p" R: ?, T& V }* w6 I% ^3 g7 m( y U
( H1 ^4 \- m0 h. J: Q; @8 L /**) W" K, z) m+ H3 i+ a
* Set the namespace for objects within an IO context.
/ z1 [5 N" E! d% `7 z- s. J/ J *
% ?7 H/ J* g) T( E) A/ J( G" i I * The namespace specification further refines a pool into different domains. The mapping of objects to PGs is also based on this value. D& z2 R9 N5 n6 M! L* w1 G9 V6 F
*. ?+ S; p/ b# x/ b1 U# z& H
* @param namespace The name to use as the namespace, or NULL use the default namespace.% C: y8 [: d1 |8 A K
*/9 m- ?* n' P1 S- z% W6 R
public void setNamespace(String namespace) {: r' N2 i# ]3 U. S( N& O2 `
rados.rados_ioctx_set_namespace(getPointer(), namespace); x' P/ s$ @, B7 L) M6 \+ I
}
% @9 V; h9 n1 A& M' l) }4 C8 @$ y; b
/**
1 `. n" ^! C( S0 p( K0 | * Get the pool ID of this context7 o; j1 c! s- p; _: V5 g
*# W% ?6 K1 _, f$ Q
* @return long
1 A, C6 n; a' b! d1 x# _ */3 h9 @/ T( i/ a* m8 h" _4 P+ A
public long getId() {% N+ O6 O" h+ g# r' Q: ~8 h
return rados.rados_ioctx_get_id(this.getPointer());
( `9 F( C. i- p, R3 T: M }
: `0 |" D* z2 q* Y4 N- Y) x5 f$ m7 V( \1 ]
/**
, A& a: T0 a2 q7 g# ^. ~$ U! Z" l * Set the associated auid owner of the current pool- `) X/ H5 h2 n! N9 L. S. x1 R) l
*
! s$ B% I% @& l/ Q8 p1 h0 v * @param auid- h# M( W$ d7 m
* The new auid
( \5 t- ~7 H* F( ] v * @throws RadosException
. z1 V: \, b4 `; y% O, L */9 {2 r- T4 z2 [( ]" i n- S
public void setAuid(final long auid) throws RadosException {
7 y: Q2 K4 l6 a8 U/ V S9 w& c) @ handleReturnCode(new Callable<Integer>() {
i9 [3 x$ K0 r @Override
3 Q0 Y# ^! L* U# f public Integer call() throws Exception {$ B# c3 Q' x, T6 D6 `
return rados.rados_ioctx_pool_set_auid(getPointer(), auid);
) v4 I1 w* F# L1 P" ], B& ~4 ?" Y- I }
: |( x. L+ ^: P# c1 z" U9 H }, "Failed to set the auid to %s", auid);
( v9 A: N% B" k# I3 V }
5 ^1 ], }4 b- G7 b& _( u
6 g2 W$ B! |4 Y: U1 T! X+ M /**2 B; c7 a; b Y
* Get the associated auid owner of the current pool( @* I( W& }& x
*
7 Q" u+ D' k0 |: P: f * @return long
( `1 E8 v' _5 s2 t% }/ [ * @throws RadosException
. Z0 E. F4 h7 t. ^7 Y */
* ~5 a' ~$ e& B5 D+ p5 Q7 p public long getAuid() throws RadosException {
, j. n6 y; c0 j7 s! e$ O final LongByReference auid = new LongByReference();( Z9 K4 m$ G* A$ x+ E
j# R0 i( j5 G" R9 j
handleReturnCode(new Callable<Integer>() {& d& B2 G/ m8 B6 J7 `
@Override* ~* q/ m$ Y& A7 p ]9 y
public Integer call() throws Exception {! y6 O( }$ r. {: p, f2 v# S! Q
return rados.rados_ioctx_pool_get_auid(getPointer(), auid);
/ Q. x: p2 D* ?7 \7 S- T* ^" T1 g }
' n6 v) Q0 q6 s# U( ^ W }, "Failed to get the auid");3 J d, J& ?2 A) V6 s
! c! `8 i, q6 T: B
return auid.getValue();4 j Z+ Y! h) m7 @7 T( w
}
. e A" _4 D6 G8 A, d6 Q
9 o9 ?4 a2 R! g6 ^. w/ \ /**+ ^* Q0 y4 w F6 w( v" f
* Get the pool name of the context
! a1 L9 `* p v2 t& f4 K, [ *. a: o1 {- N+ H0 z }1 h7 _# a
* @return String
$ N& U/ b3 m) R7 V( A * @throws RadosException
! O/ H8 H2 N" k& |+ e1 z8 [1 L+ { */7 r& Z( |4 [1 F1 a5 [4 [+ R
public String getPoolName() throws RadosException {
. Y. \0 E) s3 ~( {, u* Q final byte[] buf = new byte[1024];
! E+ Y, ~9 l- b3 k, _1 o! k handleReturnCode(new Callable<Integer>() {
' e7 @) H: d. U% W3 z @Override5 D# ~/ J' ]. D
public Integer call() throws Exception {
8 X$ R. ]4 ]/ e return rados.rados_ioctx_get_pool_name(getPointer(), buf, buf.length);1 K w! p* U6 a+ i/ v
}
n( R; X: o2 X, }) t0 k }, "Failed to get the pool name");
% R$ g) i% \- ~ ?! g% R" ?1 \# b return Native.toString(buf);
A! G& Y3 G" i, O }
- g4 Z* i9 p, h
- M/ O0 l- Z6 J+ u. f8 Z" W /**
2 s3 f- q' x/ G6 Z( I+ ^2 P. s7 z * Set the locator key, R9 E n; X) O
*
( L: s2 a1 B( ? * @param key
1 P/ y! l6 u* U9 A4 g1 Z% C * The new locator key or NULL to remove a previous one+ X" K5 f! M7 P% u# W, |
*/7 D, H8 J% |+ ^% V6 n
public void locatorSetKey(String key) {
0 o. _. s9 \8 x9 Q rados.rados_ioctx_locator_set_key(this.getPointer(), key);) e6 K H# \: G) B! h
}/ Z, h" h2 ]0 T. |4 w* U
9 e# \" M8 V/ V7 w6 K
/*** \2 Q7 h, z5 X8 r8 U0 t5 V
* List all objects in a pool
; W. i, P) @& S# \) a *
4 P% `! U0 L# v# {2 e. L* d% g * @return String[]' b( p8 \, l! m
* @throws RadosException9 W* N3 s3 l" D% p! q) D
*/
5 w, v- m1 h* p, Z$ n5 ?% } public String[] listObjects() throws RadosException {
V2 a/ E" z( g Pointer entry = new Memory(Pointer.SIZE);8 t6 q9 g* j; q1 G
List<String> objects = new ArrayList<String>();
: Q. L5 t' i' _% ~% S: T; G% Z final Pointer list = new Memory(Pointer.SIZE);
' N& h6 E% p- q$ b* A7 k, ~$ f2 M+ [9 G9 A$ ?0 B0 ^
handleReturnCode(new Callable<Integer>() {1 N2 M- M/ ?& ~" g0 ~ U$ G9 F
@Override+ ~6 x( n* {/ K, [. H4 j& p5 _
public Integer call() throws Exception {
& u2 d8 d. W5 k+ C, e" P return rados.rados_nobjects_list_open(getPointer(), list);
# h2 n6 Z1 d E0 X1 \9 | }
3 M% O( B9 }$ n* [ }, "Failed starting to list all objects");) j6 }" q+ O* s1 a
4 }* @1 G) \6 ?% W/ _ while (rados.rados_nobjects_list_next(list.getPointer(0), entry, null, null) == 0) {
& U6 F/ M* K9 X7 V objects.add(entry.getPointer(0).getString(0));
+ X% a) i; v; R% v5 J) h5 ~! W2 K }( o' ]$ G) L" [) \1 P7 W' e
/ O" u, f: w7 {1 f( X
rados.rados_nobjects_list_close(list.getPointer(0));9 n) \; v5 T- ^& M
- X# G# U% {* o; a* O& j$ }* g return objects.toArray(new String[objects.size()]);
" A" u9 u0 m: f6 p+ J2 X- @ }: K6 y0 J* X% p
( L2 A" p- { {# P* h2 D /**
+ ?6 R1 |& t( G- l8 ~ S' p0 g * List all objects in a pool by piece. Useful if a lot of objects are in the pool and do not2 k5 [' h) A5 R: L9 L
* fit in memory through listObjects() method
" V( G: g5 P, p& N: o1 V$ p2 Q; i s0 a * @param limit2 `& U' D7 b4 d' O" ~
* @return a ListCtx from which nextObjects()/nextObjects(skip) and getObjects() could be called) I8 s0 P0 ]% W2 B! y" X
* @throws RadosException# Z+ W+ s; w( g9 G
*/
; o, b+ o- k; o* Q1 v0 z public ListCtx listObjectsPartial(int limit) throws RadosException {
/ a$ j: {' ?% I F) e6 v2 B% P) P Pointer list = new Memory(Pointer.SIZE);1 N8 Z; ?( R3 D1 {5 r
4 a4 [, n; i0 i; O. T1 `/ { int r = rados.rados_nobjects_list_open(this.getPointer(), list);& J. q# Z; N8 Q. ?
if (r < 0) {
' b! V# V t t0 w- \ throw new RadosException("Failed listing all objects", r);
* t# K7 Q1 z/ y+ Y* W9 Z; J }0 q6 M+ v6 \5 @ B3 W6 G
return new ListCtx(limit, list);
5 M- p W% O( t7 h3 H }) |6 R: i* Z( O$ H
9 D- @1 u4 v& X5 Q /**
+ p, v% g- V' g$ x4 ? * Write to an object. y" B$ [/ z9 c; N
*
4 L. a) L9 ~( \ * @param oid8 R# Q9 w& W$ E+ o/ B t1 e
* The object to write to/ p' m; e$ w2 `6 j- I) l5 z
* @param buf0 u, e1 L4 b- A
* The content to write a# t9 }5 g# d, ?
* @param offset8 E0 ~% c' Q. J0 i
* The offset when writing7 I! [ ^7 c1 c6 H1 d; y( {
* @throws RadosException1 i$ Y6 Y2 H) H, U) w% ^1 J
*/
" L. b9 W8 O5 S+ @5 l" ^ public void write(final String oid, final byte[] buf, final long offset) throws RadosException, IllegalArgumentException {9 y0 W2 A( f- a! `4 Z! q3 P
if (offset < 0) {$ e* T- e8 C g; F
throw new IllegalArgumentException("Offset shouldn't be a negative value");
/ w5 s! l1 W' V/ y* j }
( D' C( n5 F' h# G% ^7 C# T+ K5 s# W1 n& e handleReturnCode(new Callable<Integer>() {' [' W4 Y7 D/ B: M: f6 i9 y
@Override
8 t% m% C, A5 p% g# _. t) k public Integer call() throws Exception {# W4 K5 S5 ~! \2 O a% h+ M$ q
return rados.rados_write(getPointer(), oid, buf, buf.length, offset);% u6 G& L- D/ }8 B
}' _- L" v$ o6 C1 k* b, ^* }
}, "Failed writing %s bytes with offset %s to %s", buf.length, offset, oid);
, Q- c" I+ W/ H% q1 K+ @, k; ` }
! ?) G' f+ t, x' D) }/ e$ w
! C+ a2 I. n' q+ O, X( d; N /** r+ V7 [% m0 T, A$ M
* Write to an object without an offset
( t b) e; U" s/ t' } *# j ]+ O' @# c0 p* k1 Z
* @param oid( M) r/ D9 l' S" Y8 t2 n* p
* The object to write to5 u/ y0 e! ^( Y0 D5 @* E
* @param buf; _5 @1 x' t% S; w
* The content to write
+ e- j, o% T- A) H( F D * @throws RadosException7 _6 _$ a) X( _/ |/ ~) g* I
*/; |7 u/ F3 t" { t+ A
public void write(String oid, byte[] buf) throws RadosException {9 c* K; M" m3 T/ f. t, n
this.writeFull(oid, buf, buf.length);0 _3 p J1 i5 T, F* C
}9 a* A% P! X' D. s/ ^& v
3 l5 j& X$ N1 F% @2 I) A! W* R
/** F& e( z' y4 |- o6 O) r! ~
* Write an entire object0 n3 P/ |! i% X
* The object is filled with the provided data. If the object exists, it is atomically truncated and then written.
: i+ g, h! o- I& o *
) ? @5 P/ a" H: T8 ^- T* g * @param oid0 c+ x, s! Y+ }: n4 ^
* The object to write to
4 [& \# R, J% B o2 r: E * @param buf* q8 B' a; z0 g6 [" C0 @
* The content to write
0 \4 o3 Q( S6 x4 n( M# P* I) R * @param len
7 {6 @* p) p- Q" [+ m+ D * The length of the data to write& a6 M, A9 z: r$ r7 D" @) H% \
* @throws RadosException$ I/ ^3 c+ f9 [( f& A" M
*/
6 G! B* ]3 X) K, j# A public void writeFull(final String oid, final byte[] buf, final int len) throws RadosException {" g( |7 p' ~- O" H o7 l
handleReturnCode(new Callable<Integer>() {) O# s* r& |3 Y. b, b6 F
@Override
! C+ x1 a9 g! S public Integer call() throws Exception {
; J& p8 }* U: q% D" ]' ^ ^ y return rados.rados_write_full(getPointer(), oid, buf, len);' w# m$ ]7 r$ a( p
}
4 H$ d) }# Q5 m/ I8 m }, "Failed to write %s bytes to %s", len, oid);
$ L; r x8 ~, L% v! D }5 s" T5 X2 V4 {9 u& h( N } u
0 P: [+ h" d8 C U g0 E
/**
; K& P5 ?5 J9 h% @& V7 k6 h * Write to an object without an offset3 U d* p3 y9 N1 W. G
*5 [( a- O8 t* V$ V# O
* @param oid2 m* E3 c; ]7 T% r7 K! \
* The object to write to. X6 |. w% Q; f5 A
* @param buf
- U: [' T3 y* j5 Q& T * The content to write
* G% b- b: F. m, B * @param offset Z# `4 ^* M) A- |1 t8 i
* The offset when writing; g4 f# f0 Z7 p3 F& h
* @throws RadosException
% q. C L2 E6 w e% m) ^ */+ g% u% D0 p4 H/ c/ \0 `
public void write(String oid, String buf, long offset) throws RadosException {; o* `; N$ e# L, J+ t* P
this.write(oid, buf.getBytes(), offset);% S, Z1 O" h+ w s" D6 o, u
}
4 I! \8 ]9 j( a
$ r- v9 P& u* e0 O9 e' g W9 U /**
* `$ E! N6 S' t" D" H: k q E9 f * Write to an object without an offset
- n. b9 S0 ^% ~, m+ ` *
( p. K5 p, T+ E/ j7 [ * @param oid
g- h3 @4 m& F4 b" q/ p; y * The object to write to
# e. Z9 y% @8 @ t8 a# y2 r * @param buf
1 O5 r7 v/ o; l- V6 E * The content to write
( K! Q$ S7 o' g0 f F3 Y) n * @throws RadosException
+ z; Z- Z9 p0 C# \. f% E */
( X4 v9 |+ D( T+ h6 v public void write(String oid, String buf) throws RadosException {8 c" f% D9 m# e
this.write(oid, buf.getBytes());
2 X# }; M5 S) h }1 p* H7 ]" ]$ j: L T; ?0 z6 u/ i
6 n* S% ?/ I3 q6 |4 h7 M
/**
, k! P+ c% {. ~5 y( G$ W4 G * Asynchronously write to an object
4 j9 ]9 ]; ~3 \3 \5 x. N *
5 ?: z' l3 a- B$ v9 u4 a8 } * @param oid" m3 x+ ^, q9 ]1 f/ y4 x8 g
* The object to write to
& V# ^4 _( T5 ~# Z* v! D% @$ y$ U3 e * @param completion
; d3 p/ e; j$ v8 i) o/ l& r4 A; n * The completion instructions
6 z- U5 \1 `+ Y' ?; a * @param buf
1 k1 t# t6 u/ s5 A * The content to write
8 c. L- k$ T' B: G. F* P * @param offset
. X- x: {8 h& R$ I, T * The offset when writing
S: s' @. {, A2 u/ x * @throws RadosException
7 U; }: s8 ~7 R! o/ R */9 g' g0 I& {8 I7 F1 }# p
public void aioWrite(final String oid, final Completion completion, final byte[] buf, final long offset) throws RadosException, IllegalArgumentException {
7 q6 O; }% w) K0 h* H3 D if (offset < 0) {: w# ^5 D: M4 a3 M) B* @( }3 |' K
throw new IllegalArgumentException("Offset shouldn't be a negative value");
" M o6 N1 y1 i, ]: x+ r: \ }
! l( y5 e) `9 S( p& u! z; M3 r handleReturnCode(new Callable<Integer>() {2 f8 j0 P, z5 p" t* v; {
@Override+ y' {; q; m( W
public Integer call() throws Exception {3 g+ ], p! _8 ^, A) n1 Y
return rados.rados_aio_write(getPointer(), oid, completion.getPointer(), buf, buf.length, offset);
/ R" g D) V/ n* `$ j& o' ~ }' x' c. q+ }' \
}, "Failed AIO writing %s bytes with offset %s to %s", buf.length, offset, oid);" Q( e' o g5 ` F# T2 q: m, e
}: x9 O- O4 ^4 c+ U
+ E9 ]) ]; H/ E* Q) B+ X
/**) J2 V# }" K$ n" I
* Asynchronously write to an object without an offset
8 D) [0 B; p2 j5 y) U) b) \( d *: y4 E/ u+ @. q- N1 v5 @5 U- z/ \
* @param oid l3 b# l0 n& ?7 `6 D, d! ~' `
* The object to write to
- ?% C( |( H( ?& _$ u# K * @param completion
! T$ J, Q7 U9 V% Z4 ~6 A * The completion instructions
& ~4 U5 S/ O) U0 p# H4 ~) z * @param buf2 v& [: w! t5 }5 J# n! t
* The content to write) m$ _5 c( U5 Z6 E- K0 m! B) n
* @throws RadosException3 k- h l4 c- M( t
*/( X/ f' m: P1 }: ?1 A
public void aioWrite(String oid, final Completion completion, byte[] buf) throws RadosException {/ r% T) N& t' y: b1 k
this.aioWriteFull(oid, completion, buf, buf.length);
3 f3 k4 u) w. Y) I, a& @ }4 C9 s3 y" D) S+ H _
" E* D4 M! B# a* y7 `+ k/ ~ /**
1 Q6 C' ~8 H: h1 V4 ~! ~ * Asynchronously write an entire object$ Y$ B2 N# G2 G) `( s
* The object is filled with the provided data. If the object exists, it is atomically truncated and then written.- T, J' J: A: x& |$ D) Z2 e3 z
*# q9 Q4 R% F/ |9 I3 z
* @param oid
B2 P2 Q: |; V2 E5 {' x" |- J * The object to write to6 e' V8 ^% r9 a4 i( b
* @param completion" k6 Q0 Y l" Y G$ n4 e2 X
* The completion instructions
) a& h) _9 P2 p; O% G+ K, T* x * @param buf
4 ]8 N; V+ t! |2 e+ t * The content to write9 n# ~2 P! z& _/ Z- N
* @param len
4 ]) L/ \6 Z( P * The length of the data to write# }: x8 D6 m3 j* Y! P, e
* @throws RadosException$ s) B; c( y7 C* I
*/0 c! f6 F+ I" W' I- y0 y
public void aioWriteFull(final String oid, final Completion completion, final byte[] buf, final int len) throws RadosException {6 d2 `1 H8 c$ z4 F4 u
handleReturnCode(new Callable<Integer>() {
. B7 y$ ]0 {* O' | @Override
0 |/ f% X' M: O) ]7 v; T public Integer call() throws Exception {
5 F Y A* ^, |0 B return rados.rados_aio_write_full(getPointer(), oid, completion.getPointer(), buf, len);! v* p/ `" G, G; M( m9 `- ]0 _
}5 k u4 L: U* j
}, "Failed to AIO write %s bytes to %s", len, oid);" Z! e$ \* ~7 b( X: ~
}
; }4 F' Z$ r7 {+ Z# i( V, l+ `$ A4 x( O; v# M7 A
/**
4 v' M5 L+ Z& g, T * Asynchronously write to an object without an offset% R, a& M& }1 x$ g0 @4 F3 B6 X K
*
& a' v5 m) n' D7 R& P * @param oid
! |- o" [1 q5 n: `" g * The object to write to3 [: G. d3 X8 O0 z
* @param completion/ h7 H9 C* K, p2 ^" t1 N% U
* The completion instructions& p. X- Q2 h6 Q6 x5 i- |( q
* @param buf) T1 }+ B) i+ U0 G/ C
* The content to write: k @0 w6 W. x( X1 }) P3 y5 c" x
* @param offset7 x& @' v+ X4 v# ]# y+ P: A6 W
* The offset when writing
+ c& g M& M+ i& h * @throws RadosException4 Q$ _- L# ~2 [* L
*/' i4 Z' ?3 S `3 M% S3 U" K
public void aioWrite(String oid, final Completion completion, String buf, long offset) throws RadosException {
, G( b# A7 V( ] this.aioWrite(oid, completion, buf.getBytes(), offset);' V# v% B" y! m! E2 B* u# R
}* z7 T) ~; F/ p
; c8 ~- T- M7 W/ T) n' I
/**
6 V& O7 v1 o8 t0 k# c * Asynchronously write to an object without an offset/ }+ y) \- N% A' ~
*
! v8 Y% w$ p, ^' }8 q0 F5 W3 V" h * @param oid
0 i0 q1 x# K Y1 ~/ x+ r * The object to write to
+ E% z! B# Z/ u4 s( w# ~5 F0 S2 D * @param completion6 [" X+ t" l; Z4 e% [, k
* The completion instructions
0 [* S9 V2 _+ e0 Y, I * @param buf$ n8 L2 W8 l0 O
* The content to write
! F( N. K- `+ W6 ^1 { * @throws RadosException9 k% n9 q( }3 W2 r# C) a7 l
*/% v. v2 b \. F1 r2 E: H
public void aioWrite(String oid, final Completion completion, String buf) throws RadosException {
' i8 r* |4 \7 w8 o6 b' p0 t this.aioWrite(oid, completion, buf.getBytes());
2 P6 P8 U( Z0 C8 s& f" c }
7 j" O. Y( d3 O: J5 u5 @& b
( y7 W z" F, d/ o% @; e4 x9 g /**% y4 M# C. q* m) `9 U5 _. B% G" y
* Block until all pending writes in an io context are safe.
4 p. }5 f* k" c5 n g0 E5 U *$ t/ b3 t5 s1 l8 R3 ]. U% E
* 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.
: ?& u5 N8 e `( j) D * @throws RadosException/ v( Z. m; y! A; J/ }! M8 o
*/
6 O9 j* n6 f% y5 G public void aioFlush() throws RadosException {
. j- f* U) k( g1 S% B$ }, D% S handleReturnCode(new Callable<Integer>() {7 K v4 G# Y' f J( T U2 S" }. `
@Override r! z" E* t( U7 b( q" s# p( A x
public Integer call() throws Exception {
- ~9 n$ J1 {8 s) e V- ^ \ return rados.rados_aio_flush(getPointer());; i) k) c9 i5 G5 n
}
/ N- I2 `, b d5 q }, "Failed to AIO flush");
+ w! V4 ]4 Z1 i* f$ t* ?2 ?1 Z% A }2 U3 }* {* E& O/ U6 a+ @
# t B1 w: e! h1 P& ?( V" _ /**
+ o' [: T8 \/ Q+ H# P& ~* {: S6 Z * Remove an object
G2 e; j/ e ~7 o *) J) k G4 o Z% \, h' u! ]
* @param oid, g6 E# Y" i8 T* i3 v& B; \
* The object to remove
$ R0 u1 y5 q+ n% j" d! ? * @throws RadosException
) {0 Y& |2 Z) k */
' C/ w; a7 ]- f* _0 } C3 u public void remove(final String oid) throws RadosException {
3 m1 o$ G$ a: l; Z handleReturnCode(new Callable<Integer>() {6 [2 B; H I, S! r9 [2 J; C. G: e
@Override4 m) j3 w5 q( F; n7 j
public Integer call() throws Exception {
6 g: V% j' ]8 W9 I" i. c return rados.rados_remove(getPointer(), oid);
/ }, |! |; b. p6 p- J* L$ l8 Q }
; Y4 s5 _4 H3 @4 m) L) C }, "Failed removing object %s", oid);
s: Z, h, O, N }" _8 G+ p5 O* @- i5 x0 J" e
4 P8 R) M3 p7 [5 i( v% y( N Z
/**: Y5 w) e7 g( P; b, u. F% W5 d
* Read data from an object7 O7 |" C9 h$ A# J( @; l% o- ^
*
8 K6 q+ ?1 C$ n# R: C * @param oid$ {% e, \* q+ Q6 A% u+ @/ {
* The object's name c. k/ T0 F; \) j! G1 _2 h( J) |- e
* @param length
# K$ \. K2 Y! H# I% ~+ N4 {: k * Amount of bytes to read' R5 T1 ~$ f! P
* @param offset3 T) Z M6 U# v- P0 A) B
* The offset where to start reading! P P& @& N# h7 b1 B# Y
* @param buf$ t7 N( p5 B7 F( f$ J+ G- ~2 b
* The buffer to store the result7 `; k3 T3 e5 K. Z. j
* @return Number of bytes read or negative on error" R3 O( V2 v- v4 f1 s8 X' X* t
* @throws RadosException
& y" [. i# t% G& Y */- K- F- a" c, v2 Y. {1 i( h
public int read(final String oid, final int length, final long offset, final byte[] buf)
6 u/ U' G# z, D C throws RadosException {0 s! S$ J, b" e
if (length < 0) {
+ y1 w2 s2 U0 ?2 g h# h' c throw new IllegalArgumentException("Length shouldn't be a negative value");
/ ?8 h) {/ `+ V* L( i+ p5 Z. R9 Y }
! v* F. b6 w5 M if (offset < 0) {
5 L V" E2 g+ A; [+ { {/ { throw new IllegalArgumentException("Offset shouldn't be a negative value");+ ]! k6 Y, s3 {4 Z" q8 d
}( ~3 V* S" m k: V
6 S1 Q) P! b- k% w
return handleReturnCode(new Callable<Integer>() {
9 k) G1 n0 X; k0 E @Override
1 F1 R2 q; ^% a6 {/ g4 I) p public Integer call() throws Exception {
$ \7 ]* Z" U; k' e" u return rados.rados_read(getPointer(), oid, buf, length, offset);. g1 ^6 A- M' U8 s& q
}
6 X ]* Z$ D, X }, "Failed to read object %s using offset %s and length %s", oid, offset, length);/ {. |% ]6 @; `
}) D# B! m. K- }! H" j# J
, _- ?2 g/ O9 i3 ?( `! A8 w' M
/**
2 g2 q" K6 B, k8 P7 f3 Q( R * Resize an object
0 Q- j7 s( k% X7 B0 n& q *, O2 I1 w2 r- y/ K* }# b; G" c
* @param oid9 C8 a7 j. I7 k* J# A$ u
* The object to resize$ U0 n2 h/ m# o ^5 n. q- o( s# Y
* @param size
! g N: B, u! t; ]0 T. y * The new length of the object. If this enlarges the object,
! x6 M. M5 K' Q' W1 v% }( j- s * the new area is logically filled with: C8 W+ w* N$ p V9 G
* zeroes. If this shrinks the object, the excess data is removed.' i8 ]2 {5 a% e8 n, A1 w$ h+ ?* z. q
* @throws RadosException) m1 U- L0 g( I
*/
6 ^3 q# ?7 k* O* u public void truncate(final String oid, final long size) throws RadosException {( f5 ~; N( m, G' }- }+ \$ E
if (size < 0) {
/ ~2 E# r. E# X6 B9 d+ i. w1 P throw new IllegalArgumentException("Size shouldn't be a negative value");
8 _1 F0 ]# Z4 y/ U: M }& ?7 O: G- u- D7 C) J
handleReturnCode(new Callable<Integer>() {, n# t- i0 [0 ?
@Override% K) B( o# [1 L' s3 s) p- V" l3 X
public Integer call() throws Exception {
0 j! t# }. K! m1 v! L7 z return rados.rados_trunc(getPointer(), oid, size);
7 `2 B1 G } q5 | }$ U2 _7 K+ t3 M
}, "Failed resizing objects %s to %s bytes", oid, size);/ s. j) d( I/ J. |
}
2 a. f% p9 R) m J- F0 a" f, Z4 X7 |
/**
9 {! J' Y/ ~, p `, \7 P# ~- l * Append data to an object0 l @; W+ {( f- A7 C W
*
$ F1 U; r& s' |/ O- h d& L * @param oid
1 T2 {) u3 s1 k) U z: z% @ * The name to append to
, f3 t9 C/ R4 ^- G* f# g * @param buf+ O( @7 ~- m0 m5 v
* The data to append7 B$ G. Y- a4 e7 e
* @throws RadosException
7 a' X' p0 w- U) c6 D* m8 K$ i *// W0 x p9 _" ?8 C9 ]/ |7 z4 t1 w8 I
public void append(String oid, byte[] buf) throws RadosException {
+ A' a5 r1 _7 L3 F5 ~" p2 ^+ m this.append(oid, buf, buf.length);
" [1 |9 z; `6 u0 }( T }
, i* {6 H: c# e/ _" } h" Q. P
0 }3 l( X1 m4 n /**! J9 E {! W' ~4 }% d2 D3 r2 @
*1 f3 O1 \6 Y4 S* E6 Q0 b9 ^( P8 g
* @param oid: a# F( O& X \& V! C* w% ]
* The name to append to9 R% A9 P9 h: g; k6 S
* @param buf
& ?0 J8 D; Q& z6 Z/ c * The data to append/ \9 E9 I& A! Q' u) _. L
* @param len
) l6 ^/ _5 w& I6 q * The number of bytes to write from buf
. b( L. Y% F* ^8 h' u. `' z * @throws RadosException8 M$ I; C7 V; P+ P& Z9 }
*/' m1 Z ?; z' [/ v% l
public void append(final String oid, final byte[] buf, final int len) throws RadosException {
7 d9 ^4 V1 J% A% T- i5 `: m handleReturnCode(new Callable<Integer>() {1 {% S& Y( j7 b, m/ ?" H4 [$ o
@Override, b: |4 D0 l8 j" s. a! a
public Integer call() throws Exception {
8 X% k* F* ~0 h9 j+ h return rados.rados_append(getPointer(), oid, buf, len);8 |# S, }6 k+ Q+ [& K
}
# F! O0 j# H2 P$ G- O }, "Failed appending %s bytes to object %s", len, oid);
3 [) c1 a. n0 J$ L }
$ z: r a4 [2 G6 Q" _; _' @ f t. E+ l* x
/**
' q0 P% X8 G, J. V: r: Q0 ^. b9 v * Append data to an object: k/ ^: {% M. C& R9 X: {
*1 w0 a6 s* U0 o% Y' W# g2 ?: D
* @param oid$ b S# M% w) `: v1 w
* The name to append to6 V n4 K, C( \+ h; M2 d7 ?& ~
* @param buf
! M) u; s9 g# ?4 _' |0 ]# v: P% w& h * The data to append
5 \- n8 X) D3 `; K; S * @throws RadosException
1 f8 Y* e$ q- J( [ */
3 d2 A# c6 P4 |! O- D9 \0 _ public void append(String oid, String buf) throws RadosException {. `+ T( j* F( z3 T
this.append(oid, buf.getBytes());/ A4 w T2 f8 |" }! x% m
}
; a d/ [$ i* d8 i) d3 D" _; I/ B/ r9 G' g
/**! A* J, r& T: t# |2 e* }
* Efficiently copy a portion of one object to another
2 \/ _0 m# k! t. }! | *1 W3 |$ R* E# r1 c
* If the underlying filesystem on the OSD supports it, this will be a
2 M3 x" F, Y3 ~8 ^% p j8 c( | * copy-on-write clone.
3 [* L! L4 B; G7 m7 M9 o9 r *
8 F4 h$ ~2 E# r7 L * The src and dest objects must be in the same pg. To ensure this,
9 _( _* J$ r2 D( G * the io context should have a locator key set (see IoCTX.locatorSetKey()).
. |8 j6 C( _2 x8 @# B W *
3 c- C+ m& S4 q7 H * @param dst
- Q, j- ?1 U! Z( h# T * The destination object X& l3 ]; E/ X) x& i; S* ?
* @param dst_off
7 H: U! y& P3 G6 m9 c, J * The offset at the destination object
$ v' E4 w* n9 O1 t- a' l- x: I# o * @param src3 X5 g: N1 T. L; W* T# o- ]
* The source object/ Q5 c* F% i9 J. K7 E+ `
* @param src_off
* X+ A# U5 ]- z" V * The offset at the source object
" s4 w/ M5 ]0 _- A) i9 d * @param len, s, K4 d$ @* i3 Y5 K5 [, k0 |$ L) ]
* The amount of bytes to copy0 B: C8 i+ i. O2 x
* @throws RadosException& Z" d% g/ ]. Y' [' w
*/+ x9 X! A. G4 V( m0 p, Q$ p
public void clone(final String dst, final long dst_off, final String src, final long src_off, final long len) throws RadosException {3 r# B2 G5 g \: X& [% H+ M
handleReturnCode(new Callable<Integer>() {
+ F) @% M1 O; `7 ~: @; [6 w @Override# G. m7 S. {, z2 u( Q
public Integer call() throws Exception {
4 |0 O3 M3 u6 M" F2 l8 o) G return rados.rados_clone_range(getPointer(), dst, dst_off, src, src_off, len);
( p$ c! }6 I& r; Z5 g1 h! e. @* u }
% ~$ [3 S: N2 c }, "Failed to copy %s bytes from %s to %s", len, src, dst);
" S+ k* U8 d4 J. D }8 p* R' |4 n" S4 W5 G: S. }
+ x; p% z! T5 @2 v3 R7 u% w; k' l
/**' f, a; H% r) _1 o/ F/ S
* Stat an object( O& \- a; ^; o/ h9 ]
*& l$ q1 ~! _3 r- r4 Q8 C/ P# g
* @param oid9 _$ r5 z9 W" s' s
* The name of the object
7 J; M6 }6 O. J& a- y9 F * @return RadosObjectInfo
O s" k7 x, x- F; h2 l9 X" N * The size and mtime of the object7 J9 j0 y$ x; Z. Q v. V8 n" x
* @throws RadosException9 L8 }" W4 f8 X! y- \5 j7 d9 O
*/
& f T: d% f; ]+ I3 I' Q public RadosObjectInfo stat(final String oid) throws RadosException {! S4 v' ^; s ?6 [5 ~; b+ [
final LongByReference size = new LongByReference();
4 Z9 I, ~4 Z2 X$ {2 k4 U% Z) p( h final LongByReference mtime = new LongByReference();9 l$ v8 D: M% X: C6 t
handleReturnCode(new Callable<Integer>() {
& L1 A2 D6 u) [ a' ?/ T6 R @Override
! \7 {" T; C* v1 | public Integer call() throws Exception { ?: {; r, Q. }2 y
return rados.rados_stat(getPointer(), oid, size, mtime);
8 c* }+ _8 J' C }: x# n* F9 p7 f* P' E) o
}, "Failed performing a stat on object %s", oid);5 u- o7 Q! B% [7 d
return new RadosObjectInfo(oid, size.getValue(), mtime.getValue());7 P7 W- H! C8 q) n
}% s/ ?" g" H0 n
5 E, |# ~/ m3 O: T! k /**
* p, V9 d* f* B% d6 w9 H * Stat the currently open pool
5 N( U% B) Q( h' Z q *
8 U0 H- b: m b5 f+ z( l * @return RadosPoolInfo- `( Z* v+ W$ f/ Y& `& @
* @throws RadosException) C" ?% `" @1 ^* d
*/
3 V- g# E7 R1 C public RadosPoolInfo poolStat() throws RadosException {
- t* t9 u1 q! `2 Q# }& n final RadosPoolInfo result = new RadosPoolInfo();$ A6 h4 b9 l5 G; x% s% P/ v
handleReturnCode(new Callable<Integer>() {+ c7 D9 C( V, D' n2 H8 b
@Override
9 O1 b. d# m. k! \ public Integer call() throws Exception {8 T1 @; t& K/ r) Y6 s! V+ }
return rados.rados_ioctx_pool_stat(getPointer(), result);
! o. X Z5 }/ b$ Y1 P }
0 {6 I$ Z+ Z+ o7 B1 D9 n }, "Failed retrieving the pool stats");
, ~- \6 z6 g- h" j5 o2 b return result;
: ?8 h3 n3 m5 G }
' E; b& m& Y/ e) p l, a! T: H1 k1 R- o/ e5 X
/**
_; l$ Q, H$ I$ p * Create a snapshot8 E/ y- {( J! P$ p8 z" }+ R
*
' v9 h$ C, J7 n * @param snapname- t, ^, ~. |2 K; s" t
* The name of the snapshot5 U, P8 q. Z" d, B: u9 C% S
* @throws RadosException
6 s- \$ z# _3 Y% ]' i" {% |% d */
. d0 Q" W# m8 R' l" |/ U% M public void snapCreate(final String snapname) throws RadosException {$ q0 g' G: ^) ?
handleReturnCode(new Callable<Integer>() {
, w4 u' E1 B0 b& K! p" Y @Override
( O5 @6 y/ X- g" ^) F3 h. o5 H+ X3 h$ E public Integer call() throws Exception {, l! E9 f2 X$ |' Q4 W) G+ B |+ k
return rados.rados_ioctx_snap_create(getPointer(), snapname);7 t3 U2 |; E# L
}. U6 Q, b6 W+ o, m0 m
}, "Failed to create snapshot %s", snapname);
& T5 z6 w8 T; O7 m+ y& _ }4 T% Q; `( s7 L- `
% D" [' W# k9 d2 n! X- p /**! K9 M5 v" g1 O4 \
* Remove a snapshot
: a8 T7 ^5 d2 C ** n# f9 @/ r# L& C% W
* @param snapname- M( e9 ?) E; y W$ l
* The name of the snapshot
0 | R1 n3 g# {: e8 Z * @throws RadosException
7 M5 f4 {3 n) m, _) L% N */- F9 E9 ?$ R$ d$ J; n! e% X+ A
public void snapRemove(final String snapname) throws RadosException {% X& ?- g% a U' b; Y8 ?1 Q
handleReturnCode(new Callable<Integer>() {
+ s! Z$ t$ g9 F- u$ \3 I1 ` @Override; m5 M- a) D K! V5 x( t! O# J
public Integer call() throws Exception {$ A5 Z* Y+ r2 U1 A
return rados.rados_ioctx_snap_remove(getPointer(), snapname);
% r9 l( c- |$ L6 P: E }
2 Q2 R# J/ ?7 a5 n4 E2 l2 J2 M! c }, "Failed to remove snapshot %s", snapname);9 }' z: }/ h* P
}" Q' y0 J& C- K0 k$ F6 |% o
; y; d. v4 Q: ~1 l' t /**3 V5 |, q: \% X) \* M. S" ~
* Get the ID of a snapshot
! T/ M& L4 V+ C *% v) s/ V0 d; E R* `2 `8 f
* @param snapname
, U% E/ ? ? M& i- L% ? * The name of the snapshot/ r1 g0 v( h/ O/ n
* @return long
6 H$ f( K! q/ L * @throws RadosException
" E, S( L3 e3 s7 C# ` K3 l3 Y* i */# m: q8 `2 c. g1 R" f! M
public long snapLookup(final String snapname) throws RadosException {
! m: `7 f" L0 R0 e8 s# Y( P' ? final LongByReference id = new LongByReference();
+ a' r3 N% p5 n/ }9 O5 S+ Z6 C handleReturnCode(new Callable<Integer>() {$ e. Q) |6 Y. J
@Override' w* Q. T$ q% |: U
public Integer call() throws Exception {; C/ w" j) M+ p! ?
return rados.rados_ioctx_snap_lookup(getPointer(), snapname, id);
4 R! i4 i( ~, m! E8 A& Y/ G }
. E% J3 t8 C z* l6 I3 K }, "Failed to lookup the ID of snapshot %s", snapname);- A! _$ `! P1 P9 K
return id.getValue();
: _2 t; }' o) j+ T8 p }, b* v7 e- y0 }* m. v' k
! L9 W! z) O# T$ C( d /**0 q1 H5 f& m" V: c$ N
* Get the name of a snapshot by it's ID
6 g( T! o* V9 s: }3 E. R, Z6 c *, _( r6 E ?: C
* @param id8 c' j; }" K2 T3 A+ r
* The ID of the snapshot
u* D, F0 s! p% o$ i+ B% J1 n * @return String
+ F* L6 i& e$ I( e# Z5 ] * @throws RadosException9 I. n! _! b9 a# ^& M7 J
*/
# O! l3 S# \$ P% u$ ~4 V$ ^7 e public String snapGetName(final long id) throws RadosException {
6 p4 b# \/ z- X8 ]# F: d5 C final byte[] buf = new byte[512];
, d4 C' }& \' |; m handleReturnCode(new Callable<Integer>() {
' U4 }9 [/ K3 I5 g @Override
; H- A2 o% w% s8 z L2 b public Integer call() throws Exception {
8 C" v, x2 F1 f4 `# Q: p8 t h return rados.rados_ioctx_snap_get_name(getPointer(), id, buf, buf.length); u+ r& V$ ]2 i: P- R. u
}$ c9 F7 v/ V3 j; E+ a/ y
}, "Failed to lookup the name of snapshot %s", id);
+ v$ V5 J5 l- n return new String(buf).trim();. M {# [( Z: w2 ~
}* F- J5 u# `2 p: }# U
* ~6 I6 w. B# D) p+ }; H0 ?' j
/**
- P5 X, I8 y* m7 T5 m- l2 @4 B * Get the timestamp of a snapshot
$ L5 z- h0 _ y8 y9 m! Z; y *9 y3 ~) V+ _0 T) U
* @param id
6 C k0 n/ _7 S* ]$ m# y * The ID of the snapshot
( z: H# M" L1 \5 k* p9 y1 @4 H- {$ { * @return long, j8 O2 a6 D. m4 J7 D4 @- B
* @throws RadosException
0 b2 T$ j" t6 V, { */! C# h( v0 l# f, P/ v) a! ?' ]
public long snapGetStamp(final long id) throws RadosException {" Z: c. c$ G6 k+ q& s
final LongByReference time = new LongByReference();' K0 F$ p' u6 k$ r9 Q9 ~8 w
handleReturnCode(new Callable<Integer>() {
2 M2 H' t- N% o @Override
. l8 c( I$ T t; x public Integer call() throws Exception {
5 B0 o- {1 E+ b8 B return rados.rados_ioctx_snap_get_stamp(getPointer(), id, time);
1 t! w# Q( r4 m, h7 K: ?1 b3 ~- O }
) t$ u$ D; `3 M8 J4 p }, "Failed to retrieve the timestamp of snapshot %s", id);, c, f0 {' U. u, T" W% Q. y
return time.getValue(); o- R4 S3 p+ q; [0 E
}% [* B- R! s( n0 {# k
$ U( P3 F& A y
/**
- t" r h+ U9 v+ }, Z' i9 _- @ * List all snapshots
, O; P R1 M/ W" w' H9 q *: c$ h1 K( w" c3 h' ?# [
* @return Long[]
% ], J% Y$ p, T( m * @throws RadosException5 `9 @- M f L G# l
*/
, w4 K3 g- `$ h: z; t5 v3 t, F public Long[] snapList() throws RadosException {
6 |8 Y' h) S m+ c: ]1 S7 l final byte[] buf = new byte[512];
- \( {0 n% p/ ]
( y" W. E$ A8 A& b5 T, |8 m8 C final Integer result = handleReturnCode(new Callable<Integer>() {
9 o) f& q; N( P+ O @Override
) S+ p$ Q7 @. R5 [& k% C public Integer call() throws Exception {, X, w0 b! v: H' a
return rados.rados_ioctx_snap_list(getPointer(), buf, buf.length);
/ ]# S% j7 ? q9 |8 R2 a; f' C }
% b& r+ I1 z, P: m& X0 t }, "Failed to list all snapshots");
2 q5 G2 z5 }( O! X- @4 m* e* y. F7 F; ?# _% t: n4 T
Long[] snaps = new Long[result];! v# U5 n" F" C9 G6 c
for (int i = 0; i < result; i++) {
1 u) ]( V( O6 R& Z, K snaps = (long) buf;
* V9 l9 J2 E8 f. I$ G( f }
% J+ V0 _; ]8 f return snaps;7 a" T+ J' ~9 g# {
}+ R e Q4 x4 m7 L9 q5 f4 N1 a
8 q2 V8 l& u3 l! J; v, [0 c2 [8 }! h public ReadOp readOpCreate() {
4 O# s! c n0 y& t8 u3 a return new ReadOp(getPointer(), rados.rados_create_read_op());6 o/ i2 \: [% ^ n' ^, N& Q5 G
}
! S: |0 o$ A! x- C. i
9 ?* J8 Q4 t8 ]6 y /**
2 s; H! N0 S* a$ a \2 D. Z9 B * Instead of releasing the read operation directly, better use ReadOp.close
4 P' V7 B( X' f9 L */( L$ C* h: J" [4 G9 V6 R1 a
@Deprecated$ h6 @$ b- L4 g e/ S, h0 R
public void readOpRelease(ReadOp read_op) {
) E( j, t H' w! Y6 z rados.rados_release_read_op(read_op.getPointer());
8 O2 a. F9 r ]7 x4 P8 Q }8 a7 x- f* I# j1 f; d/ k; Q4 }8 d2 G# n. z
e- I S, A6 Z
+ U2 C+ X! s" | `% K! Y# P' r& t /**5 w* i, d& n4 b! {2 E% H
* Get the value of an extended attribute on an object.! w( L( k* K" R' ], R
*
6 u( }7 o9 Q( t/ w * @param oid1 N7 f- b$ v1 R6 p9 D& ^
* The name of the object
0 j! Y* M- q3 ~) g3 {5 d% p2 l2 ?6 D * @param xattrName. ~+ p, o9 l# z, `* b! {
* The name of the extended attribute8 q( h w9 v. j' F# L$ [
* @return- F0 A# V9 V) u9 J0 y8 f
* The value of the extended attribute
8 |) M( ]6 \ c: p6 u * @throws RadosException& A* {3 ^( j9 d% \, }9 w
* on failure -- common error codes:8 ?& e, h& c! o0 F0 W' T
* -34 (ERANGE) : value exceeds buffer
+ x% ^+ d* n$ j6 U/ Y; ^" f * -61 (ENODATA) : no such attribute8 V9 x( o, T$ C$ \# U% b
*/
( c; ?* {: |% E1 R1 S7 y- f public String getExtendedAttribute(final String oid, final String xattrName) throws RadosException {; ]' ]% a M: f7 `3 ~# M: [- h
final byte[] buf = new byte[EXT_ATTR_MAX_LEN];
1 R8 A) v O& `9 ?, l2 G handleReturnCode(new Callable<Integer>() {
6 X R9 o" T% C @Override1 r8 h6 W5 B) e
public Integer call() throws Exception {0 ?- o- G% i7 x
return rados.rados_getxattr(getPointer(), oid, xattrName, buf, buf.length);4 A7 g! P: b3 `! S/ Y& v
}! `" s4 I% E- P+ K, Z' C" H
}, "Failed to get extended attribute %s on %s", xattrName, oid);
" n5 y2 g0 X9 B: i5 t4 B" Z // else...
8 N% b! \1 }/ a% D# g return Native.toString(buf);
4 |1 @- b7 I# X }9 q d% J$ I6 {! ^; j5 V& p
) r- }4 P1 i2 n6 l
/**
1 R% ]& [5 U& Z& _9 Z9 V * Set an extended attribute on an object.
& S8 E2 ?4 Y% n *
( g5 R; t. E/ w3 Q * @param oid# n5 ]7 r4 e+ a" F( G
* The name of the object
. {% _/ M# P) H. ^. z* X * @param xattrName; i! X: k; ~2 M ?
* The name of the extended attribute: ?) c' N2 r/ B4 j
* @param val
/ B) H2 F: I \1 ~ * The value of the extended attribute
0 F# J* u* O+ [5 i2 x; A * @throws IllegalArgumentException
& H/ G! s$ B# t& c, X * attribute value is too long! }. @8 c& _2 T8 T M' Z" n% _( Q
* @throws RadosException
* ` B& g/ X1 a; p5 ?7 Z * on failure0 \$ C0 j+ Y8 W0 Z' ~
*/# ]" T0 X; Y7 t! d5 D$ c3 e- w
public void setExtendedAttribute(final String oid, final String xattrName, String val) throws IllegalArgumentException, RadosException {
* L2 w3 V8 x/ m9 O" L final byte[] buf = Native.toByteArray(val);
. r! k3 Z5 \* |7 O0 d if (buf.length > EXT_ATTR_MAX_LEN) {& d: s& y3 \2 ~( H
throw new IllegalArgumentException( "Length of attribute value must not exceed " + EXT_ATTR_MAX_LEN);
9 |. A$ i) ]8 J, N& [$ H }0 @- w+ _2 ]+ l# I! m
// else...0 H4 X& ~0 a" K4 [8 Q" \, ^' d
handleReturnCode(new Callable<Integer>() {" p# b5 O( {5 D/ x4 i- O4 f3 h
@Override
3 X' E% m( ]: {- ^) e public Integer call() throws Exception {: H" z* O; q# G1 {/ { X
return rados.rados_setxattr(getPointer(), oid, xattrName, buf, buf.length);
% i1 b7 J/ ?; s6 P# m- N4 u }
$ r: A {( w% B% f9 k }, "Failed to set extended attribute %s on %s", xattrName, oid);
. K0 p; W F& [$ I }, `* l' [ n% {. H. e1 E9 Y- h
& j" z3 {2 S0 b @8 V. ~/ y6 t /**
& i1 |0 ?2 t; w * Delete an extended attribute from an object. {5 D, z& l! Y" z7 j8 I4 ]) y
*
- ]- }* m! u( c' R0 S) |* J * @param oid9 P8 A4 e( o% E: o1 [8 L
* The name of the object8 i! L) b) | y0 r3 M" _* x. _
* @param xattrName$ S1 U) M0 e' @" @8 o- Z7 F5 {( ]" k
* The name of the extended attribute
2 Q! x, z2 p' P/ |+ ^ * @throws RadosException
/ C( E; |2 a' u$ b- w& `8 H * on failure; `7 ?' `0 } K% C
*/0 p/ x9 r' ?( Z2 g# f
public void removeExtendedAttribute(final String oid, final String xattrName) throws RadosException {
4 ~! q( A2 @ y$ V( T8 k6 {, @. z handleReturnCode(new Callable<Integer>() {
6 H1 |0 Y0 {- I @Override
7 w$ ]* S6 C, D- r( C1 [5 o public Integer call() throws Exception {
# k9 r+ |; h0 p0 p return rados.rados_rmxattr(getPointer(), oid, xattrName);. e# h3 P3 _5 y# ]
}! U, @( G- ?" z+ M/ e
}, "Failed to remove extended attribute %s from %s", xattrName, oid);
( n- @% e$ A4 P }
7 y& Q. I. y/ h8 _* w, N& Q( \( o2 V' L! p
/**2 a/ V, \4 h( i+ k) R% M/ u9 W
* Get all extended attributes on an object.
6 H' U3 }4 G7 ^9 C *
2 a0 F3 J+ |% c& R# M2 ^0 z: p * @param oid
6 \. w5 g' w+ I2 O; p * The name of the object
5 X- F, \7 D7 V3 t * @return: c1 [9 W. G3 S+ v
* The map of the extended attributes# W- J7 W3 a5 ^; G
* @throws RadosException8 t' u C8 q/ \: C. S
* on failure4 d! M* F4 z, N4 f" q6 g
*/
) k& w# k( n6 m! K3 s/ q public Map<String, String> getExtendedAttributes(final String oid) throws RadosException {7 D! m; J Q* L7 l4 K0 i
Map<String, String> attr_map = new HashMap<>();
6 x% d5 O8 r, N1 v final Pointer iterator = new Memory(Pointer.SIZE);
# M; V4 S b* ]5 v final PointerByReference attr_name = new PointerByReference();" u7 \& D+ j: V- G9 x* v9 H, g
final PointerByReference attr_value = new PointerByReference();
+ y4 I+ z3 Y B j final IntByReference attr_value_len = new IntByReference();
) X: E4 X/ E* e4 }1 c* ~0 T
: q T% {; h4 X$ H, U1 v! |% \ handleReturnCode(new Callable<Integer>() {0 L: r! ?. i" |) S
@Override9 j1 x7 @% b: v
public Integer call() throws Exception {! b6 f4 s# k! n* Z# B
return rados.rados_getxattrs(getPointer(), oid, iterator);
+ s; q {( | `- Z7 k8 g' g }
* K2 g# U9 C' E( j- n" Y! ] }, "Failed starting to list all extended attributes");: Q2 u, L3 ^% Y! e( i0 g7 h
0 e# p9 z% |% P9 I7 X
while (rados.rados_getxattrs_next(iterator.getPointer(0), attr_name, attr_value, attr_value_len) == 03 P& [$ z, e( Z3 I7 s* g M
&& attr_value_len.getValue() > 0) {9 u* B. K1 `: ~8 K. d+ m
int length = attr_value_len.getValue();
' `& w4 ?$ x6 x String name = (attr_name.getValue() == null ? null : new String(attr_name.getValue().getString(0)));
V5 N; q7 |8 L+ D D String value = (attr_value.getValue() == null ? null : new String(attr_value.getValue().getString(0)));0 ^( ` S, l& }5 o' v; W( r, m9 I
if (length > 0 && name != null && value != null) {) E8 A) m* _: M3 e- {
attr_map.put(name, value);
: ?: t# h6 ~) p# U8 O: @" P }6 a$ e" P$ `/ J0 Z, \9 o
}: m9 q* m. K& z6 H4 ~# \6 t( o* H
4 Z2 h" e" D) a8 E$ T3 a/ G2 }
rados.rados_getxattrs_end(iterator.getPointer(0));
" H; O; l4 k! D' Y# X7 t# I4 U! t V8 ^& [6 R# V" q" K
return attr_map;. S0 h" M7 R5 p
}
6 [0 u0 ^$ z3 R I! ^* ?" z
7 }2 f0 |. |8 N. S8 s0 N @Override
9 E/ o. c) j0 m0 U& Y2 o3 q public void close() throws IOException {/ A% z% y$ q" f
rados.rados_ioctx_destroy(getPointer());
- E0 ], x# v- l' U }
' J& f4 B; u; @6 R; D9 t}! J" ?: `, `( `5 i4 I
4 `6 F* h9 O' q
7 T% w& D3 x: O4 I至此,大家应该对Java访问Ceph有了彻底的认识了1 A+ Z& ?- V s! ?3 {3 i. ? g
* Z5 L* H) p" b/ V
# `5 c" X }7 s* P Z7 |
|
|