From 93552e4199f2a07e881ea4532582fbc0d691e77f Mon Sep 17 00:00:00 2001 From: Greg Farnum Date: Fri, 21 Aug 2009 09:31:50 -0700 Subject: [PATCH] libceph: Change the C++-only functions to be C-compatible. Hypertable: Change to use ceph_getdnames instead of getdir. Hadoop: Minor updates to use the new C-style functions in libceph. --- src/client/hadoop/CephFSInterface.cc | 42 ++++++++++++++++------ src/client/hypertable/CephBroker.cc | 32 +++++++++++++---- src/client/libceph.cc | 54 +++++++++++++++++++++------- src/client/libceph.h | 46 +++++++++++++----------- 4 files changed, 124 insertions(+), 50 deletions(-) diff --git a/src/client/hadoop/CephFSInterface.cc b/src/client/hadoop/CephFSInterface.cc index e6644cb14371c..f41b1d1750fd5 100644 --- a/src/client/hadoop/CephFSInterface.cc +++ b/src/client/hadoop/CephFSInterface.cc @@ -9,6 +9,8 @@ #include using namespace std; +const static int IP_ADDR_LENGTH = 24;//a buffer size; may want to up for IPv6. +static int path_size; /* * Class: org_apache_hadoop_fs_ceph_CephFileSystem * Method: ceph_initializeClient @@ -32,6 +34,7 @@ JNIEXPORT jboolean JNICALL Java_org_apache_hadoop_fs_ceph_CephFileSystem_ceph_1i env->ReleaseStringUTFChars(j_debug_level, c_debug_level); return false; } + path_size = 64; //reasonable starting point? //construct an arguments array const char *argv[10]; int argc = 0; @@ -61,9 +64,17 @@ JNIEXPORT jstring JNICALL Java_org_apache_hadoop_fs_ceph_CephFileSystem_ceph_1ge { dout(10) << "CephFSInterface: In getcwd" << dendl; - string path; - ceph_getcwd(path); - return env->NewStringUTF(path.c_str()); + char *path = new char[path_size]; + int r = ceph_getcwd(path, path_size); + if (r==-ERANGE) { //path is too short + path_size = ceph_getcwd(path, 0) * 1.2; //leave some extra + delete path; + path = new char[path_size]; + ceph_getcwd(path, path_size); + } + jstring j_path = env->NewStringUTF(path); + delete path; + return j_path; } /* @@ -463,7 +474,7 @@ JNIEXPORT jboolean JNICALL Java_org_apache_hadoop_fs_ceph_CephFileSystem_ceph_1k JNIEXPORT jboolean JNICALL Java_org_apache_hadoop_fs_ceph_CephFileSystem_ceph_1stat (JNIEnv * env, jobject obj, jstring j_path, jobject j_stat) { //setup variables - struct Client::stat_precise st; + struct stat_precise st; const char* c_path = env->GetStringUTFChars(j_path, 0); if (c_path == NULL) return false; @@ -482,7 +493,7 @@ JNIEXPORT jboolean JNICALL Java_org_apache_hadoop_fs_ceph_CephFileSystem_ceph_1s jfieldID c_mode_id = env->GetFieldID(cls, "mode", "I"); if (c_mode_id == NULL) return false; //do actual lstat - int r = ceph_lstat(c_path, &st); + int r = ceph_lstat_precise(c_path, &st); env->ReleaseStringUTFChars(j_path, c_path); if (r < 0) return false; //fail out; file DNE or Ceph broke @@ -559,10 +570,21 @@ JNIEXPORT jint JNICALL Java_org_apache_hadoop_fs_ceph_CephFileSystem_ceph_1repli JNIEXPORT jstring JNICALL Java_org_apache_hadoop_fs_ceph_CephFileSystem_ceph_1hosts (JNIEnv * env, jobject obj, jint j_fh, jlong j_offset) { //get the address - string address; - ceph_get_file_stripe_address(j_fh, j_offset, address); + char *address = new char[IP_ADDR_LENGTH]; + int r = ceph_get_file_stripe_address(j_fh, j_offset, address, IP_ADDR_LENGTH); + if (r == -ERANGE) {//buffer's too small + delete address; + int size = ceph_get_file_stripe_address(j_fh, j_offset, address, 0); + address = new char[size]; + r = ceph_get_file_stripe_address(j_fh, j_offset, address, size); + } + if (r != 0) { //some rather worse problem + if (r == -EINVAL) return NULL; //ceph thinks there are no OSDs + } //make java String of address - return env->NewStringUTF(address.c_str()); + jstring j_addr = env->NewStringUTF(address); + delete address; + return j_addr; } /* @@ -581,12 +603,12 @@ JNIEXPORT jint JNICALL Java_org_apache_hadoop_fs_ceph_CephFileSystem_ceph_1setTi if (atime!=-1) mask |= CEPH_SETATTR_ATIME; //build a struct stat and fill it in! //remember to convert from millis to seconds and microseconds - Client::stat_precise attr; + stat_precise attr; attr.st_mtime_sec = mtime / 1000; attr.st_mtime_micro = (mtime % 1000) * 1000; attr.st_atime_sec = atime / 1000; attr.st_atime_micro = (atime % 1000) * 1000; - return ceph_setattr(c_path, &attr, mask); + return ceph_setattr_precise(c_path, &attr, mask); } /* diff --git a/src/client/hypertable/CephBroker.cc b/src/client/hypertable/CephBroker.cc index 1b29131ad030a..ce2477e390152 100644 --- a/src/client/hypertable/CephBroker.cc +++ b/src/client/hypertable/CephBroker.cc @@ -393,15 +393,33 @@ void CephBroker::readdir(ResponseCallbackReaddir *cb, const char *dname) { HT_DEBUGF("Readdir dir='%s'", dname); - //get from ceph in list + //get from ceph in a buffer make_abs_path(dname, absdir); - std::list dir_con; - ceph_getdir(absdir.c_str(), dir_con); - //convert to vector - for (std::list::iterator i = dir_con.begin(); i!=dir_con.end(); ++i) { - if (!(i->compare(".")==0 || i->compare("..")==0)) - listing.push_back(*i); + DIR *dirp; + ceph_opendir(absdir.c_str(), &dirp); + int r; + int buflen = 100; //good default? + char *buf = new char[buflen]; + string *ent; + int bufpos; + while (1) { + r = ceph_getdnames(dirp, buf, buflen); + if (r==-ERANGE) { //expand the buffer + delete buf; + buflen *= 2; + buf = new char[buflen]; + continue; + } + if (r==0) break; + //if we make it here, we got at least one name, maybe more + bufpos = 0; + while (bufpossize()+1; + delete ent; + } } cb->response(listing); } diff --git a/src/client/libceph.cc b/src/client/libceph.cc index 5b24249f96a9f..dfc361926ab39 100644 --- a/src/client/libceph.cc +++ b/src/client/libceph.cc @@ -8,6 +8,7 @@ #include "messages/MMonMap.h" #include "common/common_init.h" #include "msg/SimpleMessenger.h" +#include "Client.h" /* ************* ************* ************* ************* * C interface @@ -83,7 +84,21 @@ extern "C" int ceph_statfs(const char *path, struct statvfs *stbuf) { return client->statfs(path, stbuf); } - + +extern "C" int ceph_getcwd(char *buf, int buflen) +{ + string cwd; + client->getcwd(cwd); + int size = cwd.size()+1; //need space for null character + if (size > buflen) { + if (buflen == 0) return size; + else return -ERANGE; + } + size = cwd.copy(buf, size); + buf[size] = '\0'; //fill in null character + return 0; +} + extern "C" int ceph_chdir (const char *s) { return client->chdir(s); @@ -185,19 +200,25 @@ extern "C" int ceph_symlink(const char *existing, const char *newname) } // inode stuff -extern "C" int ceph_lstat(const char *path, struct stat *stbuf, struct frag_info_t *dirstat) +extern "C" int ceph_lstat(const char *path, struct stat *stbuf) { - return client->lstat(path, stbuf, dirstat); + return client->lstat(path, stbuf); } -int ceph_lstat(const char *path, Client::stat_precise *stbuf, frag_info_t *dirstat) +extern "C" int ceph_lstat_precise(const char *path, stat_precise *stbuf) { - return client->lstat_precise(path, stbuf, dirstat); + return client->lstat_precise(path, (Client::stat_precise*)stbuf); } -extern "C" int ceph_setattr(const char *relpath, Client::stat_precise *attr, int mask) +extern "C" int ceph_setattr(const char *relpath, struct stat *attr, int mask) { - return client->setattr(relpath, attr, mask); + Client::stat_precise p_attr = Client::stat_precise(*attr); + return client->setattr(relpath, &p_attr, mask); +} + +extern "C" int ceph_setattr_precise(const char *relpath, + struct stat_precise *attr, int mask) { + return client->setattr(relpath, (Client::stat_precise*)attr, mask); } extern "C" int ceph_chmod(const char *path, mode_t mode) @@ -282,11 +303,18 @@ extern "C" int ceph_get_file_replication(const char *path) { return rep; } -int ceph_get_file_stripe_address(int fh, loff_t offset, std::string& address) { - return client->get_file_stripe_address(fh, offset, address); -} - -int ceph_getdir(const char *relpath, std::list& names) +int ceph_get_file_stripe_address(int fh, loff_t offset, char *buf, int buflen) { - return client->getdir(relpath, names); + string address; + int r = client->get_file_stripe_address(fh, offset, address); + if (r != 0) return r; //at time of writing, method ONLY returns + // 0 or -EINVAL if there are no known osds + int len = address.size()+1; + if (len > buflen) { + if (buflen == 0) return len; + else return -ERANGE; + } + len = address.copy(buf, len, 0); + buf[len] = '\0'; // write a null char to terminate c-style string + return 0; } diff --git a/src/client/libceph.h b/src/client/libceph.h index bd010fbdc7ced..7c4b2bbfc4570 100644 --- a/src/client/libceph.h +++ b/src/client/libceph.h @@ -9,14 +9,25 @@ #include #include -#ifdef __cplusplus -#include -#include -#include "Client.h" -extern "C" { -#endif - - struct frag_info_t; +struct frag_info_t; +struct stat_precise { + ino_t st_ino; + dev_t st_dev; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + blksize_t st_blksize; + blkcnt_t st_blocks; + time_t st_atime_sec; + time_t st_atime_micro; + time_t st_mtime_sec; + time_t st_mtime_micro; + time_t st_ctime_sec; + time_t st_ctime_micro; +}; int ceph_initialize(int argc, const char **argv); void ceph_deinitialize(); @@ -25,7 +36,8 @@ int ceph_umount(); int ceph_statfs(const char *path, struct statvfs *stbuf); -int ceph_chdir (const char *s); +int ceph_getcwd(char *buf, int buflen); +int ceph_chdir(const char *s); int ceph_opendir(const char *name, DIR **dirpp); int ceph_closedir(DIR *dirp); @@ -51,9 +63,11 @@ int ceph_readlink(const char *path, char *buf, loff_t size); int ceph_symlink(const char *existing, const char *newname); // inode stuff -int ceph_lstat(const char *path, struct stat *stbuf, frag_info_t *dirstat=0); +int ceph_lstat(const char *path, struct stat *stbuf); +int ceph_lstat_precise(const char *path, struct stat_precise *stbuf); -int ceph_setattr(const char *relpath, Client::stat_precise *attr, int mask); +int ceph_setattr(const char *relpath, struct stat *attr, int mask); +int ceph_setattr_precise (const char *relpath, struct stat_precise *stbuf, int mask); int ceph_chmod(const char *path, mode_t mode); int ceph_chown(const char *path, uid_t uid, gid_t gid); int ceph_utime(const char *path, struct utimbuf *buf); @@ -73,14 +87,6 @@ int ceph_fstat(int fd, struct stat *stbuf); int ceph_sync_fs(); int ceph_get_file_stripe_unit(int fh); int ceph_get_file_replication(const char *path); -#ifdef __cplusplus -} -//not for C, sorry! -int ceph_getdir(const char *relpath, std::list& names); -void ceph_getcwd(std::string& cwd); -int ceph_get_file_stripe_address(int fd, loff_t offset, std::string& address); -int ceph_lstat(const char *path, Client::stat_precise *stbuf, frag_info_t *dirstat=0); - -#endif +int ceph_get_file_stripe_address(int fd, loff_t offset, char *buf, int buflen); #endif -- 2.39.5