Skip to content

02_metadata_management.md

Lavnish edited this page Mar 31, 2026 · 2 revisions

Chapter 2: Metadata Management

Welcome back to cdfs-ton! In Chapter 1: Client Application Interface, we learned how to use simple commands like put and get to interact with our distributed file system. We saw that when you tell cdfs-ton to put a file, your client application breaks it into "chunks" and sends these chunks to various "Storage Nodes."

But how does the system know where each chunk is stored? And how can it find all those chunks later when you want to get your file back? This is where the Metadata Management system comes in.

Imagine cdfs-ton as a gigantic library. You, as the user, simply ask for "My Awesome Vacation Photos.jpg" or "Project Report.docx." You don't care where in the library those files are or how they're split across different shelves. You just want them!

For the library to work, it needs a super-smart librarian and a detailed catalog. This librarian knows:

  • Every book's name (your file's name).
  • How each book is divided (your file broken into "chunks").
  • The unique ID of each chapter (your chunk IDs).
  • Exactly which shelf and row each chapter is on (which Storage Nodes hold each chunk).

This "librarian" is the Metadata Server, and the "catalog" it maintains is the core of cdfs-ton's Metadata Management. It's the central intelligence that knows everything about your files, except for the actual file content itself.

What is Metadata?

In computer terms, "metadata" simply means "data about data." It's not the actual content of your files (like the pictures in your photo album or the words in your document), but rather information that describes and helps manage those files.

For cdfs-ton, the Metadata Server keeps track of crucial metadata for every file you store:

  • File Name: The name you gave your file (e.g., /photos/summer/my_vacation.jpg).
  • Chunk Breakdown: How your file was split into smaller pieces (chunks).
  • Chunk IDs: A unique identifier for each chunk. Think of it as a unique chapter number.
  • Chunk Locations: Which specific Storage Nodes (the physical storage shelves) hold copies (replicas) of each chunk. This is critical for finding your file later and for data safety.
  • Available Storage: It also monitors which Storage Nodes are currently active and available to store new chunks.
  • Next Available Chunk ID: It keeps track of the next unique ID it can assign to a new chunk, ensuring no two chunks ever get the same ID.

The Metadata Server: The Brain of CDFS-TON

The Metadata Server is the "control tower" or "librarian" of cdfs-ton. It runs separately from your client application and the Storage Nodes. Its primary job is to manage all this metadata. When you use cdfs_client put or cdfs_client get, your client application talks directly to the Metadata Server first to get instructions or register file information.

How Metadata Management Works for a cdfs_get Request

Let's revisit the cdfs_get command from Chapter 1. When you type cdfs_client get /photos/my_vacation.jpg downloaded_photo.jpg, here's how the Metadata Server's role ensures you get your file back:

  1. Client Request: Your cdfs_client application sends a request to the Metadata Server, saying, "I need the file /photos/my_vacation.jpg."
  2. Metadata Lookup: The Metadata Server searches its internal catalog for an entry matching /photos/my_vacation.jpg.
  3. Information Retrieval: If it finds the file, it retrieves all its metadata: the list of chunk IDs that make up the file, and for each chunk, which Storage Nodes have copies.
  4. Client Instruction: The Metadata Server sends this metadata back to your cdfs_client application.
  5. Direct Chunk Download: Your cdfs_client then uses this information to connect directly to the specified Storage Nodes and download each chunk.
  6. File Reconstruction: Once all chunks are downloaded, your cdfs_client stitches them back together to re-create the original my_vacation.jpg file on your local machine.

Here's a simplified sequence of how your client gets file information from the Metadata Server:

sequenceDiagram
    participant Client
    participant MetadataServer as Metadata Server

    Client->>MetadataServer: 1. Request file metadata for "my_vacation.jpg" (OP_GET_METADATA)
    MetadataServer->>MetadataServer: 2. Search internal catalog for "my_vacation.jpg"
    MetadataServer-->>Client: 3. Return file metadata: chunk IDs, chunk sizes, and locations (Storage Nodes' IPs/ports)
    Note over Client: Client now knows where to find each piece of the file.
    Client->>MetadataServer: (Later, for other requests like listing files, deleting, etc.)
Loading

Inside the Metadata Server

Let's peek behind the scenes at how the Metadata Server (metadata_server/metadata.c) manages all this information.

The File Catalog

The Metadata Server stores all file information in a central catalog. This catalog is essentially an array of file_metadata_t structures. Each structure holds all the important details about one file.

// File: common/dfs.h
typedef struct {
    int32_t chunk_id;
    size_t chunk_size;
    int32_t node_count;
    uint8_t node_ips[REPLICATION_FACTOR][16]; // IPs of nodes holding this chunk
    int32_t node_ports[REPLICATION_FACTOR];   // Ports of nodes holding this chunk
} chunk_info_t;

typedef struct {
    uint8_t filename[MAX_FILENAME];
    int32_t chunk_count;
    chunk_info_t chunks[MAX_CHUNKS]; // Array of chunk details for this file
} file_metadata_t;
  • chunk_info_t: This struct describes a single chunk. It includes its unique chunk_id, its chunk_size, how many copies (replicas) exist (node_count), and the network addresses (node_ips, node_ports) of the Storage Nodes that store these copies.
  • file_metadata_t: This struct represents an entire file. It stores the filename, the total chunk_count for that file, and an array (chunks) containing all the chunk_info_t entries for each of its pieces.

The Metadata Server keeps a collection of these file_metadata_t structs:

// File: metadata_server/metadata.c (simplified)
static file_metadata_t files[MAX_FILES]; // Our main catalog: an array of file records
static int32_t file_count = 0;           // How many files are currently in the catalog
static int32_t next_chunk_id = 1;        // The next unique ID to give to a new chunk
  • files: This is the actual array where all file metadata is stored. It's like the physical card catalog.
  • file_count: A simple counter to know how many files are currently registered.
  • next_chunk_id: This important variable ensures every new chunk gets a unique ID. It just keeps incrementing.

Registering a New File (register_file)

When your client uploads a file using cdfs_put, the very last step (after all chunks are sent to Storage Nodes) is to tell the Metadata Server about the new file. This is handled by the register_file function:

// File: metadata_server/metadata.c (simplified)
int32_t register_file(const uint8_t *filename, const chunk_info_t* chunks, int32_t chunk_count) {
    // A special lock is used here (pthread_mutex_lock) to prevent multiple
    // clients from trying to update the catalog at the exact same time,
    // which could lead to errors or lost data.
    // ... acquire lock ...

    // Check if there's space for a new file and if the filename already exists.
    // If everything is okay:
    file_metadata_t *new_file_entry = &files[file_count]; // Point to next empty slot
    strncpy((char *)new_file_entry->filename, (const char *)filename, MAX_FILENAME - 1);
    new_file_entry->chunk_count = chunk_count;

    // Copy the details of all the chunks into this new file entry
    for(int32_t i = 0; i < chunk_count; i++){
        new_file_entry->chunks[i] = chunks[i];
    }
    file_count++; // Increment the total number of files in our system

    // ... release lock ...
    return 0; // Success!
}

This function takes the filename, the array of chunk_info_t (which contains all the chunk IDs and their locations), and the chunk_count. It then creates a new entry in its files catalog. This is how the Metadata Server learns about your newly uploaded file and all its pieces!

Getting File Metadata (get_file_metadata)

When your client wants to download a file (cdfs_get), it calls get_file_metadata on the Metadata Server:

// File: metadata_server/metadata.c (simplified)
int32_t get_file_metadata(const uint8_t *filename, file_metadata_t *out){
    // ... acquire lock ...

    // Loop through all registered files to find the matching filename
    for(int32_t i = 0; i < file_count; i++){
        if(strcmp((char *)files[i].filename, (const char *)filename) == 0){
            // If found, copy its metadata to the 'out' parameter
            file_metadata_t *src = &files[i];
            strncpy((char *)out->filename, (const char *)src->filename, MAX_FILENAME - 1);
            out->chunk_count = src->chunk_count;
            for (int32_t j = 0; j < src->chunk_count; j++) {
                out->chunks[j] = src->chunks[j];
            }
            // ... release lock ...
            return 0; // File found and metadata copied
        }
    }
    // ... release lock ...
    return -1; // File not found
}

This function searches the files array for the requested filename. If found, it copies all the associated file_metadata_t (filename, chunk count, and all chunk_info_t details) into the out variable, which is then sent back to the cdfs_client. The client then knows exactly where to go to download each chunk.

Allocating New Chunk IDs (allocate_chunks)

Before a client can send chunks to Storage Nodes, it needs unique IDs for them. The allocate_chunks function handles this:

// File: metadata_server/metadata.c (simplified)
int32_t allocate_chunks(int32_t count, int32_t *out_start_chunk_id) {
    if (count <= 0) return -1; // Must request at least one chunk ID

    // ... acquire lock ...

    // Provide the current next_chunk_id as the starting ID
    *out_start_chunk_id = next_chunk_id;
    // Increment next_chunk_id by 'count' for the next request
    next_chunk_id += count;

    // ... release lock ...
    return 0; // Success!
}

When your cdfs_client asks for, say, 5 chunk IDs, this function simply gives it the current next_chunk_id as a starting point and then updates next_chunk_id by adding 5. This ensures every chunk in the system has a unique identifier.

The Role of pthread_mutex_t

You might have noticed comments like // ... acquire lock ... and // ... release lock ... in the code snippets. These refer to a special mechanism called a "mutex" (pthread_mutex_t).

Imagine multiple cdfs_client applications (or even internal cdfs-ton processes) trying to update or read the files catalog at the exact same time. Without proper control, one might overwrite another's changes, or read incomplete data. The mutex acts like a "single access pass." Only one process can "hold the lock" and modify the metadata at any given moment. Once it's done, it "releases the lock," allowing another process to take its turn. This keeps the metadata consistent and prevents chaos.

Conclusion

The Metadata Management system, primarily run by the Metadata Server, is the absolute heart of cdfs-ton. It doesn't store your actual files, but it knows everything about them: their names, how they're broken into chunks, unique IDs for those chunks, and exactly where in the distributed system each chunk is stored. It's the central brain that makes finding and reconstructing your files possible, even across many different machines.

In the next chapter, we'll shift our focus from knowing what and where your chunks are to understanding how those chunks are actually stored and managed by the individual Chunk Storage & Management system.