Bird
Raised Fist0

In-Memory File System

LLDhardInterview freq: medium
Choose your preparation mode4 modes available
🏗️
In-Memory File System
Design an in-memory file system supporting directories, files, permissions, search, and symbolic links
hardInfrastructure and Utility SystemsFreq: medium
Prerequisites:Tree Data StructureOOP DesignJava Concurrency Basics
⚙️
Functional Requirements
  • Support hierarchical directory structure with files and subdirectories
  • Files and directories have permissions (read, write, execute) per user/group
  • Symbolic links resolve transparently during file operations
  • Search supports recursive traversal with filters
  • Thread-safe operations to prevent data races and inconsistent state
  • Support atomic rename and move operations
  • Efficient memory usage with lazy loading of metadata
👤
Use Cases
  • Create, read, update, delete files and directories
  • Set and check permissions on files and directories
  • Create and resolve symbolic links
  • Search files and directories by name or metadata
  • Concurrent access by multiple threads
  • Handle edge cases like circular symbolic links and permission denial
🧑‍💻
Actors
  • User
  • System Administrator
  • File System API Client
❓
Clarifying Questions to Ask
  • How many concurrent threads/gates are expected to access the file system?
  • Should permission checks be enforced per operation or can they be bypassed by admin?
  • Is there a pricing or quota strategy for file sizes or number of files?
  • How to handle symbolic link loops during resolution?
  • Are file contents mutable or immutable once created?
  • Should search support pattern matching or only exact names?
  • What is the expected maximum depth of directory nesting?
Out of Scope
✗ Persistent storage or disk-backed file system
✗ Network file sharing protocols
✗ User authentication and authorization beyond permission flags
✗ File content versioning or snapshots
⚡
QPS Calculation
read qps1000
write qps200
search qps100
🖥️
Server Estimate
number of servers3
reasoningTo handle concurrency and provide fault tolerance with replication.
🔢
Enumerations
enum Permission
READ | WRITE | EXECUTE
Defines file system permissions explicitly to prevent typo bugs and enable exhaustive switch statements for permission checks.
enum FileType
REGULAR | DIRECTORY | SYMLINK
Differentiates file system node types to enforce type-specific behavior and avoid instanceof checks.
enum PermissionScope
OWNER | GROUP | OTHERS
Encapsulates permission scopes to clearly separate user, group, and others permissions, enabling fine-grained access control.
📦
FileSystemNode
6 fields
protected final String nameprotected volatile Directory parentprotected final FileType typeprotected final Map<PermissionScope, EnumSet<Permission>> permissionsprotected final long creationTimeprotected volatile long lastModifiedTime
Abstract base class representing a node in the file system tree. Holds common attributes like name, parent, type, and permissions. Provides permission checking and metadata management.
public String getName()Returns the name of the node.
public Directory getParent()Returns the parent directory; volatile ensures visibility across threads.
public synchronized void setParent(Directory parent)Atomically sets the parent directory to maintain tree integrity.
public boolean checkPermission(PermissionScope scope, Permission permission)Checks if the given permission is granted for the specified scope.
protected synchronized void updateLastModifiedTime()Updates last modified timestamp atomically.
📦
File
2 fields
private volatile byte[] contentprivate final ReadWriteLock contentLock
Represents a regular file storing byte content. Manages concurrent read/write access to content using ReadWriteLock.
public byte[] readContent()Returns a copy of the file content with read lock to ensure consistency.
public void writeContent(byte[] newContent)Replaces file content atomically with write lock to prevent data races.
📦
Directory
1 fields
private final ConcurrentHashMap<String, FileSystemNode> children
Represents a directory node containing child files and directories. Supports thread-safe add, remove, and lookup of children.
public synchronized boolean addChild(FileSystemNode child)Atomically adds a child node if name not already present.
public synchronized boolean removeChild(String name)Atomically removes a child node by name.
public FileSystemNode getChild(String name)Returns child node by name or null if absent.
public List<FileSystemNode> listChildren()Returns a snapshot list of all children.
📦
SymbolicLink
1 fields
private volatile FileSystemNode target
Represents a symbolic link pointing to another file system node. Resolves target lazily and handles cycles.
public FileSystemNode getTarget() throws IOExceptionResolves and returns the target node, throws IOException on cycles.
public synchronized void setTarget(FileSystemNode target)Atomically sets the symbolic link target.
📦
FileSystem
2 fields
private final Directory rootprivate final ReadWriteLock fsLock
Main entry point managing the root directory and providing thread-safe file system operations like create, delete, move, and search.
public synchronized File createFile(String path, EnumSet<Permission> permissions) throws IOExceptionCreates a new file at the specified path with given permissions atomically.
public synchronized Directory createDirectory(String path, EnumSet<Permission> permissions) throws IOExceptionCreates a new directory at the specified path atomically.
public synchronized boolean deleteNode(String path) throws IOExceptionDeletes a file system node at path atomically.
public synchronized boolean moveNode(String sourcePath, String destPath) throws IOExceptionAtomically moves or renames a node from sourcePath to destPath.
public List<FileSystemNode> search(String namePattern) throws IOExceptionSearches files and directories recursively matching the name pattern.
🗄️
FileSystemNodes
PK: node_id
node_id UUID PRIMARY KEYparent_id UUIDname VARCHARtype VARCHARpermissions MAP<PermissionScope, SET<Permission>>creation_time TIMESTAMPlast_modified_time TIMESTAMPcontent BLOB
Stores all file system nodes including files, directories, and symbolic links.
🗄️
SymbolicLinks
PK: link_id
link_id UUID PRIMARY KEYtarget_node_id UUIDlink_name VARCHARcreation_time TIMESTAMP
Stores symbolic link mappings to target nodes.
🔌
POST /files
Request
{
  "path": "string",
  "permissions": "EnumSet<Permission>"
}
Response
{
  "fileId": "UUID",
  "status": "success/failure"
}
Creates a new file at the specified path with given permissions.
🔌
POST /directories
Request
{
  "path": "string",
  "permissions": "EnumSet<Permission>"
}
Response
{
  "directoryId": "UUID",
  "status": "success/failure"
}
Creates a new directory at the specified path.
🔌
GET /search
Request
{
  "namePattern": "string"
}
Response
{
  "results": "List<FileSystemNode>"
}
Searches files and directories matching the name pattern.

Practice

(1/5)
1. A class CarBuilder constructs a Car object step-by-step using methods like setEngine(), setWheels(), and finally build(). The Car constructor is private. Which design pattern is applied here and why is it the correct choice?
easy
A. Builder pattern, because it separates complex object construction from its representation, allowing stepwise creation.
B. Factory Method pattern, because it creates objects through inheritance and subclasses.
C. Prototype pattern, because it clones existing objects to create new ones efficiently.
D. Singleton pattern, because it ensures only one instance of Car exists.

Solution

  1. Step 1: Identify the construction process

    The class uses multiple setter methods to configure parts of the object before finalizing with build(), indicating stepwise construction.
  2. Step 2: Match pattern intent

    Builder pattern separates construction from representation, ideal for complex objects with many optional parts. Factory Method uses inheritance, Prototype clones objects, Singleton restricts instance count.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Stepwise object creation with private constructor -> Builder pattern [check]
Hint: Stepwise construction with private constructor -> Builder pattern [check]
Common Mistakes:
2. To add a WeekendFeeStrategy for weekend pricing without modifying existing classes, which SOLID principle is being applied and what is the minimum required change?
medium
A. Modify ParkingLot to add weekend logic, violating OCP but keeping DIP intact.
B. Create a new WeekendFeeStrategy class implementing FeeStrategy interface; ParkingLot uses FeeStrategy polymorphically, preserving OCP and DIP.
C. Add weekend flag to Vehicle class and modify pricing logic there, violating SRP.
D. Add weekend pricing logic inside Spot classes, violating Liskov Substitution Principle.

Solution

  1. Step 1: Identify SOLID principles involved

    Open-Closed Principle (OCP) requires new functionality added via extension, not modification; Dependency Inversion Principle (DIP) requires depending on abstractions.
  2. Step 2: Implement WeekendFeeStrategy as new class implementing FeeStrategy

    This allows ParkingLot to use polymorphism without changing existing code, preserving OCP and DIP.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    New FeeStrategy class + polymorphic use -> OCP and DIP preserved [check]
Hint: New strategy class + interface use = OCP and DIP [check]
Common Mistakes:
3. In a parking lot system, the parkVehicle() method checks if a spot is available and then marks it occupied. Without synchronized, what exact thread interleaving causes double-booking?
medium
A. Thread 1 parks vehicle, Thread 2 waits until Thread 1 finishes, then parks.
B. Thread 1 checks spot availability -> true, context switch; Thread 2 checks availability -> true; both mark spot occupied.
C. Thread 1 marks spot occupied, Thread 2 checks availability -> false, no double-booking.
D. Thread 1 and Thread 2 both crash simultaneously causing no booking.

Solution

  1. Step 1: Identify the check-then-act race condition

    Without synchronization, Thread 1 reads spot as available but before marking occupied, context switches to Thread 2 which also reads available.
  2. Step 2: Both threads proceed to mark the spot occupied independently

    This leads to double-booking as both think the spot was free at check time.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap -> both threads see available -> double-booking [check]
Hint: Check-then-act without sync -> double-booking race [check]
Common Mistakes:
4. Electric cars require charging spots in the parking module. What is the minimum change to the current Java design to support ElectricCar and ChargingSpot without modifying existing classes?
hard
A. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType, create ElectricCar subclass, and update compatibility map externally.
B. Modify Vehicle class to add an isElectric flag and update spot compatibility logic inside existing classes.
C. Create a new ElectricVehicle interface and make ElectricCar implement it, modifying Spot to check for this interface.
D. Add charging logic inside existing ParkingLot class and extend Spot with charging capability.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and subclasses allows extension without changing existing class code.
  2. Step 2: Update compatibility map externally to maintain open-closed principle and avoid class explosion.

    Options B, C, and D require modifying existing classes, violating OCP or causing tight coupling.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New enums + subclass + external compatibility update -> minimal change [check]
Hint: Add enums + subclass + external map update, no existing class change [check]
Common Mistakes:
5. The ESPNcricinfo system needs to support ElectricCar vehicles that require ChargingSpot parking spots. What is the minimum change to the current design to support this without modifying existing classes?
hard
A. Modify Vehicle class to add isElectric flag and add charging logic inside existing Spot classes.
B. Create a new ElectricCar class and ChargingSpot class, then modify ParkingLot to handle both types explicitly.
C. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar extends Vehicle, and update SpotCompatibility.COMPATIBILITY_MAP accordingly.
D. Add a new method in Vehicle interface for charging and implement it only in ElectricCar.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and new subclasses allows extension without changing existing class code.
  2. Step 2: Update compatibility map for new types

    Updating SpotCompatibility.COMPATIBILITY_MAP supports new vehicle-spot matching without altering existing logic.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Extend enums + new subclasses + update compatibility map -> no existing class changes [check]
Hint: Extend enums + new subclasses + compatibility map -> minimal change [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard