This commit is contained in:
IlyaShurupov 2024-03-29 17:39:56 +03:00
parent 8e150b52c3
commit 5fd14ea4dd
8 changed files with 88 additions and 120 deletions

View file

@ -8,19 +8,15 @@ class Directory : public Node {
public:
Directory();
Directory(const Directory& node);
~Directory() override;
NodeType getType() const override { return DIRECTORY; }
[[nodiscard]] std::shared_ptr<Node> clone() const override;
bool detachNode(const Key& key) override;
bool attachNode(const Key &newKey, std::shared_ptr<Node> newNode) override;
std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth = 0) override;
std::shared_ptr<Node> findNode(const Key& path) override;
[[nodiscard]] ui64 size() const override;
bool isDirectory() const override { return true; }
private:

View file

@ -7,26 +7,13 @@
// restore path unwindingk
// RESTORE LINKS
// COPY operator update link targets
// Improve error logs
// use smart pointers
// COPY operator update link targets on copied nodes
// in-tree node links will report false to those operations and hard nodes deletion
// use in node 'is_delete' flag and travers all nodes with link checks
// remove mParent mTreeNode links
// Functionality:
// deleting directory - mark all nodes as deleted
// traverse and check for links
// unlink if those links are outgoing
// Refactor
// - remove code duplication
// - Move DirectoryKey inside Node (no need to store pointers from Node to DirectoryTree::Node)
// - Merge DirectoryTree::Node and Node (no pointer overhead, requires tree nodes to be consistent, check insertNodeInstead)
// - introduce smart pointers
// - reconsider switch statements
class FileSystem {
public:

View file

@ -8,8 +8,8 @@ public:
Link(const Link& node);
~Link() override;
NodeType getType() const override { return LINK; }
[[nodiscard]] std::shared_ptr<Node> clone() const override;
[[nodiscard]] std::shared_ptr<Node> getLink() const;
[[nodiscard]] bool isHard() const;
@ -17,9 +17,7 @@ public:
// link on link is not allowed, so no inf looping here
std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth) override;
void dumpUtil(std::stringstream& ss, const Key& key, ui32 currentDepth, std::vector<bool>& indents) override;
bool isLink() const override { return true; }
private:

View file

@ -14,42 +14,32 @@ typedef long i32;
class Link;
extern std::string gError;
typedef std::string Key;
class Node {
public:
enum NodeType { FILE, LINK, DIRECTORY };
public:
Node() = default;
Node(const Node& node);
virtual ~Node();
virtual NodeType getType() const { return FILE; }
[[nodiscard]] virtual std::shared_ptr<Node> clone() const;
virtual bool detachNode(const Key& key) { return false; }
virtual bool attachNode(const Key &newKey, std::shared_ptr<Node> newNode) { return false; }
virtual void getMaxDepthUtil(ui32 depth, ui32& maxDepth) const {}
virtual void dumpUtil(std::stringstream& ss, const Key& key, ui32 currentDepth, std::vector<bool>& indents);
ui32 getMaxDepth() const;
void dump(std::stringstream& ss);
void getNodeStraightPath(const std::shared_ptr<Node>& node, std::vector<std::shared_ptr<Node>>& path) const;
virtual ui64 size() const { return 0; }
virtual std::shared_ptr<Node> getTarget();
virtual std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth = 0);
virtual std::shared_ptr<Node> findNode(const Key& path) { return nullptr; }
bool empty() const { return !size(); }
static void indent(std::stringstream & ss, ui32 depth, std::vector<bool>& indents);
virtual bool isDirectory() const { return false; }
virtual bool isLink() const { return false; }
virtual bool isHard() const { return false; }

View file

@ -2,34 +2,20 @@
#include "Directory.hpp"
#include <sstream>
#include <cassert>
#include <algorithm>
Directory::Directory() {
}
Directory::Directory() = default;
Directory::~Directory() = default;
bool Directory::attachNode(const Key &newKey, std::shared_ptr<Node> newNode) {
auto iterNode = mMembers.find(newKey);
if (iterNode != mMembers.end()) {
auto existingNode = iterNode->second;
if (!(false && newNode->empty() && existingNode->empty())) {
gError = "Such node already exists";
return false;
}
return false; // exit silently
}
assert(mMembers.find(newKey) == mMembers.end());
mMembers.insert({ newKey, newNode });
return true;
}
bool Directory::detachNode(const Key& key) {
auto removeNode = mMembers.find(key);
if (removeNode == mMembers.end()) {
gError = "Invalid path";
return false;
}
assert(mMembers.find(key) != mMembers.end());
//if (removeNode->key.incomingLinksHard || removeNode->key.incomingLinksDynamic) {
// gError = "Cannot modify node with incoming hard links";
@ -99,11 +85,6 @@ Directory::Directory(const Directory &node) : Node(node) {
}
}
Directory::~Directory() {
for (const auto& node : mMembers) {
// delete node.second;
}
}
std::shared_ptr<Node> Directory::clone() const {
auto out = std::make_shared<Directory>(*this);

View file

@ -8,6 +8,8 @@
#include <cassert>
#include <algorithm>
static std::string gError;
FileSystem::FileSystem() {
root = std::make_shared<Directory>();
currentDirectory = root;
@ -65,14 +67,19 @@ bool FileSystem::makeDirectory(const Path& path) {
return false;
}
auto directory = std::make_shared<Directory>();
if (!parentNode->attachNode(path.getFilename(), directory)) {
gError = "File or link with such name already exists";
return false;
auto existingNode = parentNode->findNode(path.getFilename());
if (existingNode) {
if (!(existingNode->getType() == Node::DIRECTORY && existingNode->empty())) {
gError = "File or link with such name already exists";
return false;
}
return true;
}
auto directory = std::make_shared<Directory>();
directory->mParent = parentNode;
assert(parentNode->attachNode(path.getFilename(), directory));
return true;
}
@ -89,13 +96,63 @@ bool FileSystem::makeFile(const Path& path) {
return false;
}
auto existingNode = parentNode->findNode(path.getFilename());
if (existingNode) {
if (!(existingNode->getType() == Node::FILE && existingNode->empty())) {
gError = "Directory with such name already exists";
return false;
}
return true;
}
auto newFile = std::make_shared<Node>();
if (!parentNode->attachNode(path.getFilename(), newFile)) {
gError = "Directory with such name already exists";
newFile->mParent = parentNode;
assert(parentNode->attachNode(path.getFilename(), newFile));
return true;
}
bool FileSystem::makeLink(const Path& source, const Path& target, bool isDynamic) {
if (source.getDepth() < 1 || source.isInvalid()) {
gError = "Invalid source path";
return false;
}
newFile->mParent = parentNode;
auto parentNodeSource = getNode(source, true);
if (!parentNodeSource) {
gError = "Invalid source path";
return false;
}
auto parentNodeTarget = getNode(target, false);
if (!parentNodeTarget) {
gError = "Invalid target path";
return false;
}
auto sourceNode = parentNodeSource->findNode(source.getFilename());
if (!sourceNode) {
gError = "Invalid source path";
return false;
}
if (sourceNode->isLink()) {
gError = "Link on link is not allowed";
return false;
}
const Key& key = source.getFilename();
if (parentNodeTarget->findNode(key)) {
gError = "Node with such name already exists";
return false;
}
auto newLink = std::shared_ptr<Node>(new Link(sourceNode, !isDynamic));
newLink->mParent = parentNodeTarget;
assert(parentNodeTarget->attachNode(key, newLink));
return true;
}
@ -210,8 +267,9 @@ bool FileSystem::copyNode(const Path& source, const Path& target) {
}
auto clonedNode = sourceNode->clone();
assert(parentNodeTarget->attachNode(key, clonedNode));
clonedNode->mParent = parentNodeTarget;
assert(parentNodeTarget->attachNode(key, clonedNode));
return true;
}
@ -241,59 +299,20 @@ bool FileSystem::moveNode(const Path &source, const Path &target) {
const Key& key = source.getFilename();
if (parentNodeTarget->findNode(key)) {
gError = "Node with such name already exists in the target directory";
return false;
}
if (sourceNode->isHard()) {
gError = "Node contains incoming hard links";
return false;
}
if (!parentNodeTarget->attachNode(key, sourceNode)) {
gError = "Node with such name already exists";
return false;
}
assert(parentNodeTarget->attachNode(key, sourceNode));
assert(parentNodeSource->detachNode(key));
sourceNode->mParent = parentNodeTarget;
assert(parentNodeSource->detachNode(key));
return true;
}
bool FileSystem::makeLink(const Path& source, const Path& target, bool isDynamic) {
if (source.getDepth() < 1 || source.isInvalid()) {
gError = "Invalid source path";
return false;
}
auto parentNodeSource = getNode(source, true);
if (!parentNodeSource) {
gError = "Invalid source path";
return false;
}
auto parentNodeTarget = getNode(target, false);
if (!parentNodeTarget) {
gError = "Invalid target path";
return false;
}
auto sourceNode = parentNodeSource->findNode(source.getFilename());
if (!sourceNode) {
gError = "Invalid source path";
return false;
}
if (sourceNode->isLink()) {
gError = "Link on link is not allowed";
return false;
}
const Key& key = source.getFilename();
auto newLink = std::shared_ptr<Node>(new Link(sourceNode, !isDynamic));
if (!parentNodeTarget->attachNode(key, newLink)) {
gError = "Node with such name already exists";
return false;
}
newLink->mParent = parentNodeTarget;
return true;
}

View file

@ -92,7 +92,7 @@ Interpreter::Interpreter() {
}
void Interpreter::reportError(const std::string& description) {
std::cout << "ERROR : " << description << "\n\n";
std::cout << "ERROR: " << description << "\n\n";
}
void Interpreter::printHelp() {

View file

@ -6,9 +6,6 @@
#include <cassert>
#include <algorithm>
std::string gError;
bool gDebug = true;
Node::Node(const Node &node) {}
Node::~Node() {
@ -54,7 +51,7 @@ void Node::dump(std::stringstream& ss) {
void Node::dumpUtil(std::stringstream& ss, const Key& key, ui32 currentDepth, std::vector<bool>& indents) {
indent(ss, currentDepth, indents);
ss << key;
if (gDebug) ss << " [file]";
ss << " [file]";
ss << "\n";
}