fix bug related to FileId use; now safer due to separate node_from_id function
This was SVN commit r3605.
This commit is contained in:
parent
4b3997f1f6
commit
6e15ed1e82
@ -233,16 +233,16 @@ struct FileNode
|
||||
{
|
||||
const char* atom_fn;
|
||||
|
||||
FileId prev : 15;
|
||||
FileId prev_id;
|
||||
FileId next_id;
|
||||
u32 visited : 1;
|
||||
FileId next : 15;
|
||||
u32 output : 1;
|
||||
|
||||
FileNode(const char* atom_fn_)
|
||||
{
|
||||
atom_fn = atom_fn_;
|
||||
|
||||
prev = next = NULL_ID;
|
||||
prev_id = next_id = NULL_ID;
|
||||
visited = output = 0;
|
||||
}
|
||||
};
|
||||
@ -276,6 +276,12 @@ public:
|
||||
return id;
|
||||
}
|
||||
|
||||
FileNode* node_from_id(FileId id) const
|
||||
{
|
||||
debug_assert(id != NULL_ID);
|
||||
return &(*nodes)[id-1];
|
||||
}
|
||||
|
||||
FileId id_from_fn(const char* atom_fn) const
|
||||
{
|
||||
Map::const_iterator cit = map.find(atom_fn);
|
||||
@ -567,25 +573,22 @@ class TourBuilder
|
||||
}
|
||||
};
|
||||
|
||||
// not const because we change the graph-related members
|
||||
FileNodes& file_nodes;
|
||||
|
||||
bool has_cycle;
|
||||
void detect_cycleR(FileId node)
|
||||
void detect_cycleR(FileId id)
|
||||
{
|
||||
FileNode* pnode = &file_nodes[node];
|
||||
FileNode* pnode = id_mgr.node_from_id(id);
|
||||
pnode->visited = 1;
|
||||
FileId next = pnode->next;
|
||||
if(next != NULL_ID)
|
||||
FileId next_id = pnode->next_id;
|
||||
if(next_id != NULL_ID)
|
||||
{
|
||||
FileNode* pnext = &file_nodes[next];
|
||||
FileNode* pnext = id_mgr.node_from_id(next_id);
|
||||
if(pnext->visited)
|
||||
has_cycle = true;
|
||||
else
|
||||
detect_cycleR(next);
|
||||
detect_cycleR(next_id);
|
||||
}
|
||||
}
|
||||
bool is_cycle_at(FileId node)
|
||||
bool is_cycle_at(FileNodes& file_nodes, FileId node)
|
||||
{
|
||||
has_cycle = false;
|
||||
for(FileNodes::iterator it = file_nodes.begin(); it != file_nodes.end(); ++it)
|
||||
@ -594,36 +597,34 @@ class TourBuilder
|
||||
return has_cycle;
|
||||
}
|
||||
|
||||
void try_add_edge(const Connection& c)
|
||||
void try_add_edge(FileNodes& file_nodes, const Connection& c)
|
||||
{
|
||||
FileId first_id = cid_first(c.id);
|
||||
FileId second_id = cid_second(c.id);
|
||||
|
||||
FileNode& first = file_nodes[first_id];
|
||||
FileNode& second = file_nodes[second_id];
|
||||
FileNode* first = id_mgr.node_from_id(first_id);
|
||||
FileNode* second = id_mgr.node_from_id(second_id);
|
||||
// one of them has already been hooked up - bail
|
||||
if(first.next != NULL_ID || second.prev != NULL_ID)
|
||||
if(first->next_id != NULL_ID || second->prev_id != NULL_ID)
|
||||
return;
|
||||
|
||||
first.next = second_id;
|
||||
second.prev = first_id;
|
||||
first->next_id = second_id;
|
||||
second->prev_id = first_id;
|
||||
|
||||
const bool introduced_cycle = is_cycle_at(second_id);
|
||||
debug_assert(introduced_cycle == is_cycle_at(first_id));
|
||||
const bool introduced_cycle = is_cycle_at(file_nodes, second_id);
|
||||
debug_assert(introduced_cycle == is_cycle_at(file_nodes, first_id));
|
||||
if(introduced_cycle)
|
||||
{
|
||||
// undo
|
||||
first.next = second.prev = NULL_ID;
|
||||
first->next_id = second->prev_id = NULL_ID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// pointer to this is returned by TourBuilder()!
|
||||
std::vector<const char*>& fn_vector;
|
||||
|
||||
void output_chain(FileNode& node)
|
||||
void output_chain(FileNode& node, std::vector<const char*>& fn_vector)
|
||||
{
|
||||
// early out: if this access was already visited, so must the entire
|
||||
// early out: if this access was already visited, so must the entire
|
||||
// chain of which it is a part. bail to save lots of time.
|
||||
if(node.output)
|
||||
return;
|
||||
@ -631,34 +632,34 @@ class TourBuilder
|
||||
// follow prev links starting with c until no more are left;
|
||||
// start ends up the beginning of the chain including <c>.
|
||||
FileNode* start = &node;
|
||||
while(start->prev != NULL_ID)
|
||||
start = &file_nodes[start->prev];
|
||||
while(start->prev_id != NULL_ID)
|
||||
start = id_mgr.node_from_id(start->prev_id);
|
||||
|
||||
// iterate over the chain - add to Filenames list and mark as visited
|
||||
FileNode* cur = start;
|
||||
do
|
||||
for(;;)
|
||||
{
|
||||
if(!cur->output)
|
||||
{
|
||||
fn_vector.push_back(cur->atom_fn);
|
||||
cur->output = 1;
|
||||
}
|
||||
cur = &file_nodes[cur->next];
|
||||
if(cur->next_id == NULL_ID)
|
||||
break;
|
||||
cur = id_mgr.node_from_id(cur->next_id);
|
||||
}
|
||||
while(cur->next != NULL_ID);
|
||||
}
|
||||
|
||||
public:
|
||||
TourBuilder(FileNodes& file_nodes_, Connections& connections, std::vector<const char*>& fns_)
|
||||
: file_nodes(file_nodes_), fn_vector(fns_)
|
||||
TourBuilder(FileNodes& file_nodes, Connections& connections, std::vector<const char*>& fn_vector)
|
||||
{
|
||||
std::sort(connections.begin(), connections.end(), Occurrence_greater());
|
||||
std::stable_sort(connections.begin(), connections.end(), Occurrence_greater());
|
||||
|
||||
for(Connections::iterator it = connections.begin(); it != connections.end(); ++it)
|
||||
try_add_edge(*it);
|
||||
try_add_edge(file_nodes, *it);
|
||||
|
||||
for(FileNodes::iterator it = file_nodes.begin(); it != file_nodes.end(); ++it)
|
||||
output_chain(*it);
|
||||
output_chain(*it, fn_vector);
|
||||
}
|
||||
|
||||
// should never be copied; this also squelches warning
|
||||
@ -705,12 +706,6 @@ archive.insert(atom_fn);
|
||||
static bool should_rebuild_main_archive(const char* P_archive_path,
|
||||
const char* trace_filename)
|
||||
{
|
||||
std::vector<const char*> diff;
|
||||
set_difference(loose.begin(), loose.end(), archive.begin(), archive.end(), back_inserter(diff));
|
||||
debug_printf("loose only:\n");
|
||||
for(std::vector<const char*>::iterator it = diff.begin(); it != diff.end(); ++it)
|
||||
debug_printf("%s\n", *it);
|
||||
|
||||
// if there's no trace file, no point in building a main archive.
|
||||
struct stat s;
|
||||
if(file_stat(trace_filename, &s) != ERR_OK)
|
||||
@ -720,7 +715,6 @@ static bool should_rebuild_main_archive(const char* P_archive_path,
|
||||
if(s.st_mtime >= vfs_mtime)
|
||||
trace_enable(false);
|
||||
|
||||
|
||||
const ssize_t loose_files_only = loose_file_total - non_loose_file_total;
|
||||
if(loose_files_only >= REBUILD_MAIN_ARCHIVE_THRESHOLD)
|
||||
return true;
|
||||
@ -761,6 +755,7 @@ static void vfs_opt_init(const char* P_archive_fn_fmt, const char* trace_filenam
|
||||
fn_vector.push_back(0);
|
||||
Filenames V_fns = &fn_vector[0];
|
||||
|
||||
|
||||
char archive_fn[PATH_MAX];
|
||||
static NextNumberedFilenameInfo archive_nfi;
|
||||
next_numbered_filename(P_archive_fn_fmt, &archive_nfi, archive_fn, false);
|
||||
|
Loading…
Reference in New Issue
Block a user