bool server_base::load(const std::string& id) { const std::string path = build_local_path(argv_, "jubatus", id); std::ifstream ifs(path.c_str(), std::ios::binary); if (!ifs) { throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error("cannot open input file") << jubatus::exception::error_file_name(path) << jubatus::exception::error_errno(errno)); } try { LOG(INFO) << "starting load from " << path; std::vector<mixable0*> mixables = get_mixable_holder()->get_mixables(); for (size_t i = 0; i < mixables.size(); ++i) { mixables[i]->clear(); mixables[i]->load(ifs); } ifs.close(); LOG(INFO) << "loaded from " << path; } catch (const std::runtime_error& e) { ifs.close(); LOG(ERROR) << "failed to load: " << path; LOG(ERROR) << e.what(); throw; } return true; }
/*! \brief Open version file Open version file for specified current file. If the appropriate version already exists, it is opened. New version file is created otherwise. \param denty Dentry of the file \param vol Volume of the file */ int32_t version_create_file(internal_dentry dentry, volume vol) { string path; string verpath; int r; struct stat st; message(LOG_DEBUG, FACILITY_VERSION, "version_create_file\n"); build_local_path(&path, vol, dentry); version_generate_filename(path.str, &verpath); // is there any version we should use? r = lstat(verpath.str, &st); if (r == 0) { // open last version message(LOG_DEBUG, FACILITY_VERSION, "open last version\n"); dentry->fh->version_fd = open(verpath.str, O_RDWR); dentry->fh->version_path = xstrdup(verpath.str); } else { version_create_file_with_attr(verpath.str, dentry, vol, &path); version_apply_retention(dentry, vol); } free(verpath.str); free(path.str); version_load_interval_tree(dentry->fh); RETURN_INT(ZFS_OK); }
bs_file_t local_file_open(struct back_storage *storage,const char *path,int flags){ //HLOG_DEBUG("local -- enter func %s", __func__); char full_path[256]; build_local_path(full_path,storage->dir,storage->fs_name,path); //HLOG_DEBUG("full path %s", full_path); int fd=0; if(flags == BS_READONLY){ fd = open(full_path,O_RDONLY); }else if (flags == BS_WRITEABLE){ fd = open(full_path,O_APPEND|O_WRONLY,00700); }else{ //HLOG_DEBUG("open with error flags:%d",flags); return NULL; } if(fd == -1){ //HLOG_ERROR("open file error"); return NULL; } #if 0 bs_file_t file = (bs_file_t)g_malloc0(sizeof(int)); if (NULL == file) { g_message("%s - Allocate Error!\n", __func__); g_free(full_path); return NULL; } *(int*)file = fd; #endif bs_file_t file = (bs_file_t)GINT_TO_POINTER(fd); //HLOG_DEBUG("-----------fd is :%d,file:%p", fd,file); return file; }
int local_file_delete(struct back_storage *storage,const char* path){ //HLOG_DEBUG("local -- enter func %s", __func__); char full_path[256]; build_local_path(full_path,storage->dir,storage->fs_name,path); int ret = remove(full_path); //HLOG_DEBUG("local -- leave func %s", __func__); return ret; }
bool server_base::load(const std::string& id) { if (id == "") { throw JUBATUS_EXCEPTION( core::common::exception::runtime_error("empty id is not allowed")); } load_file_impl(*this, build_local_path(argv_, argv_.type, id), id); return true; }
std::map<std::string, std::string> server_base::save(const std::string& id) { if (id == "") { throw JUBATUS_EXCEPTION( core::common::exception::runtime_error("empty id is not allowed")); } const std::string path = build_local_path(argv_, argv_.type, id); LOG(INFO) << "starting save to " << path; fp_holder fp(fopen(path.c_str(), "wb")); if (fp.get() == 0) { throw JUBATUS_EXCEPTION( core::common::exception::runtime_error("cannot open output file") << core::common::exception::error_file_name(path) << core::common::exception::error_errno(errno)); } int fd = fileno(fp.get()); if (flock(fd, LOCK_EX | LOCK_NB) < 0) { // try exclusive lock throw JUBATUS_EXCEPTION(core::common::exception::runtime_error( "cannot get the lock of file; any RPC is saving to same file?") << core::common::exception::error_file_name(path) << core::common::exception::error_errno(errno)); } try { framework::save_server(fp.get(), *this, id); if (fp.close()) { goto write_failure; } } catch (const std::ios_base::failure&) { goto write_failure; } // putting error handling code here is to prevent skipping variable // initialization. skipping variable declaration causes undefined behavior. if (0) { write_failure: int tmperrno = errno; if (remove(path.c_str()) < 0) { LOG(WARNING) << "failed to cleanup dirty model file: " << path << ": " << jubatus::util::system::syscall::get_error_msg(errno); } throw JUBATUS_EXCEPTION( core::common::exception::runtime_error("cannot write output file") << core::common::exception::error_file_name(path) << core::common::exception::error_errno(tmperrno)); } update_saved_status(path); LOG(INFO) << "saved to " << path; std::map<std::string, std::string> ret; ret.insert(std::make_pair(get_server_identifier(argv_), path)); return ret; }
int local_file_is_exist(struct back_storage * storage,const char *path){ //HLOG_DEBUG("local -- enter func %s", __func__); char full_path[256]; build_local_path(full_path,storage->dir,storage->fs_name,path); //HLOG_DEBUG("path:%sfull path %s",path,full_path); if (!g_file_test(full_path,G_FILE_TEST_EXISTS)){ return -1; } //HLOG_DEBUG("local -- leave func %s", __func__); return 0; }
int local_file_mkdir(struct back_storage * storage,const char *dir_path){ //HLOG_DEBUG("local -- enter func %s", __func__); char full_path[256]; build_local_path(full_path,storage->dir,storage->fs_name,dir_path); // HLOG_DEBUG("full path is %s",full_path); if(0!=g_mkdir(full_path,00700)){ //HLOG_ERROR("g_mkdir error"); return -1; } //HLOG_DEBUG("local -- leave func %s", __func__); return 0; }
// this function only read dir, is compleet? int32_t version_apply_retention(internal_dentry dentry, volume vol) { string dpath; int32_t r; acquire_dentry(dentry->parent); build_local_path(&dpath, vol, dentry->parent); release_dentry(dentry->parent); ZFS_DIR * dirp = zfs_opendir(dpath.str); free(dpath.str); if (dirp == NULL) { RETURN_INT(errno); } /* Create a list of all versions for specified file. */ while (0) { zfs_dirent entry, *de; r = zfs_readdir_r(dirp, &entry, &de); if (r > 0) // zfs_readdir_r has failed { zfs_closedir(dirp); RETURN_INT(r); } else if (r == 0 && de == NULL) // end of list { break; } //DO NOTTING HILL PLEASE } zfs_closedir(dirp); /* Sort versions. */ /* Process from the oldest and check if it violates any maximum, while complying with minimums. Delete such versions. */ // xstrconcat(dpath.str, DIRECTORY_SEPARATOR, name, NULL); // unlink() RETURN_INT(ZFS_OK); }
bs_file_t local_file_create(struct back_storage *storage,const char *path){ //HLOG_DEBUG("local -- enter func %s", __func__); char full_path[256]; build_local_path(full_path,storage->dir,storage->fs_name,path); //HLOG_DEBUG("full path:%s", full_path); int fd = g_creat(full_path,00700); #if 0 bs_file_t file = (bs_file_t)g_malloc0(sizeof(int)); if (NULL == file) { g_message("%s - build local path error!\n", __func__); g_free(full_path); return NULL; } *(int*)file = fd; #endif bs_file_t file = (bs_file_t)GINT_TO_POINTER(fd); //HLOG_DEBUG("local -- leave func %s", __func__); return file; }
bs_file_info_t * local_file_info(struct back_storage *storage,const char* path){ //HLOG_DEBUG("local -- enter func %s", __func__); char full_path[256]; build_local_path(full_path,storage->dir,storage->fs_name,path); struct stat buf; int res=lstat(full_path,&buf); bs_file_info_t *info = NULL; if(res != 0){ //HLOG_ERROR("lstat error"); return NULL; } info = (bs_file_info_t*)g_malloc0(sizeof(bs_file_info_t)); strcpy((char *) info->name,path); info->is_dir = g_file_test (full_path, G_FILE_TEST_IS_DIR); info->size = buf.st_size; info->lmtime = buf.st_mtime; //HLOG_DEBUG("local -- leave func %s", __func__); return info; }
bs_file_info_t* local_list_dir(struct back_storage * storage,const char * dir_path,uint32_t* num_entries){ //HLOG_DEBUG("local -- enter func %s", __func__); char full_path[256]; build_local_path(full_path,storage->dir,storage->fs_name,dir_path); GDir * dir = g_dir_open(full_path,0,NULL); if(dir==NULL){ //HLOG_ERROR("g_dir_open error"); return NULL; } struct stat buf; bs_file_info_t * infos = (bs_file_info_t*)g_malloc0(sizeof(bs_file_info_t)*8192); if (NULL == infos) { //HLOG_ERROR("build local path error!"); return NULL; } const gchar *filename; bs_file_info_t *info = infos; int idx=0; while((filename = g_dir_read_name(dir)) != NULL) { gchar *file_path = g_build_filename(full_path,filename,NULL); int res=lstat(file_path,&buf); if (0 != res) { g_free(file_path); g_free(infos); //g_dir_close(dir); HLOG_ERROR("lstat error"); return NULL; } strcpy((char *) info->name,filename); info->is_dir = g_file_test(file_path, G_FILE_TEST_IS_DIR); info->size = buf.st_size; info->lmtime = buf.st_mtime; info++; idx++; } *num_entries = idx; g_dir_close(dir); //HLOG_DEBUG("local -- leave func %s", __func__); return infos; }
bool server_base::save(const std::string& id) { const std::string path = build_local_path(argv_, "jubatus", id); std::ofstream ofs(path.c_str(), std::ios::trunc | std::ios::binary); if (!ofs) { throw JUBATUS_EXCEPTION( core::common::exception::runtime_error("cannot open output file") << core::common::exception::error_file_name(path) << core::common::exception::error_errno(errno)); } try { LOG(INFO) << "starting save to " << path; framework::save_server(ofs, *this, id); ofs.close(); LOG(INFO) << "saved to " << path; } catch (const std::runtime_error& e) { LOG(ERROR) << "failed to save: " << path; LOG(ERROR) << e.what(); throw; } return true; }
/*! \brief Delete version file Delete version file and its respective interval file. \param dir Dentry of the directory the file is in \param vol Volume the file is on \param name Name of the file */ bool version_retent_file(internal_dentry dir, volume vol, char *name) { string path; char *dst; acquire_dentry(dir); zfsd_mutex_lock(&vol->mutex); zfsd_mutex_lock(&fh_mutex); build_local_path(&path, vol, dir); release_dentry(dir); zfsd_mutex_unlock(&vol->mutex); zfsd_mutex_unlock(&fh_mutex); dst = xstrconcat(path.str, DIRECTORY_SEPARATOR, name, NULL); version_unlink_version_file(dst); free(dst); // file is deleted immediately return true; }
bool server_base::load(const std::string& id) { load_file_impl(*this, build_local_path(argv_, "jubatus", id), id); return true; }
/*! \brief Create list of intervals for a file version Create list of intervals together with version files these intervals are stored in that create the whole content of a file version. List is created from interval files during file open. Result is stored in the internal file handle. \param dentry Dentry of the file \param vol Volume the file in on */ int32_t version_build_intervals(internal_dentry dentry, volume vol) { time_t stamp; varray v; char *sname; char *p; version_item *list; unsigned int n, m; unsigned int i, j; string dpath; bool r; r = version_load_interval_tree(dentry->fh); if (!r) RETURN_INT(ZFS_OK); // parse version file name sname = xstrdup(dentry->name.str); p = strchr(sname, VERSION_NAME_SPECIFIER_C); if (!p) { free(sname); RETURN_INT(ENOENT); } *p = '\0'; stamp = atoi(p + 1); // get list of version files that newer than timestamp zfsd_mutex_lock(&dentry->parent->fh->mutex); build_local_path(&dpath, vol, dentry->parent); zfsd_mutex_unlock(&dentry->parent->fh->mutex); varray_create(&v, sizeof(version_item), 1); version_browse_dir(dpath.str, sname, &stamp, NULL, &v); free(sname); n = VARRAY_USED(v); list = (version_item *) xmalloc(n * sizeof(version_item)); for (i = 0; i < n; i++) { list[i] = VARRAY_ACCESS(v, i, version_item); list[i].path = xstrconcat(dpath.str, DIRECTORY_SEPARATOR, list[i].name, NULL); } varray_destroy(&v); free(dpath.str); // sort the list qsort(list, n, sizeof(version_item), comp_version_items); // get intervals for version files in the list for (i = 0; i < n; i++) { // read int fd; char *ival; if (!list[i].path) continue; ival = xstrconcat(list[i].path, VERSION_INTERVAL_FILE_ADD, NULL); fd = open(ival, O_RDONLY); free(ival); if (fd > 0) { // read interval file struct stat st; list[i].intervals = interval_tree_create(1, NULL); if (fstat(fd, &st) < 0) { CLEAR_VERSION_ITEM(list[i]); } else if (!interval_tree_read (list[i].intervals, fd, st.st_size / sizeof(interval))) CLEAR_VERSION_ITEM(list[i]); close(fd); } else if (errno == ENOENT) { // complete file i++; break; } // invalid version file else CLEAR_VERSION_ITEM(list[i]); } // delete all redundant intervals m = i; for (j = i + 1; j < n; j++) CLEAR_VERSION_ITEM(list[j]); dentry->fh->version_list = list; dentry->fh->version_list_length = m; RETURN_INT(ZFS_OK); }