dvd files
wget https://git.christianimmanuel.de/games/dvd/archive/dvd.tar.gztest_1.c raw
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
// ANSI color codes
#define RESET "\033[0m"
#define RED "\033[31m"
#define GREEN "\033[32m"
#define YELLOW "\033[33m"
#define BLUE "\033[34m"
#define MAGENTA "\033[35m"
#define CYAN "\033[36m"
#define WHITE "\033[37m"
#define MAX_LINE_LENGTH 1024
#define NUM_THREADS 4
// Define the struct to hold the parsed data for each line
typedef struct {
char *titleId; // Dynamically allocated
int ordering;
char *title; // Dynamically allocated
char *region; // Dynamically allocated
char *language; // Dynamically allocated
char *types; // Dynamically allocated
char *attributes; // Dynamically allocated
int isOriginalTitle;
} TitleLanguages;
typedef struct {
FILE *fh;
long start_offset;
long end_offset;
TitleLanguages **parsed_lines;
int *line_count;
int thread_id;
} ThreadArgs;
char *strdup(const char *s);
// Function to read and store all lines (as strings)
void *processAkaLinesThread(void *args) {
ThreadArgs *thread_args = (ThreadArgs *)args;
FILE *fh = thread_args->fh;
long start_offset = thread_args->start_offset;
long end_offset = thread_args->end_offset;
TitleLanguages **parsed_lines = thread_args->parsed_lines;
int *line_count = thread_args->line_count;
printf(MAGENTA "┌──────────────────────────────────────\n└── " CYAN "Starting Thread" YELLOW " %d\n" RESET, thread_args->thread_id);
// Set the file pointer to the start_offset position
fseek(fh, start_offset, SEEK_SET);
char line[MAX_LINE_LENGTH]; // Buffer for each line
int alloc_size = 10; // Initial memory allocation size
*parsed_lines = malloc(alloc_size * sizeof(TitleLanguages)); // Allocate memory for the array of TitleLanguages structs
if (!*parsed_lines) {
perror("Memory allocation failed");
return NULL;
}
// Read lines until we reach the end_offset
while (ftell(fh) < end_offset && fgets(line, sizeof(line), fh)) {
// Remove newline character from line
line[strcspn(line, "\n")] = 0;
// If we've reached the allocated size, reallocate more memory for TitleLanguages array
if (*line_count >= alloc_size) {
alloc_size *= 2; // Double the allocated size
*parsed_lines = realloc(*parsed_lines, alloc_size * sizeof(TitleLanguages));
if (!*parsed_lines) {
perror("Memory reallocation failed");
return NULL;
}
}
TitleLanguages *current_line = &(*parsed_lines)[*line_count];
// Parse the fields from the line and directly store them into the struct
current_line->titleId = strdup(strtok(line, "\t"));
current_line->ordering = atoi(strtok(NULL, "\t"));
current_line->title = strdup(strtok(NULL, "\t"));
current_line->region = strdup(strtok(NULL, "\t"));
current_line->language = strdup(strtok(NULL, "\t"));
current_line->types = strdup(strtok(NULL, "\t"));
current_line->attributes = strdup(strtok(NULL, "\t"));
current_line->isOriginalTitle = atoi(strtok(NULL, "\t"));
// If any memory allocation fails, free all previously allocated memory
if (!current_line->titleId || !current_line->title || !current_line->region ||
!current_line->language || !current_line->types || !current_line->attributes) {
perror("Memory allocation failed");
return NULL;
}
(*line_count)++;
}
return NULL;
}
// Function to read the Akas file and process lines
int readAkas(TitleLanguages **languages) {
FILE *fh = NULL;
// Open the file specified by the constant FILENAME
fh = fopen("imdb/title.akas.tsv", "r");
if (!fh) {
perror("Error opening file");
return 1;
}
// Get the file size to divide the file into chunks for threads
fseek(fh, 0, SEEK_END);
long file_size = ftell(fh);
fclose(fh);
// Create threads to process file chunks
pthread_t threads[NUM_THREADS];
ThreadArgs thread_args[NUM_THREADS];
long chunk_size = file_size / NUM_THREADS;
TitleLanguages *merged_languages = NULL;
int merged_line_count = 0;
for (int i = 0; i < NUM_THREADS; i++) {
thread_args[i].fh = fopen("imdb/title.akas.tsv", "r");
thread_args[i].start_offset = i * chunk_size;
thread_args[i].end_offset = (i == NUM_THREADS - 1) ? file_size : (i + 1) * chunk_size;
thread_args[i].parsed_lines = malloc(sizeof(TitleLanguages *));
if (!thread_args[i].parsed_lines) {
perror("Memory allocation failed for thread_args[i].parsed_lines"); exit(1); }
thread_args[i].line_count = malloc(sizeof(int));
if (!thread_args[i].line_count) {
perror("Memory allocation failed for thread_args[i].line_count"); exit(1); }
*thread_args[i].line_count = 0;
thread_args[i].thread_id = i;
pthread_create(&threads[i], NULL, processAkaLinesThread, &thread_args[i]);
}
// Join threads and combine results
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
// Merge thread results into the final languages array
for (int j = 0; j < *thread_args[i].line_count; j++) {
merged_languages = realloc(merged_languages, (merged_line_count + 1) * sizeof(TitleLanguages));
if (!merged_languages) {
perror("Memory reallocation failed");
return 1;
}
merged_languages[merged_line_count] = (*thread_args[i].parsed_lines)[j];
merged_line_count++;
}
// Clean up thread-specific memory
free(thread_args[i].parsed_lines);
free(thread_args[i].line_count);
fclose(thread_args[i].fh);
}
printf("Processing complete. Total lines read: %d\n", merged_line_count);
// Assign the merged languages back to the caller
*languages = merged_languages;
return merged_line_count;
}
int main(void) {
TitleLanguages *languages = NULL;
int line_count = 0;
// Pass the address of languages to readAkas
line_count = readAkas(&languages);
// Print the first 4 lines and last 4 lines of the struct array
printf("First and last 4 lines processed:\n");
for (int i = 0; i < line_count; i++) {
// Print first 4 lines
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);
}
// Print last 4 lines
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);
}
}
// Clean up the array of structs and the dynamically allocated strings
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;
}