コード例 #1
0
ファイル: OssFS.cpp プロジェクト: dluobo/cloudfs
int OssFS::getattr(const char *path, struct stat *statbuf) 
{
	log_debug("path:%s", path);	
	int res = 0;
	
	OssObject *obj = this->find_file(path);

	log_debug("immediate sync:%zd, obj:%p", AliConf::IMMEDIATE_SYNC, obj);
	if (obj != NULL) 
	{
		memset(statbuf, 0, sizeof(struct stat));
		if (obj->get_stats()->type == OSS_DIR)
			statbuf->st_mode = S_IFDIR | obj->get_stats()->mode;
		else if (obj->get_stats()->type == OSS_REGULAR)
			statbuf->st_mode = S_IFREG | obj->get_stats()->mode;
		else if (obj->get_stats()->type == OSS_LINK)
			statbuf->st_mode = S_IFLNK | obj->get_stats()->mode;
		statbuf->st_nlink = 2;
		statbuf->st_size = obj->get_stats()->size;
		statbuf->st_atim.tv_sec = obj->get_stats()->mtime;
		statbuf->st_atim.tv_nsec = 0;
		statbuf->st_mtim.tv_sec = obj->get_stats()->mtime;
		statbuf->st_mtim.tv_nsec = 0;
		statbuf->st_ctim.tv_sec = obj->get_stats()->mtime;
		statbuf->st_ctim.tv_nsec = 0;
		statbuf->st_uid = getuid();
		statbuf->st_gid = getgid();
	} else
		res = -ENOENT;
	return res;
}
コード例 #2
0
ファイル: OssFS.cpp プロジェクト: dluobo/cloudfs
int OssFS::mkdir(const char *path, mode_t mode) 
{
	log_debug("path:%s", path);
	std::vector<OssStats *> dir_stats;
	string tmp_str = path;
    if (tmp_str.at(tmp_str.length() - 1) != '/') {
        tmp_str.append("/");
    }

	OssDirObject* parentObj = (OssDirObject *)get_parent(path);
	if (NULL == parentObj)
	{
		log_error("path [%s]", path);
		return -ENOENT;
	}
	OssObject *obj = this->add_file(tmp_str.c_str(), dir_stats, OSS_DIR);
	if (NULL == obj)
	{
		return -ENOENT;
	}

	OSS_FILE_META meta;
	obj->get_stats()->to_meta(meta);
    m_oss->put_object_data(AliConf::BUCKET.c_str(), obj->get_path_name(), meta);


	return 0;
}
コード例 #3
0
ファイル: OssFS.cpp プロジェクト: dluobo/cloudfs
int OssFS::readlink(const char *path, char *link, size_t size) {
	log_debug("path:%s, link:%s", path, link);
	OssObject *obj = find_certain_path(path);	
	if (obj == NULL || obj->get_stats()->type != OSS_LINK) {
		return -ENOENT;
	}
	OssSymObject *sym = (OssSymObject *) obj;
	sym->get_link_obj(link, size);
	return 0;
}
コード例 #4
0
ファイル: OssFS.cpp プロジェクト: dluobo/cloudfs
int OssFS::truncate(const char *path, off_t newSize) {
	log_debug("path:%s", path);

	OssObject *obj = this->find_certain_path(path);

	if (obj == NULL) {
		return -ENOENT;	
	}

	//我们在这里先判断这个文件类型, cloudfs目前只支持普通文件的truncate
	if (obj->get_stats()->type != OSS_REGULAR)
	{
		log_debug("Error Truncate type");
		return -1;
	}

	OssGroupObject *pTmpObj = (OssGroupObject *)obj;
	return pTmpObj->truncate(newSize);

}
コード例 #5
0
ファイル: OssFS.cpp プロジェクト: dluobo/cloudfs
// 下面做的工作就是为每个文件实例化一个相应的类
// 目录文件实例化为 OssDirObject 
int OssFS::load_files(vector<oss_object_desc_t>& objects, bool initial_load, size_t sync_flag)
{
	std::vector<OssStats *> group_stats;
	vector<oss_object_desc_t>::iterator iter;
	OSS_FILE_META meta;
	OssObject *tmpObj = NULL;	

	for (iter = objects.begin(); iter != objects.end(); iter++) 
	{
		meta.clear();
		convert_object_to_meta(&(*iter), meta);

		//先检查本该文件是否已经存在, 如果已经存在则不需要加载
		//第一次的全量加载不进行本步骤的检查, 提高加载速度
		if (!initial_load)
		{
			tmpObj = get_file(iter->name.c_str());
			
			if (tmpObj != NULL)
			{

				//先判断该文件是否已经被打开读写, 如果已经被打开, 则保持该文件状态不变化
				if (tmpObj->is_open())
				{
					log_error("file [%s] is opened, ignore it", iter->name.c_str());
					if (sync_flag != 0)
					{
						tmpObj->set_sync_flag(sync_flag);
					}					
					continue;
				}
			
				/* obj可能是目录, 普通文件, 链接文件的任意一种
				   目录: 设置同步标识, 直接跳过
				   普通文件与链接文件: 如果文件文件大小不一致, 直接删除cloudfs中的对象, 重新创建一个新的对象
				*/				
				OssStats *pTmpStat = const_cast<OssStats *>(tmpObj->get_stats());
				if (pTmpStat->type == OSS_DIR)
				{		
						if (sync_flag != 0)
						{
							tmpObj->set_sync_flag(sync_flag);
						}	
						continue;
					
				}				
				else if ((pTmpStat->type == OSS_REGULAR) || (pTmpStat->type == OSS_LINK))
				{														
					//后台文件与前台文件一致, 直接continue					
					if (pTmpStat->get_size() == iter->size) 
					{
						if (sync_flag != 0)
						{
							tmpObj->set_sync_flag(sync_flag);
						}	
						continue;
					}

					log_error("file [%s] in OSS size[%zd] is different from cloudfs size[%zd], updating ...", 
									iter->name.c_str(), iter->size, pTmpStat->get_size());
					
					//后台文件与前台文件不一致, 删除前台对象, 后面会重新创建该对象
					//删除上层目录表中该对象的信息
					OssDirObject * parent_dir = (OssDirObject *)get_parent(iter->name.c_str());
					if (parent_dir != NULL)
					{
						parent_dir->remove_record(tmpObj->get_file_name());
					}
					else
					{
						log_error("file [%s] get parent directory failed", iter->name.c_str());
					}

				}
				else
				{
					log_error("file [%s] invalid object type %zd", iter->name.c_str(), pTmpStat->type);
					continue;
				}

				
			}
		}
		
		log_debug("file:[%s] need online sync", iter->name.c_str());

		group_stats.clear();
		OssStats stats = OssStats(meta);
		if (stats.type == OSS_REGULAR)
		{
			log_debug("stats.size:[%d]", stats.size);
			create_group_stats(stats.size, 0, group_stats);
			tmpObj = this->add_file(iter->name.c_str(), group_stats, stats.type);
			//subobject不再需要保存stats, 此处循环释放所有的stat
			delete_group_stats(group_stats);
			
		}
		//增加对LINK文件的初始化处理
		else if (stats.type == OSS_DIR)
		{
			tmpObj = this->add_file(iter->name.c_str(), group_stats, stats.type);
		}
		else if (stats.type == OSS_LINK)
		{
			OssStats *pTmpStat = new OssStats(meta);
			group_stats.push_back(pTmpStat);
			tmpObj = this->add_file(iter->name.c_str(), group_stats, stats.type);
		}
		else
		{
			log_error("invalid stats.type %d", stats.type);
		}

		/* 检查add_file的结果, 并设置对应的sync_flag */
		if (tmpObj != NULL)
		{
			if (sync_flag != 0)
				tmpObj->set_sync_flag(sync_flag);
		}
	}

	return 0;
}
コード例 #6
0
ファイル: OssFS.cpp プロジェクト: dluobo/cloudfs
int OssFS::readdir(const char *path, void *buf, fuse_fill_dir_t filler,
				   off_t offset, struct fuse_file_info *fileInfo) 
{
	log_debug("path:%s", path);
	(void) offset;
	(void) fileInfo;

	//先准备两个子目录, 当前子目录和上级目录
	filler(buf, ".", NULL, 0);
	filler(buf, "..", NULL, 0);

	OssObject *pTargetDir = NULL;
	OSS_OBJS_MAP *target_dir = NULL;
	string Prefix;	
	const char *pDelimiter = "/";	
		
	if (strcmp(path, "/") == 0) 
	{
		//根目录不需要设置Prefix
		Prefix = "";					
	} 
	else
	{
		//非根目录, prefix组装形式为fun/模式
		Prefix = (path+1);
		Prefix = Prefix + "/";		
	}

	pTargetDir = get_file(path);
	target_dir = pTargetDir->get_subs();


	int is_syncd = 0;
	
	//检查同步时间配置, 如果时间间隔不为0, 则按照配置进行文件夹访问时间刷新
	if (AliConf::ONLINE_SYNC_CYCLE != 0)
	{
		//pTargetDir是当前要读取的目录对象, 判断当前操作与上一次操作的时间间隔
		OssStats *pStat = (OssStats *)pTargetDir->get_stats();
		time_t current_time = time(0);
		vector<oss_object_desc_t> object_list;
		if ((size_t)(current_time - pStat->mtime) > AliConf::ONLINE_SYNC_CYCLE)
		{								
			size_t sync_flag = pTargetDir->get_sync_flag() + 1;
			pTargetDir->set_sync_flag(sync_flag);
			
			int ret_code = m_oss->get_bucket(AliConf::BUCKET.c_str(),
							  Prefix.c_str(),
							  pDelimiter,
							  object_list);
			if (ret_code != 0)
			{
				//如果向OSS请求更新目录子文件与子目录失败, 记录error日志, 按照已有的缓存数据继续处理
				log_error("get_bucket failed");
			}
			else
			{
				//更新对象的访问时间
				pStat->mtime = current_time;
				
				//更新load过来的文件
				load_files(object_list, false, pTargetDir->get_sync_flag());

				//用于下面函数判断是否进行了一次同步
				is_syncd = 1;
			}			
		}
	}

	OssObject* tmpObj;
	map<const char *, OssObject *>::iterator it;
	vector<const char *> vecDel;
	vector<const char *>::iterator vec_iter;

	//遍历目录的map结构, 启用目录的读锁
	((OssDirObject *)pTargetDir)->rdlock();
	for (it = target_dir->begin(); it != target_dir->end(); it++) 
	{
		tmpObj = it->second;

		if (1 == is_syncd)
		{
			// 本次readdir进行过数据同步
			if (tmpObj->get_sync_flag() == pTargetDir->get_sync_flag()) 
			{
				filler(buf, it->first, NULL, 0);
			}
			else
			{
				log_debug("file:[%s] need delete.", it->first);
				vecDel.push_back(it->first);
			}			
		}
		else
		{
			// 本次readdir没有进行过数据同步, 不需要比较同步flag
			filler(buf, it->first, NULL, 0);
		}
		
	}

	//遍历结束, 关闭锁
	((OssDirObject *)pTargetDir)->unlock();

	for (vec_iter = vecDel.begin(); vec_iter != vecDel.end(); vec_iter++) {
		del_file(*vec_iter);
	}

	return 0;
}