sapling/remotefilelog/ctreemanifest/treemanifest.cpp
Tony Tung a6bc389217 [ctree] free memory when destroying a treemanifest object
Summary: Everyone who holds heap-allocated memory gets destructors!

Test Plan: valgrind and confirmed no memory leaking from ctreemanifest

Reviewers: #fastmanifest, durham

Reviewed By: durham

Subscribers: mitrandir

Differential Revision: https://phabricator.intern.facebook.com/D3763327

Tasks: 12818084

Signature: t1:3763327:1472105103:8ac9d9694be4bf3b09e19e4381737622c94a2dac
2016-08-26 14:00:37 -07:00

89 lines
2.6 KiB
C++

// treemanifest.cpp - c++ implementation of a tree manifest
//
// Copyright 2016 Facebook, Inc.
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
//
// no-check-code
#include "treemanifest.h"
treemanifest::~treemanifest() {
if (this->rootManifest != NULL) {
delete this->rootManifest;
}
}
void _treemanifest_find(
const std::string &filename,
const std::string &rootnode,
Manifest **cachedlookup,
const ManifestFetcher &fetcher,
std::string *resultnode, char *resultflag) {
size_t curpathlen = 0;
std::string curnode(rootnode);
// Loop over the parts of the query filename
PathIterator pathiter(filename);
const char *word;
size_t wordlen;
while (pathiter.next(&word, &wordlen)) {
if (*cachedlookup == NULL) {
// Obtain the raw data for this directory
*cachedlookup = fetcher.get(filename.c_str(), curpathlen, curnode);
}
Manifest *manifest = *cachedlookup;
ManifestIterator mfiterator = manifest->getIterator();
ManifestEntry *entry;
bool recurse = false;
// Loop over the contents of the current directory looking for the
// next directory/file.
while ((entry = mfiterator.next()) != NULL) {
// If the current entry matches the query file/directory, either recurse,
// return, or abort.
if (wordlen == entry->filenamelen &&
strncmp(word, entry->filename, wordlen) == 0) {
// If this is the last entry in the query path, either return or abort
if (pathiter.isfinished()) {
// If it's a file, it's our result
if (!entry->isdirectory()) {
resultnode->assign(binfromhex(entry->node));
if (entry->flag == NULL) {
*resultflag = '\0';
} else {
*resultflag = *entry->flag;
}
return;
} else {
// Found a directory when expecting a file - give up
break;
}
}
// If there's more in the query, either recurse or give up
curpathlen = curpathlen + wordlen + 1;
if (entry->isdirectory() && filename.length() > curpathlen) {
curnode.erase();
curnode.append(binfromhex(entry->node));
cachedlookup = &entry->resolved;
recurse = true;
break;
} else {
// Found a file when we expected a directory or
// found a directory when we expected a file.
break;
}
}
}
if (!recurse) {
// Failed to find a match
return;
}
}
}