我们的文件系统应用将实现一个简单的层次结构的文件系统,就像我们在 Windows 或 UNIX 上所看到的文件系统。为了让例子代码的数量保持在可以管理的范围内,我们忽略了真实的文件系统的许多方面,比如所有权、权限、符号链接,以及其他一些特性。但我们所构建的功能足以告诉你,可以怎样实现一个功能完备的文件系统,而且我们还考虑了像性能和可伸缩性这样的问题。以这种方式,我们可以创建一个具有现实的复杂度的应用,而又不会被埋葬在大量代码中。
件系统) 。
我们的文件系统由目录和文件组成。目录是可以容纳目录或文件的容器,也就是说,这个文件系统是层次结构的。在文件系统的根上有一个专用目录。每个目录和文件都有名字。其父目录相同的文件和目录必须具有不同的名字 (但父目录不同的文件和目录的名字可以相同)。换句话说,目录形成了命名范围,单个目录中的各个项的名字必须唯一。你可以列出目录的内容。目前,我们没有路径名的概念,也不能创建或销毁文件及目录。相反,服务器提供的是数目固定的目录和文件 (我们将在
XREF
中处理文件的创建和销毁)。你可以读写文件,但目前,读和写针对的总是文件的整个内容;你不可能读写文件的部分内容。
在给出了刚才概述的非常简单的需求之后,我们可以着手设计系统的接口了。文件和目录有共同之处:它们都有名字,而且文件和目录都可以包含在目录中。这提示我们,可以基类型来提供共有的功能,用派生类型来提供目录和文件专有的功能。
FileSyste.ice
module FileSystem{
interface CAbsNode{//抽象的文件接口
string GetName();//文件的名称
};
exception GenericError{//读写可能会抛出异常
string sReson;
};
sequence<string> seqString;//文件内容
interface CAbsFile extends CAbsNode{//可读可写的文件
seqString Read();
void Write(seqString text) throws GenericError;
};
sequence<CAbsNode*> seqNode;//复合节点:包含了分支结点【目录】和叶子结点
interface CAbsFolder extends CAbsNode{//文件夹
seqNode GetChilds();
};
interface CFileUtil{//获取文件系统的根目录
CAbsFolder* GetRoot();
};
};
FileImpl.h
#include <Ice/Ice.h>
#include "FileSystem.h"
namespace FileSystem{
class CFile;
typedef IceUtil::Handle<CFile> CFilePtr;
class CFolder;
typedef IceUtil::Handle<CFolder> CFolderPtr;
class CNode : virtual public CAbsNode{//抽象文件结点
public:
static Ice::ObjectAdapterPtr spObjAdapter;
private:
const std::string sName;//文件名
CAbsFolderPtr spParentFolder;//文件所在目录【父目录】
public:
CNode(const std::string& name, const CFolderPtr& parent);
virtual std::string GetName(const Ice::Current&);
private:
CNode(const CNode& other);//禁止拷贝构造
void operator=(const CNode& other);//禁止赋值
};
class CFile : virtual public CAbsFile, virtual public FileSystem::CNode{//文件
private:
seqString vecString;//文件内容
public:
CFile(const std::string&, const CFolderPtr&);
virtual FileSystem::seqString Read(const Ice::Current&);
virtual void Write(const FileSystem::seqString&, const Ice::Current&);
};
class CFolder : virtual public CAbsFolder, virtual public FileSystem::CNode{//文件夹
private:
seqNode vecNode;//目录下包含的文件和文件夹
public:
CFolder(const std::string&, const CFolderPtr&);
virtual FileSystem::seqNode GetChilds(const Ice::Current&);
void AddChild(CAbsNodePrx child);
};
}
FileImpl.cpp
#include "FileImpl.h"
#include <IceUtil/UUID.h>
#include <time.h>
using namespace std;
Ice::ObjectAdapterPtr FileSystem::CNode::spObjAdapter;
FileSystem::CNode::CNode(const string& name, const CFolderPtr& parent)
: sName(name), spParentFolder(parent){
Ice::Identity oId; oId.name = (parent? IceUtil::generateUUID() : "RootDir");//创建一个标识
CAbsNodePrx spNode = CAbsNodePrx::uncheckedCast(spObjAdapter->createProxy(oId));//创建结点
if(parent){
//CFolder* pFolder = dynamic_cast<CFolder*>(parent->GetSelf());
parent->AddChild(spNode);//如果父目录不为空,则添加进去
}
spObjAdapter->add(this, oId);//同时添加到适配器中
}
std::string FileSystem::CNode::GetName(const Ice::Current&){ return sName;}
FileSystem::CFile::CFile(const string& name, const CFolderPtr& parent) : CNode(name, parent){}
FileSystem::seqString FileSystem::CFile::Read(const Ice::Current&){return vecString;}
void FileSystem::CFile::Write(const FileSystem::seqString& text, const Ice::Current&){vecString = text;}
FileSystem::CFolder::CFolder(const string& name, const CFolderPtr& parent) : CNode(name, parent){}
FileSystem::seqNode FileSystem::CFolder::GetChilds(const Ice::Current&){return vecNode;}
void FileSystem::CFolder::AddChild(const CAbsNodePrx child){vecNode.push_back(child);}
Server.cpp
#include "FileSystem.h"
#include "FileImpl.h"
#include <Ice/Application.h>
using namespace FileSystem;
using namespace std;
class CMyApp : virtual public Ice::Application{
public:
virtual int run(int, char* []){
//文件夹派生定义,文件基类定义
CNode::spObjAdapter = communicator()->createObjectAdapterWithEndpoints("SimpleFilesystem", "default -p 10000");
CFolderPtr spRootFolder = new CFolder("/", 0);//创建根目录
CAbsFilePtr spTxtFile = new CFile("诗和远方", spRootFolder);//创建ReadMe.txt
seqString vString;
vString.push_back("无迹方知流光逝,有梦不觉人生寒。");
spTxtFile->Write(vString);
CFolderPtr spPoetyFolder = new CFolder("诗仙李白", spRootFolder);
CAbsFilePtr spDocFile = new CFile("静夜思", spPoetyFolder);
vString.erase(vString.begin(), vString.end());
vString.push_back("床前明月光,疑是地上霜。");
vString.push_back("举头望明月,低头思故乡。");
spDocFile->Write(vString);
CNode::spObjAdapter->activate();
communicator()->waitForShutdown();//等待我们发出“停止”命令
if(interrupted()) cerr << appName() << ":接收到停止服务的信号,并成功停止了服务!" << endl;
return 0;
}
};
int main(int argc, char* argv[]){
CMyApp theApp;
return theApp.main(argc, argv);
}
Client.cpp
#include <Ice/Ice.h>
#include "FileSystem.h"
using namespace FileSystem;
#include <iostream>
#include <iterator>
using namespace std;
static void DirDisp(const CAbsFolderPrx& folder, int depth = 0)
{
string sIndent(++depth, '\t');
seqNode vecNode = folder->GetChilds();
for(seqNode::const_iterator it = vecNode.begin(); it != vecNode.end(); it++){
CAbsFolderPrx spFolder = CAbsFolderPrx::checkedCast(*it);
CAbsFilePrx spFile = CAbsFilePrx::uncheckedCast(*it);
cout << sIndent << (*it)->GetName() << (spFolder? " (Folder) : " : " (File) : ") << endl;
if(spFolder) DirDisp(spFolder);
else{
string sIndent(++depth, '\t');
seqString vecString = spFile->Read();
for(seqString::const_iterator it = vecString.begin(); it != vecString.end(); it++) cout << sIndent << "\t" << *it << endl;
}
}
}
int main(int argc, char * argv[])
{
int iStatus = 0;
Ice::CommunicatorPtr spCommunicator;
try {
spCommunicator = Ice::initialize(argc, argv);//创建一个Communicator
Ice::ObjectPrx spObjProxy = spCommunicator->stringToProxy("RootDir:default -p 10000");//创建一个根目录的代理
if(!spObjProxy) throw "Could not create proxy";
CAbsFolderPrx spFolder = CAbsFolderPrx::checkedCast(spObjProxy);//向下映射
if(!spFolder) throw "Invalid proxy";
cout << "Contents of root directory:" << endl;
DirDisp(spFolder);
}
catch (const Ice::Exception & ex) {
cerr << ex << endl;
iStatus = 1;
}
catch (const char * msg) {
cerr << msg << endl;
iStatus = 1;
}
if(spCommunicator) spCommunicator->destroy();
system("Pause");
return iStatus;
}