Nimbin2git.christianimmanuel.de / Games / dvd / imdb_aka.c

dvd files

last change 2026-09-04 (2 hours ago)

wget https://git.christianimmanuel.de/games/dvd/archive/dvd.tar.gz
imdb_aka.c 5.8 KB · 197 lines raw
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>


#define MAX_LINE_LENGTH 1024
#define NUM_THREADS 16

// Define the struct to hold the parsed data for each line
typedef struct {
    char *titleId;
    int ordering;
    char *title;
    char *region;
    char *language;
    char *types;
    char *attributes;
    int isOriginalTitle;
} TitleLanguages;

typedef struct {
    char *filename;
    long start_offset;
    long end_offset;
    TitleLanguages *parsed_lines;
    int *line_count;
} ThreadData;

char *strdup(const char *s) {
    size_t len = strlen(s) + 1;
    char *dup = malloc(len);
    if (dup) {
        memcpy(dup, s, len);
    }
    return dup;
}

// Function to process the file chunk for each thread
void* processAkaLinesThread(void *arg) {
    ThreadData *data = (ThreadData*)arg;
    FILE *file = fopen(data->filename, "r");
    if (!file) {
        perror("Error opening file in thread");
        pthread_exit(NULL);
    }

    char line[MAX_LINE_LENGTH];
    long start = data->start_offset;
    long end = data->end_offset;
    int line_count = 0;

    printf("Thread starting: processing from %ld to %ld\n", start, end);

    fseek(file, start, SEEK_SET);

    // Read and process lines within the given range
    while (ftell(file) < end && fgets(line, sizeof(line), file)) {
        line[strcspn(line, "\n")] = 0;

        char *titleId = strtok(line, "\t");
        if (!titleId) continue;
        char *ordering_str = strtok(NULL, "\t");
        char *title = strtok(NULL, "\t");
        char *region = strtok(NULL, "\t");
        char *language = strtok(NULL, "\t");
        char *types = strtok(NULL, "\t");
        char *attributes = strtok(NULL, "\t");
        char *isOriginalTitle_str = strtok(NULL, "\t");

        if (!ordering_str || !title || !region || !language || !types || !attributes || !isOriginalTitle_str) {
            continue;
        }

        TitleLanguages *current_line = &data->parsed_lines[line_count];
        current_line->titleId = strdup(titleId);
        current_line->ordering = atoi(ordering_str);
        current_line->title = strdup(title);
        current_line->region = strdup(region);
        current_line->language = strdup(language);
        current_line->types = strdup(types);
        current_line->attributes = strdup(attributes);
        current_line->isOriginalTitle = atoi(isOriginalTitle_str);

        if (!current_line->titleId || !current_line->title || !current_line->region || 
            !current_line->language || !current_line->types || !current_line->attributes) {
            perror("Memory allocation failed");
            fclose(file);
            pthread_exit(NULL);
        }

        line_count++;
    }

    *(data->line_count) = line_count;
    fclose(file);
    pthread_exit(NULL);
}

// Function to read the Akas file and process lines with multiple threads
int readAkasWithThreads(const char *filename, TitleLanguages **languages) {
    FILE *fh = fopen(filename, "r");
    if (!fh) {
        perror("Error opening file");
        return -1;
    }

    fseek(fh, 0, SEEK_END);
    long file_size = ftell(fh);
    fseek(fh, 0, SEEK_SET);

    printf("File size: %ld bytes\n", file_size);

    int num_lines = file_size / MAX_LINE_LENGTH * NUM_THREADS;
    *languages = malloc(num_lines * sizeof(TitleLanguages));
    if (!*languages) {
        perror("Memory allocation failed");
        fclose(fh);
        return -1;
    }

    pthread_t threads[NUM_THREADS];
    ThreadData thread_data[NUM_THREADS];
    int line_counts[NUM_THREADS];

    long chunk_size = file_size / NUM_THREADS;
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_data[i].filename = (char *)filename;
        thread_data[i].start_offset = i * chunk_size;
        thread_data[i].end_offset = (i == NUM_THREADS - 1) ? file_size : (i + 1) * chunk_size;
        
        thread_data[i].parsed_lines = *languages + (i * num_lines / NUM_THREADS);
        thread_data[i].line_count = &line_counts[i];

        printf("Thread %d: start offset %ld, end offset %ld\n", i, thread_data[i].start_offset, thread_data[i].end_offset);
        pthread_create(&threads[i], NULL, processAkaLinesThread, &thread_data[i]);
    }

    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }

    fclose(fh);

    int total_lines = 0;
    for (int i = 0; i < NUM_THREADS; i++) {
        total_lines += line_counts[i];
    }

    return total_lines;
}

int testLanguages(void) {
    TitleLanguages *languages = NULL;
    int line_count = 0;

    line_count = readAkasWithThreads("imdb/title.akas.tsv", &languages);

    printf("Processed %d lines\n", line_count);

    printf("First and last 4 lines processed:\n");
    for (int i = 0; i < line_count; i++) {
        if (i < 4) {
            printf("Line %d: %s, %d, %s, %s, %s, %s, %d\n", i + 1, 
                   languages[i].titleId, 
                   languages[i].ordering, 
                   languages[i].title, 
                   languages[i].region, 
                   languages[i].language, 
                   languages[i].types, 
                   languages[i].isOriginalTitle);
        }
        if (i >= line_count - 4) {
            printf("Line %d: %s, %d, %s, %s, %s, %s, %d\n", i + 1, 
                   languages[i].titleId, 
                   languages[i].ordering, 
                   languages[i].title, 
                   languages[i].region, 
                   languages[i].language, 
                   languages[i].types, 
                   languages[i].isOriginalTitle);
        }
    }

    for (int i = 0; i < line_count; i++) {
        free(languages[i].titleId);
        free(languages[i].title);
        free(languages[i].region);
        free(languages[i].language);
        free(languages[i].types);
        free(languages[i].attributes);
    }
    free(languages);

    return 0;
}