Added space reservation
This commit is contained in:
parent
a260002a6c
commit
af34a9c260
@ -177,12 +177,13 @@ result_t import_backing(char** _backing, const char* disk) {
|
|||||||
|
|
||||||
if (info.backing_path != NULL) {
|
if (info.backing_path != NULL) {
|
||||||
// Get the backing identifier of the parent
|
// Get the backing identifier of the parent
|
||||||
|
errno = 0;
|
||||||
char* backing = strdup(basename(info.backing_path));
|
char* backing = strdup(basename(info.backing_path));
|
||||||
if (backing == NULL) {
|
if (backing == NULL) {
|
||||||
free_disk_info(&info);
|
free_disk_info(&info);
|
||||||
remove(temp_path);
|
remove(temp_path);
|
||||||
free(temp_path);
|
free(temp_path);
|
||||||
return failure("Failed to get the backing identifier of the parent.");
|
return failure("Failed to get the backing identifier of the parent of '%s' (%s).", disk, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the backing exists
|
// Check that the backing exists
|
||||||
@ -406,13 +407,14 @@ result_t get_backing_parent(char** _parent, const char* backing) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the backing identifier of the parent
|
// Get the backing identifier of the parent
|
||||||
|
errno = 0;
|
||||||
char* parent = strdup(basename(info.backing_path));
|
char* parent = strdup(basename(info.backing_path));
|
||||||
|
|
||||||
// Free the disk info as it is not needed anymore
|
// Free the disk info as it is not needed anymore
|
||||||
free_disk_info(&info);
|
free_disk_info(&info);
|
||||||
|
|
||||||
if (parent == NULL)
|
if (parent == NULL)
|
||||||
return failure("Failed to get the backing identifier of the parent.");
|
return failure("Failed to get the backing identifier of the parent of '%s' (%s).", backing, strerror(errno));
|
||||||
|
|
||||||
*_parent = parent;
|
*_parent = parent;
|
||||||
return success();
|
return success();
|
||||||
|
142
src/container.c
142
src/container.c
@ -9,6 +9,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
result_t check_container_identifier(const char* container) {
|
result_t check_container_identifier(const char* container) {
|
||||||
// Check that the container identifier is not null
|
// Check that the container identifier is not null
|
||||||
@ -271,14 +273,152 @@ result_t get_container_backing(char** _backing, const char* container) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the backing identifier
|
// Get the backing identifier
|
||||||
|
errno = 0;
|
||||||
char* backing = strdup(basename(info.backing_path));
|
char* backing = strdup(basename(info.backing_path));
|
||||||
|
|
||||||
// Free the disk information as it is no longer needed
|
// Free the disk information as it is no longer needed
|
||||||
free_disk_info(&info);
|
free_disk_info(&info);
|
||||||
|
|
||||||
if (backing == NULL)
|
if (backing == NULL)
|
||||||
return failure("Failed to get backing identifier for container '%s'.", container);
|
return failure("Failed to get backing identifier for container '%s' (%s).", container, strerror(errno));
|
||||||
|
|
||||||
*_backing = backing;
|
*_backing = backing;
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_t get_container_info(disk_info_t* _info, const char* container) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
_info->size = 0;
|
||||||
|
_info->allocated = 0;
|
||||||
|
_info->backing_path = NULL;
|
||||||
|
|
||||||
|
// Check that the container exists
|
||||||
|
result_t result = check_container_exists(container);
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Get the container path
|
||||||
|
char* path;
|
||||||
|
result = get_container_path(&path, container);
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Get the disk information
|
||||||
|
result = get_disk_info(_info, path);
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result_t get_oldest_container(char** _container) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_container = NULL;
|
||||||
|
|
||||||
|
// List the containers
|
||||||
|
char** containers;
|
||||||
|
result_t result = list_containers(&containers);
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Find the oldest container
|
||||||
|
char* oldest_container = NULL;
|
||||||
|
time_t oldest_time = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; containers[i] != NULL; i++) {
|
||||||
|
// Get the container path
|
||||||
|
char* path;
|
||||||
|
result = get_container_path(&path, containers[i]);
|
||||||
|
if (result != success())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get information about the container file
|
||||||
|
struct stat st;
|
||||||
|
errno = 0;
|
||||||
|
if (stat(path, &st) != 0) {
|
||||||
|
free(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the container is older than the current oldest
|
||||||
|
if (oldest_container == NULL || st.st_mtime < oldest_time) {
|
||||||
|
oldest_container = containers[i];
|
||||||
|
oldest_time = st.st_mtime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duplicate the oldest container
|
||||||
|
if (oldest_container != NULL) {
|
||||||
|
errno = 0;
|
||||||
|
*_container = strdup(oldest_container);
|
||||||
|
if (*_container == NULL) {
|
||||||
|
for (size_t i = 0; containers[i] != NULL; i++)
|
||||||
|
free(containers[i]);
|
||||||
|
free(containers);
|
||||||
|
return failure("Failed to allocate memory for the oldest container (%s).", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the containers
|
||||||
|
for (size_t i = 0; containers[i] != NULL; i++)
|
||||||
|
free(containers[i]);
|
||||||
|
free(containers);
|
||||||
|
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
|
result_t get_container_pool_space(uint64_t* _space) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_space = 0;
|
||||||
|
|
||||||
|
// Get the container pool path
|
||||||
|
char* pool_path;
|
||||||
|
result_t result = get_container_pool_path(&pool_path);
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Get the space of the container pool
|
||||||
|
struct statvfs st;
|
||||||
|
errno = 0;
|
||||||
|
if (statvfs(pool_path, &st) != 0) {
|
||||||
|
free(pool_path);
|
||||||
|
return failure("Failed to get space of container pool (%s).", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
*_space = st.f_bsize * st.f_bavail;
|
||||||
|
|
||||||
|
free(pool_path);
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
|
result_t reserve_container_pool_space(uint64_t size) {
|
||||||
|
// As long as there is not enough space in the container pool, remove the oldest container
|
||||||
|
while (true) {
|
||||||
|
// Get the available space in the container pool
|
||||||
|
uint64_t space;
|
||||||
|
result_t result = get_container_pool_space(&space);
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Check if there is enough space
|
||||||
|
if (space >= size)
|
||||||
|
return success();
|
||||||
|
|
||||||
|
// Get the oldest container
|
||||||
|
char* container;
|
||||||
|
result = get_oldest_container(&container);
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (container == NULL)
|
||||||
|
return success(); // No more containers to remove
|
||||||
|
|
||||||
|
// Remove the oldest container
|
||||||
|
result = remove_container(container);
|
||||||
|
|
||||||
|
free(container);
|
||||||
|
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "disk.h"
|
||||||
|
|
||||||
#define CONTAINER_IDENTIFIER_MAX_LENGTH 64
|
#define CONTAINER_IDENTIFIER_MAX_LENGTH 64
|
||||||
|
|
||||||
@ -67,3 +68,24 @@ result_t list_containers(char*** _containers);
|
|||||||
/// @param container The container to get the backing of.
|
/// @param container The container to get the backing of.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t get_container_backing(char** _backing, const char* container);
|
result_t get_container_backing(char** _backing, const char* container);
|
||||||
|
|
||||||
|
/// @brief Gets information about the given container. If the container does not exist, the call will return a failure result with an error message.
|
||||||
|
/// @param _info The string pointer to store the resulting disk information in. The caller is responsible for freeing the string.
|
||||||
|
/// @param container The container to get information about.
|
||||||
|
/// @return The result of the operation.
|
||||||
|
result_t get_container_info(disk_info_t* _info, const char* container);
|
||||||
|
|
||||||
|
/// @brief Gets the oldest container in the pool.
|
||||||
|
/// @param _container The string pointer to store the resulting container in. The caller is responsible for freeing the string.
|
||||||
|
/// @return The result of the operation.
|
||||||
|
result_t get_oldest_container(char** _container);
|
||||||
|
|
||||||
|
/// @brief Gets the available space in the pool.
|
||||||
|
/// @param _space The string pointer to store the resulting space in, in bytes. The caller is responsible for freeing the string.
|
||||||
|
/// @return The result of the operation.
|
||||||
|
result_t get_container_pool_space(uint64_t* _space);
|
||||||
|
|
||||||
|
/// @brief Reserves the given space in the pool. If the pool does not have enough space, the oldest containers will be removed to make space.
|
||||||
|
/// @param size The size to reserve, in bytes.
|
||||||
|
/// @return The result of the operation.
|
||||||
|
result_t reserve_container_pool_space(uint64_t size);
|
@ -273,10 +273,11 @@ result_t get_disk_info(disk_info_t* _info, const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Duplicate the backing path string
|
// Duplicate the backing path string
|
||||||
|
errno = 0;
|
||||||
backing_path = strdup(backing_str);
|
backing_path = strdup(backing_str);
|
||||||
if (backing_path == NULL) {
|
if (backing_path == NULL) {
|
||||||
json_object_put(root);
|
json_object_put(root);
|
||||||
return failure("Failed to allocate memory for the backing path.");
|
return failure("Failed to allocate memory for the backing path (%s).", strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,9 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Parse commands from the command line
|
// TODO: Parse commands from the command line
|
||||||
|
char* container;
|
||||||
|
get_oldest_container(&container);
|
||||||
|
printf("Oldest container: %s\n", container);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_help(int argc, char* argv[]) {
|
int command_help(int argc, char* argv[]) {
|
||||||
|
@ -202,6 +202,7 @@ result_t execute(int* _exit_code, char** _stdoutbuf, char** _stderrbuf, const ch
|
|||||||
va_start(args, executable);
|
va_start(args, executable);
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
|
errno = 0;
|
||||||
argv[i] = strdup(va_arg(args, const char*));
|
argv[i] = strdup(va_arg(args, const char*));
|
||||||
if (argv[i] == NULL) {
|
if (argv[i] == NULL) {
|
||||||
for (int j = 0; j < i; j++)
|
for (int j = 0; j < i; j++)
|
||||||
@ -511,13 +512,14 @@ result_t list_files(char*** _files, const char* path, bool (*filter)(const char*
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Add the entry to the files array
|
// Add the entry to the files array
|
||||||
|
errno = 0;
|
||||||
files[length] = strdup(entry->d_name);
|
files[length] = strdup(entry->d_name);
|
||||||
if (files[length] == NULL) {
|
if (files[length] == NULL) {
|
||||||
for (size_t i = 0; i < length; i++)
|
for (size_t i = 0; i < length; i++)
|
||||||
free(files[i]);
|
free(files[i]);
|
||||||
free(files);
|
free(files);
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
return failure("Failed to allocate memory for the file name.");
|
return failure("Failed to allocate memory for the file name (%s).", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
length++;
|
length++;
|
||||||
|
Loading…
Reference in New Issue
Block a user