* Did something useful while waiting at IAD: reference scanning is now
much faster.
This commit is contained in:
		
							parent
							
								
									9311ab76a5
								
							
						
					
					
						commit
						b7f008fc35
					
				
					 5 changed files with 52 additions and 31 deletions
				
			
		| 
						 | 
					@ -1390,10 +1390,7 @@ void DerivationGoal::computeClosure()
 | 
				
			||||||
	   in it. */
 | 
						   in it. */
 | 
				
			||||||
        PathSet references;
 | 
					        PathSet references;
 | 
				
			||||||
        if (!pathExists(path + "/nix-support/no-scan")) {
 | 
					        if (!pathExists(path + "/nix-support/no-scan")) {
 | 
				
			||||||
            Paths references2;
 | 
					            references = scanForReferences(path, allPaths);
 | 
				
			||||||
            references2 = filterReferences(path, 
 | 
					 | 
				
			||||||
                Paths(allPaths.begin(), allPaths.end()));
 | 
					 | 
				
			||||||
            references = PathSet(references2.begin(), references2.end());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* For debugging, print out the referenced and
 | 
					            /* For debugging, print out the referenced and
 | 
				
			||||||
               unreferenced paths. */
 | 
					               unreferenced paths. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,26 +11,45 @@
 | 
				
			||||||
#include "hash.hh"
 | 
					#include "hash.hh"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned int refLength = 32; /* characters */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void search(const string & s,
 | 
					static void search(const string & s,
 | 
				
			||||||
    Strings & ids, Strings & seen)
 | 
					    StringSet & ids, StringSet & seen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for (Strings::iterator i = ids.begin();
 | 
					    static bool initialised = false;
 | 
				
			||||||
         i != ids.end(); )
 | 
					    static bool isBase32[256];
 | 
				
			||||||
    {
 | 
					    if (!initialised) {
 | 
				
			||||||
        checkInterrupt();
 | 
					        for (unsigned int i = 0; i < 256; ++i) isBase32[i] = false;
 | 
				
			||||||
        if (s.find(*i) == string::npos)
 | 
					        for (unsigned int i = 0; i < base32Chars.size(); ++i)
 | 
				
			||||||
            i++;
 | 
					            isBase32[(unsigned char) base32Chars[i]] = true;
 | 
				
			||||||
        else {
 | 
					        initialised = true;
 | 
				
			||||||
            debug(format("found reference to `%1%'") % *i);
 | 
					 | 
				
			||||||
            seen.push_back(*i);
 | 
					 | 
				
			||||||
            i = ids.erase(i);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for (unsigned int i = 0; i + refLength <= s.size(); ) {
 | 
				
			||||||
 | 
					        int j;
 | 
				
			||||||
 | 
					        bool match = true;
 | 
				
			||||||
 | 
					        for (j = refLength - 1; j >= 0; --j)
 | 
				
			||||||
 | 
					            if (!isBase32[(unsigned char) s[i + j]]) {
 | 
				
			||||||
 | 
					                i += j + 1;
 | 
				
			||||||
 | 
					                match = false;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        if (!match) continue;
 | 
				
			||||||
 | 
					        string ref(s, i, refLength);
 | 
				
			||||||
 | 
					        if (ids.find(ref) != ids.end()) {
 | 
				
			||||||
 | 
					            debug(format("found reference to `%1%' at offset `%2%'")
 | 
				
			||||||
 | 
					                  % ref % i);
 | 
				
			||||||
 | 
					            seen.insert(ref);
 | 
				
			||||||
 | 
					            ids.erase(ref);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ++i;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void checkPath(const string & path,
 | 
					void checkPath(const string & path,
 | 
				
			||||||
    Strings & ids, Strings & seen)
 | 
					    StringSet & ids, StringSet & seen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    checkInterrupt();
 | 
					    checkInterrupt();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -69,36 +88,35 @@ void checkPath(const string & path,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Strings filterReferences(const string & path, const Strings & paths)
 | 
					PathSet scanForReferences(const string & path, const PathSet & paths)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    map<string, string> backMap;
 | 
					    map<string, Path> backMap;
 | 
				
			||||||
    Strings ids;
 | 
					    StringSet ids;
 | 
				
			||||||
    Strings seen;
 | 
					    StringSet seen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* For efficiency (and a higher hit rate), just search for the
 | 
					    /* For efficiency (and a higher hit rate), just search for the
 | 
				
			||||||
       hash part of the file name.  (This assumes that all references
 | 
					       hash part of the file name.  (This assumes that all references
 | 
				
			||||||
       have the form `HASH-bla'). */
 | 
					       have the form `HASH-bla'). */
 | 
				
			||||||
    for (Strings::const_iterator i = paths.begin();
 | 
					    for (PathSet::const_iterator i = paths.begin(); i != paths.end(); i++) {
 | 
				
			||||||
         i != paths.end(); i++)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        string baseName = baseNameOf(*i);
 | 
					        string baseName = baseNameOf(*i);
 | 
				
			||||||
        unsigned int pos = baseName.find('-');
 | 
					        unsigned int pos = baseName.find('-');
 | 
				
			||||||
        if (pos == string::npos)
 | 
					        if (pos == string::npos)
 | 
				
			||||||
            throw Error(format("bad reference `%1%'") % *i);
 | 
					            throw Error(format("bad reference `%1%'") % *i);
 | 
				
			||||||
        string s = string(baseName, 0, pos);
 | 
					        string s = string(baseName, 0, pos);
 | 
				
			||||||
 | 
					        assert(s.size() == refLength);
 | 
				
			||||||
 | 
					        assert(backMap.find(s) == backMap.end());
 | 
				
			||||||
        // parseHash(htSHA256, s);
 | 
					        // parseHash(htSHA256, s);
 | 
				
			||||||
        ids.push_back(s);
 | 
					        ids.insert(s);
 | 
				
			||||||
        backMap[s] = *i;
 | 
					        backMap[s] = *i;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    checkPath(path, ids, seen);
 | 
					    checkPath(path, ids, seen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Strings found;
 | 
					    PathSet found;
 | 
				
			||||||
    for (Strings::iterator i = seen.begin(); i != seen.end(); i++)
 | 
					    for (StringSet::iterator i = seen.begin(); i != seen.end(); i++) {
 | 
				
			||||||
    {
 | 
					        map<string, Path>::iterator j;
 | 
				
			||||||
        map<string, string>::iterator j;
 | 
					 | 
				
			||||||
        if ((j = backMap.find(*i)) == backMap.end()) abort();
 | 
					        if ((j = backMap.find(*i)) == backMap.end()) abort();
 | 
				
			||||||
        found.push_back(j->second);
 | 
					        found.insert(j->second);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return found;
 | 
					    return found;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
#include "util.hh"
 | 
					#include "util.hh"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Strings filterReferences(const Path & path, const Strings & refs);
 | 
					PathSet scanForReferences(const Path & path, const PathSet & refs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* !__REFERENCES_H */
 | 
					#endif /* !__REFERENCES_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,7 +109,7 @@ static unsigned char divMod(unsigned char * bytes, unsigned char y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// omitted: E O U T
 | 
					// omitted: E O U T
 | 
				
			||||||
char chars[] = "0123456789abcdfghijklmnpqrsvwxyz";
 | 
					const string base32Chars = "0123456789abcdfghijklmnpqrsvwxyz";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
string printHash32(const Hash & hash)
 | 
					string printHash32(const Hash & hash)
 | 
				
			||||||
| 
						 | 
					@ -117,6 +117,8 @@ string printHash32(const Hash & hash)
 | 
				
			||||||
    Hash hash2(hash);
 | 
					    Hash hash2(hash);
 | 
				
			||||||
    unsigned int len = (hash.hashSize * 8 - 1) / 5 + 1;
 | 
					    unsigned int len = (hash.hashSize * 8 - 1) / 5 + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char * chars = base32Chars.c_str();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    string s(len, '0');
 | 
					    string s(len, '0');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int pos = len - 1;
 | 
					    int pos = len - 1;
 | 
				
			||||||
| 
						 | 
					@ -165,6 +167,8 @@ Hash parseHash32(HashType ht, const string & s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Hash hash(ht);
 | 
					    Hash hash(ht);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char * chars = base32Chars.c_str();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (unsigned int i = 0; i < s.length(); ++i) {
 | 
					    for (unsigned int i = 0; i < s.length(); ++i) {
 | 
				
			||||||
        char c = s[i];
 | 
					        char c = s[i];
 | 
				
			||||||
        unsigned char digit;
 | 
					        unsigned char digit;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,8 @@ const int md5HashSize = 16;
 | 
				
			||||||
const int sha1HashSize = 20;
 | 
					const int sha1HashSize = 20;
 | 
				
			||||||
const int sha256HashSize = 32;
 | 
					const int sha256HashSize = 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const string base32Chars;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Hash
 | 
					struct Hash
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue