In-Memory Cloud Storage: Files, Discovery, Users, and Compression
Context: Design an in-memory storage library that maps fully qualified POSIX-style file paths (e.g., "/a/b/c.txt") to file metadata. There is no real filesystem; all data structures are in-memory. Assume requests will not create collisions between file and directory names (e.g., "/a" won't be both a file and a directory).
Requirements
Implement the following feature levels. Each later level must preserve and build on earlier behaviors.
Level 1 — Basic file operations
-
bool AddFile(const std::string& name, int size)
-
Add a new file at path
name
with size in bytes.
-
Return false if a file with the same path already exists; true otherwise.
-
bool CopyFile(const std::string& name_from, const std::string& name_to)
-
Copy the file at
name_from
to
name_to
.
-
Fail if
name_from
does not exist or is not a file, or if
name_to
already exists.
-
Return true on success, false otherwise.
-
std::optional
<int>
GetFileSize(const std::string& name)
-
Return the file size if the file exists; otherwise std::nullopt.
Level 2 — File discovery
-
Support finding files by:
-
Matching path prefixes (directory-like queries).
-
Matching suffixes (e.g., extension or arbitrary suffix).
-
Define APIs and choose data structures to make these queries efficient.
-
Describe expected time and space complexity.
Level 3 — Users and capacity limits
-
Add a user concept with per-user storage capacity limits (bytes).
-
Associate files with users and enforce limits on AddFile and CopyFile.
-
Specify error handling and what each API returns when limits would be exceeded.
Level 4 — Compression support
-
Support compressing and decompressing files.
-
Define APIs to compress/decompress a file and update its stored size accordingly.
-
Clarify whether GetFileSize returns logical (uncompressed) size or physical (stored) size, and how capacity accounting works with compression.
General constraints and deliverables
-
Keep everything in-memory. Do not use the OS filesystem.
-
Provide class and method interfaces and the core data structures (e.g., maps/tries/indexes). Justify trade-offs.
-
Concurrency handling is optional, but describe how you would make operations thread-safe.
-
Include a brief test strategy with example scenarios that demonstrate expected behavior.