Skip to content

Commit 1f38f74

Browse files
Rework filesystem demo in C++ (#275)
1 parent ea3266c commit 1f38f74

File tree

12 files changed

+289
-351
lines changed

12 files changed

+289
-351
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
cmake_minimum_required(VERSION 3.16)
22

3-
project(manual_simpleFilesystem CXX)
3+
project(filesystem CXX)
44

55
include(../../cmake/common.cmake)
66

77
add_executable(client Client.cpp Filesystem.ice)
88
slice2cpp_generate(client)
99
target_link_libraries(client Ice::Ice)
1010

11-
add_executable(server Server.cpp FilesystemI.cpp FilesystemI.h Filesystem.ice)
11+
add_executable(server Server.cpp Memory.cpp Memory.h Filesystem.ice)
1212
slice2cpp_generate(server)
1313
target_link_libraries(server Ice::Ice)

cpp/Ice/filesystem/Client.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) ZeroC, Inc.
2+
3+
#include "Filesystem.h"
4+
5+
#include <Ice/Ice.h>
6+
#include <iostream>
7+
8+
using namespace std;
9+
using namespace Filesystem;
10+
11+
/// Recursively print the contents of a directory in tree fashion. For files, show the contents of each file.
12+
/// @param dir The directory to list.
13+
/// @param depth The current nesting level (for indentation).
14+
static void
15+
listRecursive(const DirectoryPrx& dir, size_t depth = 0)
16+
{
17+
const string indent(++depth, '\t');
18+
19+
// The node proxies returned by list() are never null.
20+
NodeSeq contents = dir->list();
21+
22+
for (const optional<NodePrx>& node : contents)
23+
{
24+
auto subdir = Ice::checkedCast<DirectoryPrx>(node);
25+
cout << indent << node->name() << (subdir ? " (directory):" : " (file):") << endl;
26+
if (subdir)
27+
{
28+
listRecursive(*subdir, depth);
29+
}
30+
else
31+
{
32+
auto file = Ice::uncheckedCast<FilePrx>(node);
33+
Lines lines = file->read();
34+
for (const auto& line : lines)
35+
{
36+
cout << indent << '\t' << line << endl;
37+
}
38+
}
39+
}
40+
}
41+
42+
int
43+
main(int argc, char* argv[])
44+
{
45+
// Create an Ice communicator to initialize the Ice runtime.
46+
const Ice::CommunicatorHolder communicatorHolder{argc, argv};
47+
const Ice::CommunicatorPtr& communicator = communicatorHolder.communicator();
48+
49+
// Create a proxy for the root directory.
50+
DirectoryPrx rootDir{communicator, "RootDir:tcp -h localhost -p 4061"};
51+
52+
// Recursively list the contents of the root directory.
53+
cout << "Contents of root directory:" << endl;
54+
listRecursive(rootDir);
55+
56+
return 0;
57+
}

cpp/Ice/filesystem/Filesystem.ice

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) ZeroC, Inc.
2+
3+
#pragma once
4+
5+
module Filesystem
6+
{
7+
/// Represents a write failure.
8+
exception WriteException
9+
{
10+
/// The reason for the write failure.
11+
string reason;
12+
}
13+
14+
/// The base interface for files and directories.
15+
interface Node
16+
{
17+
/// Gets the name of this node.
18+
/// @return The name of the node.
19+
idempotent string name();
20+
}
21+
22+
/// The contents of a file.
23+
sequence<string> Lines;
24+
25+
/// Represents a file in our filesystem. A file holds lines of text.
26+
interface File extends Node
27+
{
28+
/// Reads the file and returns its contents.
29+
/// @return The contents of the file.
30+
idempotent Lines read();
31+
32+
/// Overwrites the file with new contents.
33+
/// @param text The new contents of the file.
34+
/// @throws WriteException Thrown if the file cannot be written to.
35+
idempotent void write(Lines text) throws WriteException;
36+
}
37+
38+
/// A list of node proxies.
39+
sequence<Node*> NodeSeq;
40+
41+
/// Represents a directory. A directory holds files and other directories.
42+
interface Directory extends Node
43+
{
44+
/// Gets the contents of the directory.
45+
/// @return The contents of the directory, as a list of non-null node proxies.
46+
idempotent NodeSeq list();
47+
}
48+
}

cpp/Ice/filesystem/Memory.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) ZeroC, Inc.
2+
3+
#include "Memory.h"
4+
5+
using namespace std;
6+
using namespace Memory;
7+
8+
//
9+
// MNode
10+
//
11+
12+
MNode::MNode(string name) : _name(std::move(name)) {}
13+
14+
string
15+
MNode::name(const Ice::Current&)
16+
{
17+
return _name;
18+
}
19+
20+
//
21+
// MFile
22+
//
23+
24+
Filesystem::Lines
25+
MFile::read(const Ice::Current&)
26+
{
27+
return _lines;
28+
}
29+
30+
void
31+
MFile::write(Filesystem::Lines text, const Ice::Current&)
32+
{
33+
writeDirect(std::move(text));
34+
}
35+
36+
void
37+
MFile::writeDirect(Filesystem::Lines text)
38+
{
39+
_lines = std::move(text);
40+
}
41+
42+
//
43+
// MDirectory
44+
//
45+
46+
Filesystem::NodeSeq
47+
MDirectory::list(const Ice::Current&)
48+
{
49+
return _contents;
50+
}
51+
52+
void
53+
MDirectory::addChild(Filesystem::NodePrx child)
54+
{
55+
_contents.push_back(std::move(child));
56+
}

cpp/Ice/filesystem/Memory.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) ZeroC, Inc.
2+
3+
#ifndef MEMORY_H
4+
#define MEMORY_H
5+
6+
#include "Filesystem.h"
7+
8+
// Provides an in-memory implementation of the Filesystem objects.
9+
namespace Memory
10+
{
11+
/// Implements Slice interface Node.
12+
class MNode : public virtual Filesystem::Node
13+
{
14+
public:
15+
/// Constructs a new MNode servant
16+
explicit MNode(std::string name);
17+
18+
// Implements Slice operation name.
19+
std::string name(const Ice::Current& current) override;
20+
21+
private:
22+
std::string _name;
23+
};
24+
25+
/// Implements Slice interface File.
26+
class MFile final : public Filesystem::File, public MNode
27+
{
28+
public:
29+
using MNode::MNode;
30+
31+
// Implements Slice operation read.
32+
Filesystem::Lines read(const Ice::Current&) final;
33+
34+
// Implements Slice operation write.
35+
void write(Filesystem::Lines text, const Ice::Current&) final;
36+
37+
// Write directly to this file, without going through an Ice operation.
38+
void writeDirect(Filesystem::Lines text);
39+
40+
private:
41+
Filesystem::Lines _lines;
42+
};
43+
44+
/// Implements Slice interface Directory.
45+
class MDirectory final : public Filesystem::Directory, public MNode
46+
{
47+
public:
48+
using MNode::MNode;
49+
50+
// Implements Slice operation list.
51+
Filesystem::NodeSeq list(const Ice::Current&) final;
52+
53+
/// Adds a node to this directory.
54+
/// @param child The node proxy to add.
55+
void addChild(Filesystem::NodePrx child);
56+
57+
private:
58+
Filesystem::NodeSeq _contents;
59+
};
60+
}
61+
62+
#endif

cpp/Manual/simpleFilesystem/README.md renamed to cpp/Ice/filesystem/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Manual Simple Filesystem
1+
# Filesystem
22

3-
This demo implements the simple filesystem application shown at the
4-
end of the client and server C++ mapping chapters.
3+
This demo implements the filesystem application shown at the end of the client and server
4+
C++ mapping chapters.
55

66
To build the demo run:
77

cpp/Ice/filesystem/Server.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) ZeroC, Inc.
2+
3+
#include "Memory.h"
4+
5+
#include <Ice/Ice.h>
6+
#include <iostream>
7+
8+
using namespace std;
9+
using namespace Memory;
10+
11+
int
12+
main(int argc, char* argv[])
13+
{
14+
// CtrlCHandler is a helper class that handles Ctrl+C and similar signals. It must be constructed at the beginning
15+
// of the program, before creating an Ice communicator or starting any thread.
16+
Ice::CtrlCHandler ctrlCHandler;
17+
18+
// Create an Ice communicator to initialize the Ice runtime. The CommunicatorHolder is a RAII helper that creates
19+
// the communicator in its constructor and destroys it when it goes out of scope.
20+
const Ice::CommunicatorHolder communicatorHolder{argc, argv};
21+
const Ice::CommunicatorPtr& communicator = communicatorHolder.communicator();
22+
23+
// Create an object adapter that listens for incoming requests and dispatches them to servants.
24+
auto adapter = communicator->createObjectAdapterWithEndpoints("Filesystem", "tcp -p 4061");
25+
26+
// Create the root directory servant (with name "/" and no parent), and add this servant to the adapter.
27+
auto root = make_shared<MDirectory>("/");
28+
adapter->add(root, Ice::stringToIdentity("RootDir"));
29+
30+
// Create a file called "README", add this servant to the adapter, and add the corresponding proxy to the root
31+
// directory.
32+
auto file = make_shared<MFile>("README");
33+
file->writeDirect({"This file system contains a collection of poetry."});
34+
root->addChild(adapter->addWithUUID<Filesystem::FilePrx>(file));
35+
36+
// Create a directory called "Coleridge", add this servant to the adapter, and add the corresponding proxy to the
37+
// root directory.
38+
auto coleridge = make_shared<MDirectory>("Coleridge");
39+
root->addChild(adapter->addWithUUID<Filesystem::DirectoryPrx>(coleridge));
40+
41+
// Create a file called "Kubla_Khan", add this servant to the adapter, and add the corresponding proxy to the
42+
// Coleridge directory.
43+
file = make_shared<MFile>("Kubla_Khan");
44+
file->writeDirect(
45+
{"In Xanadu did Kubla Khan",
46+
"A stately pleasure-dome decree:",
47+
"Where Alph, the sacred river, ran",
48+
"Through caverns measureless to man",
49+
"Down to a sunless sea."});
50+
coleridge->addChild(adapter->addWithUUID<Filesystem::FilePrx>(file));
51+
52+
// Start dispatching requests after registering all servants.
53+
adapter->activate();
54+
cout << "Listening on port 4061..." << endl;
55+
56+
// Wait until the user presses Ctrl+C.
57+
int signal = ctrlCHandler.wait();
58+
cout << "Caught signal " << signal << ", exiting..." << endl;
59+
60+
return 0;
61+
}

cpp/Manual/simpleFilesystem/Client.cpp

Lines changed: 0 additions & 73 deletions
This file was deleted.

0 commit comments

Comments
 (0)