// FileLogCache.cpp: implementation of the FileLogCache class. // ////////////////////////////////////////////////////////////////////// #include "extdll.h" #include "util.h" #include "cbase.h" #include <clientapi.h> #include "filehead.h" #include "clientloguser.h" #include "changesorter.h" #include "filelogcache.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// /* Create a new FileLogCache. After a FileLogCache has been constructed, * not much else needs to be done to it. */ FileLogCache::FileLogCache(StrBuf filepath, ClientApi* cli, Error* e) { client = cli; errors = e; client->Init( errors ); numarrows = 0; size = 1; changes = new ChangeSorter(); main = new FileHead(filepath, this); //Create the "main" FileHead. main->loc = cl_main; head = main; tail = main; from = NULL; into = NULL; client->WaitTag(); //flesh out "main" before scan! main->scanMain(); //check all revs in "main" client->Final( errors ); } FileHead* FileLogCache::AddFrom(StrBuf filepath) { size++; if (from == NULL) //If we don't have any "from" FileHeads yet: { from = new FileHead(filepath, this); from->loc = cl_from; head = from; from->next_into = main; main->next_from = from; } else { //otherwise, insert this as the new "from" FileHead* working = new FileHead(filepath, this); working->loc = cl_from; working->next = from; main->next_from = working; working->next_into = main; from->next_into = working; working->next_from = from; from = working; } return from; } /*AddInto works much like AddFrom - I don't think it needs explanation. */ FileHead* FileLogCache::AddInto(StrBuf filepath) { size++; if (into == NULL) { into = new FileHead(filepath, this); into->loc = cl_into; into->next_from = main; main->next_into = into; } else { FileHead* working = new FileHead(filepath, this); working->loc = cl_into; working->next = into; main->next_into = working; working->next_from = main; into->next_from = working; working->next_into = into; into = working; } return into; } FileHead* FileLogCache::AddAfter(StrBuf filepath, FileHead* caller) { size++; if (caller == main) return AddFrom(filepath); FileHead* working = new FileHead(filepath, this); working->loc = caller->loc; working->next = caller->next; caller->next = working; switch (caller->loc) { case cl_from: if (caller == head) head = working; working->next_from = caller->next_from; working->next_into = caller; if (caller->next_from) caller->next_from->next_into = working; caller->next_from = working; break; case cl_into: if (caller == tail) tail = working; working->next_into = caller->next_into; working->next_from = caller; if (caller->next_into) caller->next_into->next_from = working; caller->next_into = working; break; } return working; } FileHead* FileLogCache::Get(StrBuf& filepath, bool exfrom, FileHead* caller) { /* If this is a Windows server, do case insensitive compares. */ if (client->GetProtocol("nocase")) return GetI(filepath, exfrom, caller); if (main->name == filepath){ //Was it main? return main; } FileHead* working = from; //Is it in from? while (working != NULL) { if (working->name == filepath) return working; working = working->next; } working = into; //Is it in into? while (working != NULL) { if (working->name == filepath) return working; working = working->next; } /* Make a new one, then. */ if (caller == main) //If the caller was "main"... { if (exfrom) return AddFrom(filepath); else return AddInto(filepath); } else { return AddAfter(filepath, caller); } } FileHead* FileLogCache::GetI(StrBuf& filepath, bool exfrom, FileHead* caller) { if (main->name.CCompare(filepath) == 0) //Was it main? { return main; } FileHead* working = from; //Is it in from? while (working != NULL) { if (working->name.CCompare(filepath) == 0) return working; working = working->next; } working = into; //Is it in into? while (working != NULL) { if (working->name.CCompare(filepath) == 0) return working; working = working->next; } /* Make a new one, then. */ if (caller == main) //If the caller was "main"... { if (exfrom) return AddFrom(filepath); else return AddInto(filepath); } else { return AddAfter(filepath, caller); } } FileLogCache::~FileLogCache() //Clean up everything when deleting this object. { if (main != NULL) delete main; if (from != NULL) delete from; if (into != NULL) delete into; delete changes; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#13 | 1709 | Sam Stafford |
Propagate bug fix and include change from p4hltest. No functional change - P4HL never used "numarrows" so the bug doesn't affect it. |
||
#12 | 1689 | Sam Stafford |
Integrate 02.1 API and code cleanup to P4HL. Lots of work. Phew. |
||
#11 | 1600 | Sam Stafford |
Integrate case-insensitivity fix to P4HL. Integration only change. |
||
#10 | 1586 | Sam Stafford | Migrate outstanding changes into P4HL - no functional change. | ||
#9 | 1557 | Sam Stafford |
Integrate bug fix for testing. Looks good so far. |
||
#8 | 1548 | Sam Stafford |
Integrate RevType change to make sure it works. It does. |
||
#7 | 1521 | Sam Stafford |
Integrated change 1520 to P4HL. Updated CObjectFile::Expand() to use the new variable name. Infrastructure change. |
||
#6 | 1457 | Sam Stafford |
Use RunTag() to queue up filelog commands. Should in theory improve performance, although I haven't noticed any great difference. Integration only change. |
||
#5 | 1450 | Sam Stafford |
Major performance improvement - use one ClientApi connection for all filelogs. Improves querying time about tenfold on large requests! Had to move client->Final() to the constructor to ensure that connection is cleaned up promptly and doesn't hang things up. |
||
#4 | 1433 | Sam Stafford |
Integ display: if you see one of a file's revisions, you see them all. Previously, your view was limited to those revisions which were directly related to the file you asked about. However, if you asked about a file branched from the mainline, this meant that you couldn't see mainline changes that weren't yet integrated into your branch, and that's not terribly useful. |
||
#3 | 975 | Sam Stafford |
Nigh-complete fix for job 4 - the "scan" methods all go from tail to head now, and Get uses the improved "addAfter" method where appropriate. An unforeseen problem was the fact that a complex integ history can get followed through more than one possible path, causing later versions of a given file to get scanned before earlier versions, and messing up the graph. This is fixed (albeit in a kludgey fashion) in scanMain here by making two passes through the FileHead, caching the files on the first pass and actually running scans on the second pass. A slightly more efficient way of handling it might be to keep a list of FileRevs that need to be scanned - perhaps by declaring a temporary FileHead to serve as a list? Once it's been hammered out in scanMain() satisfactorily that method can be employed in the other scan methods. |
||
#2 | 974 | Sam Stafford |
Partial fixes to the sorting of a FileLogCache as it's created. FileRevs are now doubly-linked. FileHead now has a scanMain() function that acts as an interleaved scanFrom and scanInto. The next step will be to have scans go from #1 to #head (this is why FileRevs are now doubly linked). |
||
#1 | 937 | Sam Stafford |
Renaming my guest directory to the more conventional sam_stafford. |
||
//guest/samwise/p4hl/src/dlls/FileLogCache.cpp | |||||
#1 | 936 | Sam Stafford |
Adding P4HL to the public depot. See relnotes.txt for installation instructions; all relevant files are under p4hl/dist. Source code is under p4hl/src in the form of a VC++ project. |