]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/librgw_file_gp.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2015 Red Hat, Inc.
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
23 #include "include/rados/librgw.h"
24 #include "include/rados/rgw_file.h"
26 #include "gtest/gtest.h"
27 #include "common/ceph_argparse.h"
28 #include "common/debug.h"
30 #define dout_context g_ceph_context
31 #define dout_subsys ceph_subsys_rgw
34 librgw_t rgw
= nullptr;
35 string
uid("testuser");
36 string
access_key("");
37 string
secret_key("");
38 struct rgw_fs
*fs
= nullptr;
40 bool do_pre_list
= false;
43 bool do_writev
= false;
44 bool do_readv
= false;
45 bool do_verify
= false;
47 bool do_create
= false;
48 bool do_delete
= false;
49 bool do_stat
= false; // stat objects (not buckets)
50 bool do_hexdump
= false;
52 bool object_open
= false;
54 uint32_t owner_uid
= 867;
55 uint32_t owner_gid
= 5309;
56 uint32_t create_mask
= RGW_SETATTR_UID
| RGW_SETATTR_GID
| RGW_SETATTR_MODE
;
58 string bucket_name
= "blastoff";
59 string object_name
= "jocaml";
61 struct rgw_file_handle
*bucket_fh
= nullptr;
62 struct rgw_file_handle
*object_fh
= nullptr;
64 typedef std::tuple
<string
,uint64_t, struct rgw_file_handle
*> fid_type
;
65 std::vector
<fid_type
> fids
;
67 std::uniform_int_distribution
<uint8_t> uint_dist
;
70 constexpr int iovcnt
= 16;
71 constexpr int page_size
= 65536;
72 constexpr int seed
= 8675309;
82 std::vector
<ZPage
*> pages
;
85 explicit ZPageSet(int n
) {
87 iovs
= (struct iovec
*) calloc(n
, sizeof(struct iovec
));
88 for (int page_ix
= 0; page_ix
< n
; ++page_ix
) {
89 ZPage
* p
= new ZPage();
90 for (int data_ix
= 0; data_ix
< page_size
; ++data_ix
) {
91 p
->data
[data_ix
] = uint_dist(rng
);
93 p
->cksum
= XXH64(p
->data
, page_size
, seed
);
94 pages
.emplace_back(p
);
96 struct iovec
* iov
= &iovs
[page_ix
];
97 iov
->iov_base
= p
->data
;
98 iov
->iov_len
= page_size
;
102 int size() { return pages
.size(); }
104 struct iovec
* get_iovs() { return iovs
; }
106 bool operator==(const ZPageSet
& rhs
) {
108 for (int page_ix
= 0; page_ix
< n
; ++page_ix
) {
109 ZPage
* p1
= pages
[page_ix
];
110 ZPage
* p2
= rhs
.pages
[page_ix
];
111 if (p1
->cksum
!= p2
->cksum
)
117 bool operator==(const rgw_uio
* uio
) {
119 int vix
= 0, off
= 0;
120 rgw_vio
* vio
= &uio
->uio_vio
[vix
];
121 int vio_len
= vio
->vio_len
;
124 for (int ix
= 0; ix
< iovcnt
; ++ix
) {
125 ZPage
* p1
= pages
[ix
];
126 data
= static_cast<char*>(vio
->vio_base
) + off
;
127 cksum
= XXH64(data
, page_size
, seed
);
129 if (p1
->cksum
!= cksum
) {
130 int r
= memcmp(data
, p1
->data
, page_size
);
131 std::cout
<< "problem at ix " << ix
<< " r " << r
<< std::endl
;
136 if (off
>= vio_len
) {
137 vio
= &uio
->uio_vio
[++vix
];
138 vio_len
= vio
->vio_len
;
147 for (int page_ix
= 0; page_ix
< n
; ++page_ix
) {
148 ZPage
* p
= pages
[page_ix
];
149 p
->cksum
= XXH64(p
->data
, page_size
, seed
);
153 void reset_iovs() { // VOP_READ and VOP_WRITE update
155 for (int page_ix
= 0; page_ix
< n
; ++page_ix
) {
156 ZPage
* p
= pages
[page_ix
];
157 struct iovec
* iov
= &iovs
[page_ix
];
158 iov
->iov_base
= p
->data
;
159 iov
->iov_len
= page_size
;
164 for (unsigned int ix
= 0; ix
< pages
.size(); ++ix
)
171 ZPageSet zp_set1
{iovcnt
}; // 1M random data in 16 64K pages
180 int ret
= librgw_create(&rgw
, saved_args
.argc
, saved_args
.argv
);
182 ASSERT_NE(rgw
, nullptr);
185 TEST(LibRGW
, MOUNT
) {
186 int ret
= rgw_mount2(rgw
, uid
.c_str(), access_key
.c_str(), secret_key
.c_str(),
187 "/", &fs
, RGW_MOUNT_FLAG_NONE
);
189 ASSERT_NE(fs
, nullptr);
192 TEST(LibRGW
, CREATE_BUCKET
) {
195 struct rgw_file_handle
*fh
;
197 st
.st_uid
= owner_uid
;
198 st
.st_gid
= owner_gid
;
201 int ret
= rgw_mkdir(fs
, fs
->root_fh
, bucket_name
.c_str(), &st
, create_mask
,
202 &fh
, RGW_MKDIR_FLAG_NONE
);
207 TEST(LibRGW
, LOOKUP_BUCKET
) {
208 int ret
= rgw_lookup(fs
, fs
->root_fh
, bucket_name
.c_str(), &bucket_fh
,
209 nullptr, 0, RGW_LOOKUP_FLAG_NONE
);
214 static bool r2_cb(const char* name
, void *arg
, uint64_t offset
,
215 struct stat
*st
, uint32_t st_mask
,
217 // don't need arg--it would point to fids
218 fids
.push_back(fid_type(name
, offset
, nullptr));
219 return true; /* XXX ? */
223 TEST(LibRGW
, LIST_OBJECTS
) {
225 /* list objects via readdir, bucketwise */
228 ldout(g_ceph_context
, 0) << __func__
<< " readdir on bucket "
229 << bucket_name
<< dendl
;
232 int ret
= rgw_readdir(fs
, bucket_fh
, &offset
, r2_cb
, &fids
,
233 &eof
, RGW_READDIR_FLAG_NONE
);
234 for (auto& fid
: fids
) {
235 std::cout
<< "fname: " << get
<0>(fid
) << " fid: " << get
<1>(fid
)
242 TEST(LibRGW
, LOOKUP_OBJECT
) {
243 if (do_get
|| do_stat
|| do_put
|| do_bulk
|| do_readv
|| do_writev
) {
244 int ret
= rgw_lookup(fs
, bucket_fh
, object_name
.c_str(), &object_fh
,
245 nullptr, 0, RGW_LOOKUP_FLAG_CREATE
);
250 TEST(LibRGW
, OBJ_OPEN
) {
251 if (do_get
|| do_put
|| do_readv
|| do_writev
) {
252 int ret
= rgw_open(fs
, object_fh
, 0 /* posix flags */, 0 /* flags */);
258 TEST(LibRGW
, PUT_OBJECT
) {
261 string data
= "hi mom"; // fix this
262 int ret
= rgw_write(fs
, object_fh
, 0, data
.length(), &nbytes
,
263 (void*) data
.c_str(), RGW_WRITE_FLAG_NONE
);
265 ASSERT_EQ(nbytes
, data
.length());
266 /* commit write transaction */
267 ret
= rgw_close(fs
, object_fh
, 0 /* flags */);
272 TEST(LibRGW
, GET_OBJECT
) {
275 memset(sbuf
, 0, 512);
277 int ret
= rgw_read(fs
, object_fh
, 0 /* off */, 512 /* len */, &nread
, sbuf
,
281 bl
.push_back(buffer::create_static(nread
, sbuf
));
290 TEST(LibRGW
, STAT_OBJECT
) {
293 int ret
= rgw_getattr(fs
, object_fh
, &st
, RGW_GETATTR_FLAG_NONE
);
295 dout(15) << "rgw_getattr on " << object_name
<< " size = "
296 << st
.st_size
<< dendl
;
300 TEST(LibRGW
, WRITE_READ_VERIFY
)
302 if (do_bulk
&& do_put
) {
303 ZPageSet zp_set1
{iovcnt
}; // 1M random data in 16 64K pages
304 struct iovec
*iovs
= zp_set1
.get_iovs();
306 /* read after write POSIX-style */
307 size_t nbytes
, off
= 0;
308 for (int ix
= 0; ix
< 16; ++ix
, off
+= page_size
) {
309 struct iovec
*iov
= &iovs
[ix
];
310 int ret
= rgw_write(fs
, object_fh
, off
, page_size
, &nbytes
,
311 iov
->iov_base
, RGW_WRITE_FLAG_NONE
);
313 ASSERT_EQ(nbytes
, size_t(page_size
));
315 zp_set1
.reset_iovs();
319 /* "functions that call alloca are not inlined"
321 * http://gcc.gnu.org/ml/gcc-help/2004-04/msg00158.html
323 #define alloca_uio() \
325 int uiosz = sizeof(rgw_uio) + iovcnt*sizeof(rgw_vio); \
326 uio = static_cast<rgw_uio*>(alloca(uiosz)); \
327 memset(uio, 0, uiosz); \
328 uio->uio_vio = reinterpret_cast<rgw_vio*>(uio+sizeof(rgw_uio)); \
335 struct iovec
*iovs
= zp_set1
.get_iovs();
337 ASSERT_NE(uio
, nullptr);
339 for (int ix
= 0; ix
< iovcnt
; ++ix
) {
340 struct iovec
*iov
= &iovs
[ix
];
341 rgw_vio
*vio
= &(uio
->uio_vio
[ix
]);
342 vio
->vio_base
= iov
->iov_base
;
343 vio
->vio_len
= iov
->iov_len
;
344 vio
->vio_u1
= iov
; // private data
346 uio
->uio_cnt
= iovcnt
;
347 uio
->uio_offset
= iovcnt
* page_size
;
349 int ret
= rgw_writev(fs
, object_fh
, uio
, RGW_WRITE_FLAG_NONE
);
357 memset(uio
, 0, sizeof(rgw_uio
));
358 uio
->uio_offset
= 0; // ok, it was already 0
359 uio
->uio_resid
= UINT64_MAX
;
360 int ret
= rgw_readv(fs
, object_fh
, uio
, RGW_READ_FLAG_NONE
);
363 for (unsigned int ix
= 0; ix
< uio
->uio_cnt
; ++ix
) {
364 rgw_vio
*vio
= &(uio
->uio_vio
[ix
]);
366 buffer::create_static(vio
->vio_len
,
367 static_cast<char*>(vio
->vio_base
)));
371 ASSERT_EQ(uint32_t{bl
.length()}, uint32_t{iovcnt
*page_size
});
381 TEST(LibRGW
, READV_AFTER_WRITEV
)
384 if (do_readv
&& do_writev
&& do_verify
) {
385 ASSERT_TRUE(zp_set1
== uio
);
389 TEST(LibRGW
, DELETE_OBJECT
) {
391 int ret
= rgw_unlink(fs
, bucket_fh
, object_name
.c_str(),
392 RGW_UNLINK_FLAG_NONE
);
397 TEST(LibRGW
, DELETE_BUCKET
) {
399 int ret
= rgw_unlink(fs
, fs
->root_fh
, bucket_name
.c_str(),
400 RGW_UNLINK_FLAG_NONE
);
405 TEST(LibRGW
, CLEANUP
) {
408 ASSERT_NE(uio
->uio_rele
, nullptr);
410 uio
->uio_rele(uio
, RGW_UIO_NONE
);
415 ret
= rgw_close(fs
, object_fh
, RGW_CLOSE_FLAG_NONE
);
419 ret
= rgw_fh_rele(fs
, object_fh
, 0 /* flags */);
422 ret
= rgw_fh_rele(fs
, bucket_fh
, 0 /* flags */);
426 TEST(LibRGW
, UMOUNT
) {
430 int ret
= rgw_umount(fs
, RGW_UMOUNT_FLAG_NONE
);
434 TEST(LibRGW
, SHUTDOWN
) {
435 librgw_shutdown(rgw
);
438 int main(int argc
, char *argv
[])
442 vector
<const char*> args
;
444 argv_to_vec(argc
, const_cast<const char**>(argv
), args
);
447 v
= getenv("AWS_ACCESS_KEY_ID");
452 v
= getenv("AWS_SECRET_ACCESS_KEY");
457 for (auto arg_iter
= args
.begin(); arg_iter
!= args
.end();) {
458 if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--access",
461 } else if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--secret",
464 } else if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--uid",
467 } else if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--bn",
470 } else if (ceph_argparse_flag(args
, arg_iter
, "--get",
473 } else if (ceph_argparse_flag(args
, arg_iter
, "--stat",
476 } else if (ceph_argparse_flag(args
, arg_iter
, "--put",
479 } else if (ceph_argparse_flag(args
, arg_iter
, "--bulk",
482 } else if (ceph_argparse_flag(args
, arg_iter
, "--writev",
485 } else if (ceph_argparse_flag(args
, arg_iter
, "--readv",
488 } else if (ceph_argparse_flag(args
, arg_iter
, "--verify",
491 } else if (ceph_argparse_flag(args
, arg_iter
, "--delete",
494 } else if (ceph_argparse_flag(args
, arg_iter
, "--prelist",
497 } else if (ceph_argparse_flag(args
, arg_iter
, "--create",
500 } else if (ceph_argparse_flag(args
, arg_iter
, "--hexdump",
508 /* don't accidentally run as anonymous */
509 if ((access_key
== "") ||
510 (secret_key
== "")) {
511 std::cout
<< argv
[0] << " no AWS credentials, exiting" << std::endl
;
515 saved_args
.argc
= argc
;
516 saved_args
.argv
= argv
;
518 ::testing::InitGoogleTest(&argc
, argv
);
519 return RUN_ALL_TESTS();