]>
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
36 librgw_t rgw
= nullptr;
37 string
uid("testuser");
38 string
access_key("");
39 string
secret_key("");
40 struct rgw_fs
*fs
= nullptr;
42 bool do_pre_list
= false;
45 bool do_writev
= false;
46 bool do_readv
= false;
47 bool do_verify
= false;
49 bool do_create
= false;
50 bool do_delete
= false;
51 bool do_stat
= false; // stat objects (not buckets)
52 bool do_hexdump
= false;
54 bool object_open
= false;
56 uint32_t owner_uid
= 867;
57 uint32_t owner_gid
= 5309;
58 uint32_t create_mask
= RGW_SETATTR_UID
| RGW_SETATTR_GID
| RGW_SETATTR_MODE
;
60 string bucket_name
= "blastoff";
61 string object_name
= "jocaml";
63 struct rgw_file_handle
*bucket_fh
= nullptr;
64 struct rgw_file_handle
*object_fh
= nullptr;
66 typedef std::tuple
<string
,uint64_t, struct rgw_file_handle
*> fid_type
;
67 std::vector
<fid_type
> fids
;
69 std::uniform_int_distribution
<uint8_t> uint_dist
;
72 constexpr int iovcnt
= 16;
73 constexpr int page_size
= 65536;
74 constexpr int seed
= 8675309;
84 std::vector
<ZPage
*> pages
;
87 explicit ZPageSet(int n
) {
89 iovs
= (struct iovec
*) calloc(n
, sizeof(struct iovec
));
90 for (int page_ix
= 0; page_ix
< n
; ++page_ix
) {
91 ZPage
* p
= new ZPage();
92 for (int data_ix
= 0; data_ix
< page_size
; ++data_ix
) {
93 p
->data
[data_ix
] = uint_dist(rng
);
95 p
->cksum
= XXH64(p
->data
, page_size
, seed
);
96 pages
.emplace_back(p
);
98 struct iovec
* iov
= &iovs
[page_ix
];
99 iov
->iov_base
= p
->data
;
100 iov
->iov_len
= page_size
;
104 int size() { return pages
.size(); }
106 struct iovec
* get_iovs() { return iovs
; }
108 bool operator==(const ZPageSet
& rhs
) {
110 for (int page_ix
= 0; page_ix
< n
; ++page_ix
) {
111 ZPage
* p1
= pages
[page_ix
];
112 ZPage
* p2
= rhs
.pages
[page_ix
];
113 if (p1
->cksum
!= p2
->cksum
)
119 bool operator==(const rgw_uio
* uio
) {
121 int vix
= 0, off
= 0;
122 rgw_vio
* vio
= &uio
->uio_vio
[vix
];
123 int vio_len
= vio
->vio_len
;
126 for (int ix
= 0; ix
< iovcnt
; ++ix
) {
127 ZPage
* p1
= pages
[ix
];
128 data
= static_cast<char*>(vio
->vio_base
) + off
;
129 cksum
= XXH64(data
, page_size
, seed
);
131 if (p1
->cksum
!= cksum
) {
132 int r
= memcmp(data
, p1
->data
, page_size
);
133 std::cout
<< "problem at ix " << ix
<< " r " << r
<< std::endl
;
138 if (off
>= vio_len
) {
139 vio
= &uio
->uio_vio
[++vix
];
140 vio_len
= vio
->vio_len
;
149 for (int page_ix
= 0; page_ix
< n
; ++page_ix
) {
150 ZPage
* p
= pages
[page_ix
];
151 p
->cksum
= XXH64(p
->data
, page_size
, seed
);
155 void reset_iovs() { // VOP_READ and VOP_WRITE update
157 for (int page_ix
= 0; page_ix
< n
; ++page_ix
) {
158 ZPage
* p
= pages
[page_ix
];
159 struct iovec
* iov
= &iovs
[page_ix
];
160 iov
->iov_base
= p
->data
;
161 iov
->iov_len
= page_size
;
166 for (unsigned int ix
= 0; ix
< pages
.size(); ++ix
)
173 ZPageSet zp_set1
{iovcnt
}; // 1M random data in 16 64K pages
182 int ret
= librgw_create(&rgw
, saved_args
.argc
, saved_args
.argv
);
184 ASSERT_NE(rgw
, nullptr);
187 TEST(LibRGW
, MOUNT
) {
188 int ret
= rgw_mount2(rgw
, uid
.c_str(), access_key
.c_str(), secret_key
.c_str(),
189 "/", &fs
, RGW_MOUNT_FLAG_NONE
);
191 ASSERT_NE(fs
, nullptr);
194 TEST(LibRGW
, CREATE_BUCKET
) {
197 struct rgw_file_handle
*fh
;
199 st
.st_uid
= owner_uid
;
200 st
.st_gid
= owner_gid
;
203 int ret
= rgw_mkdir(fs
, fs
->root_fh
, bucket_name
.c_str(), &st
, create_mask
,
204 &fh
, RGW_MKDIR_FLAG_NONE
);
209 TEST(LibRGW
, LOOKUP_BUCKET
) {
210 int ret
= rgw_lookup(fs
, fs
->root_fh
, bucket_name
.c_str(), &bucket_fh
,
211 nullptr, 0, RGW_LOOKUP_FLAG_NONE
);
216 static int r2_cb(const char* name
, void *arg
, uint64_t offset
,
217 struct stat
*st
, uint32_t st_mask
,
219 // don't need arg--it would point to fids
220 fids
.push_back(fid_type(name
, offset
, nullptr));
221 return true; /* XXX ? */
225 TEST(LibRGW
, LIST_OBJECTS
) {
227 /* list objects via readdir, bucketwise */
230 ldout(g_ceph_context
, 0) << __func__
<< " readdir on bucket "
231 << bucket_name
<< dendl
;
234 int ret
= rgw_readdir(fs
, bucket_fh
, &offset
, r2_cb
, &fids
,
235 &eof
, RGW_READDIR_FLAG_NONE
);
236 for (auto& fid
: fids
) {
237 std::cout
<< "fname: " << get
<0>(fid
) << " fid: " << get
<1>(fid
)
244 TEST(LibRGW
, LOOKUP_OBJECT
) {
245 if (do_get
|| do_stat
|| do_put
|| do_bulk
|| do_readv
|| do_writev
) {
246 int ret
= rgw_lookup(fs
, bucket_fh
, object_name
.c_str(), &object_fh
,
247 nullptr, 0, RGW_LOOKUP_FLAG_CREATE
);
252 TEST(LibRGW
, OBJ_OPEN
) {
253 if (do_get
|| do_put
|| do_readv
|| do_writev
) {
254 int ret
= rgw_open(fs
, object_fh
, 0 /* posix flags */, 0 /* flags */);
260 TEST(LibRGW
, PUT_OBJECT
) {
263 string data
= "hi mom"; // fix this
264 int ret
= rgw_write(fs
, object_fh
, 0, data
.length(), &nbytes
,
265 (void*) data
.c_str(), RGW_WRITE_FLAG_NONE
);
267 ASSERT_EQ(nbytes
, data
.length());
268 /* commit write transaction */
269 ret
= rgw_close(fs
, object_fh
, 0 /* flags */);
274 TEST(LibRGW
, GET_OBJECT
) {
277 memset(sbuf
, 0, 512);
279 int ret
= rgw_read(fs
, object_fh
, 0 /* off */, 512 /* len */, &nread
, sbuf
,
283 bl
.push_back(buffer::create_static(nread
, sbuf
));
292 TEST(LibRGW
, STAT_OBJECT
) {
295 int ret
= rgw_getattr(fs
, object_fh
, &st
, RGW_GETATTR_FLAG_NONE
);
297 dout(15) << "rgw_getattr on " << object_name
<< " size = "
298 << st
.st_size
<< dendl
;
302 TEST(LibRGW
, WRITE_READ_VERIFY
)
304 if (do_bulk
&& do_put
) {
305 ZPageSet zp_set1
{iovcnt
}; // 1M random data in 16 64K pages
306 struct iovec
*iovs
= zp_set1
.get_iovs();
308 /* read after write POSIX-style */
309 size_t nbytes
, off
= 0;
310 for (int ix
= 0; ix
< 16; ++ix
, off
+= page_size
) {
311 struct iovec
*iov
= &iovs
[ix
];
312 int ret
= rgw_write(fs
, object_fh
, off
, page_size
, &nbytes
,
313 iov
->iov_base
, RGW_WRITE_FLAG_NONE
);
315 ASSERT_EQ(nbytes
, size_t(page_size
));
317 zp_set1
.reset_iovs();
321 /* "functions that call alloca are not inlined"
323 * http://gcc.gnu.org/ml/gcc-help/2004-04/msg00158.html
325 #define alloca_uio() \
327 int uiosz = sizeof(rgw_uio) + iovcnt*sizeof(rgw_vio); \
328 uio = static_cast<rgw_uio*>(alloca(uiosz)); \
329 memset(uio, 0, uiosz); \
330 uio->uio_vio = reinterpret_cast<rgw_vio*>(uio+sizeof(rgw_uio)); \
337 struct iovec
*iovs
= zp_set1
.get_iovs();
339 ASSERT_NE(uio
, nullptr);
341 for (int ix
= 0; ix
< iovcnt
; ++ix
) {
342 struct iovec
*iov
= &iovs
[ix
];
343 rgw_vio
*vio
= &(uio
->uio_vio
[ix
]);
344 vio
->vio_base
= iov
->iov_base
;
345 vio
->vio_len
= iov
->iov_len
;
346 vio
->vio_u1
= iov
; // private data
348 uio
->uio_cnt
= iovcnt
;
349 uio
->uio_offset
= iovcnt
* page_size
;
351 int ret
= rgw_writev(fs
, object_fh
, uio
, RGW_WRITE_FLAG_NONE
);
359 memset(uio
, 0, sizeof(rgw_uio
));
360 uio
->uio_offset
= 0; // ok, it was already 0
361 uio
->uio_resid
= UINT64_MAX
;
362 int ret
= rgw_readv(fs
, object_fh
, uio
, RGW_READ_FLAG_NONE
);
365 for (unsigned int ix
= 0; ix
< uio
->uio_cnt
; ++ix
) {
366 rgw_vio
*vio
= &(uio
->uio_vio
[ix
]);
368 buffer::create_static(vio
->vio_len
,
369 static_cast<char*>(vio
->vio_base
)));
373 ASSERT_EQ(uint32_t{bl
.length()}, uint32_t{iovcnt
*page_size
});
383 TEST(LibRGW
, READV_AFTER_WRITEV
)
386 if (do_readv
&& do_writev
&& do_verify
) {
387 ASSERT_TRUE(zp_set1
== uio
);
391 TEST(LibRGW
, DELETE_OBJECT
) {
393 int ret
= rgw_unlink(fs
, bucket_fh
, object_name
.c_str(),
394 RGW_UNLINK_FLAG_NONE
);
399 TEST(LibRGW
, DELETE_BUCKET
) {
401 int ret
= rgw_unlink(fs
, fs
->root_fh
, bucket_name
.c_str(),
402 RGW_UNLINK_FLAG_NONE
);
407 TEST(LibRGW
, CLEANUP
) {
410 ASSERT_NE(uio
->uio_rele
, nullptr);
412 uio
->uio_rele(uio
, RGW_UIO_NONE
);
417 ret
= rgw_close(fs
, object_fh
, RGW_CLOSE_FLAG_NONE
);
421 ret
= rgw_fh_rele(fs
, object_fh
, 0 /* flags */);
424 ret
= rgw_fh_rele(fs
, bucket_fh
, 0 /* flags */);
428 TEST(LibRGW
, UMOUNT
) {
432 int ret
= rgw_umount(fs
, RGW_UMOUNT_FLAG_NONE
);
436 TEST(LibRGW
, SHUTDOWN
) {
437 librgw_shutdown(rgw
);
440 int main(int argc
, char *argv
[])
442 auto args
= argv_to_vec(argc
, argv
);
445 char* v
= getenv("AWS_ACCESS_KEY_ID");
450 v
= getenv("AWS_SECRET_ACCESS_KEY");
456 for (auto arg_iter
= args
.begin(); arg_iter
!= args
.end();) {
457 if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--access",
460 } else if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--secret",
463 } else if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--uid",
466 } else if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--bn",
469 } else if (ceph_argparse_flag(args
, arg_iter
, "--get",
472 } else if (ceph_argparse_flag(args
, arg_iter
, "--stat",
475 } else if (ceph_argparse_flag(args
, arg_iter
, "--put",
478 } else if (ceph_argparse_flag(args
, arg_iter
, "--bulk",
481 } else if (ceph_argparse_flag(args
, arg_iter
, "--writev",
484 } else if (ceph_argparse_flag(args
, arg_iter
, "--readv",
487 } else if (ceph_argparse_flag(args
, arg_iter
, "--verify",
490 } else if (ceph_argparse_flag(args
, arg_iter
, "--delete",
493 } else if (ceph_argparse_flag(args
, arg_iter
, "--prelist",
496 } else if (ceph_argparse_flag(args
, arg_iter
, "--create",
499 } else if (ceph_argparse_flag(args
, arg_iter
, "--hexdump",
507 /* don't accidentally run as anonymous */
508 if ((access_key
== "") ||
509 (secret_key
== "")) {
510 std::cout
<< argv
[0] << " no AWS credentials, exiting" << std::endl
;
514 saved_args
.argc
= argc
;
515 saved_args
.argv
= argv
;
517 ::testing::InitGoogleTest(&argc
, argv
);
518 return RUN_ALL_TESTS();