/* File caching.
Copyright (C) 2023-2025 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
. */
#ifndef GCC_LTO_LTRANS_CACHE_H
#define GCC_LTO_LTRANS_CACHE_H
#include "lockfile.h"
using checksum_t = std::array;
class ltrans_file_cache
{
public:
/* Cache item representing input/output filename pair. */
struct item
{
item (std::string input, std::string output,
checksum_t input_checksum, uint32_t last_used);
~item ();
/* Full path to input filename. */
const std::string input;
/* Full path to output filename. */
const std::string output;
/* Checksum of input file. */
const checksum_t input_checksum;
/* Larger last_used corresponds to later usage. */
uint32_t last_used;
/* Lockfile so that output file can be created later than input file. */
lockfile lock;
};
/* Constructor. Resulting cache item filenames will be
in format `prefix%d[.ltrans]suffix`. */
ltrans_file_cache (const char* dir, const char* prefix, const char* suffix,
size_t soft_cache_size);
/* Destructor. */
~ltrans_file_cache ();
/* Loads data about previously cached items from cachedata file.
Must be called with creation_lock or deletion_lock held to
prevent data race. */
void load_cache ();
/* Rewrites data about cache items into cachedata file.
Must be only called when creation_lock or deletion_lock was held since last
call to load_cache. */
void save_cache ();
/* Adds input file into cache. Cache item with input file identical to
added input file will be returned as _item.
If the file was already cached, `true` is returned, `false` otherwise.
The added input file is deleted (or moved).
Must be called with creation_lock held to prevent data race. */
bool add_to_cache (const char* filename, item*& _item);
/* If exists, returns cache item corresponding to cached input file. */
item* get_item (const char* input);
/* If no other process holds the deletion_lock, prunes oldest unused cache
items over limit. */
void try_prune ();
/* Clears cache class, as if only constructor was called. */
void cleanup ();
/* Cache is enabled if true. */
operator bool ()
{
return dir;
}
/* Access to already created items can be concurrent with item creation. */
lockfile creation_lock;
/* Access to already created items cannot be concurrent
with item deletion. */
lockfile deletion_lock;
/* Directory of cache. NULL if cache is disabled. */
const char* dir;
private:
/* Adds given cache item to all relevant datastructures. */
void add_item (item* item);
/* Creates new cache item with given checksum.
New input/output files are chosen to not collide with other items.
Must be called with creation_lock held to prevent data race. */
item* create_item (const checksum_t& checksum);
/* Prunes oldest unused cache items over limit.
Must be called with deletion_lock held to prevent data race. */
void prune ();
/* Creates cachedata filename for save/load. */
std::string filename_cachedata ();
/* All cache items in current cache. */
std::vector- items;
std::map map_checksum;
std::map map_input;
/* Cached filenames are in format "prefix%d[.ltrans]suffix". */
const char* prefix;
const char* suffix;
/* If cache items count is larger, prune deletes old items. */
size_t soft_cache_size;
/* Counter used to populate last_used of items. */
uint32_t usage_counter;
/* String in format "dir/prefix". */
std::string cache_prefix;
/* Lower indices are occupied. */
uint32_t cache_free_idx;
/* Buffer for sprintf. */
char* str_buffer;
};
#endif