// FileLogCache.cpp: implementation of the FileLogCache class. // ////////////////////////////////////////////////////////////////////// #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 ); 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) { 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) { 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) { 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 (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); } } 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 | |
---|---|---|---|---|---|
#16 | 2944 | Sam Stafford |
Add the ability to read filelog output from a text file. This functionality (if used; it's off by default) causes FLC to try to find required filelog output from a specified file before it queries the server. This can be used to fill in gaps (eg obliterated files), or more importantly, to draw graphs based on filelog output from a server you don't have access to, such as when trying to diagnose an integration problem for a customer. The filelog-parsing code hasn't been changed much, and isn't very fault-tolerant, so it might crash if fed mangled filelogs. Let the user beware. |
||
#15 | 1708 | Sam Stafford |
Initialize "numarrows" and "size" in FLC BEFORE building any FileHeads! For some reason this worked with the 01.1 API, but it probably shouldn't have anyway. Critical bug fix - must integrate to other projects. |
||
#14 | 1704 | Sam Stafford |
Change API includes to <*.h> rather than "*.h". No functional change. |
||
#13 | 1684 | Sam Stafford |
Imported new 02.1 p4api headers and libs. MAJOR code cleanup to make it fit without resorting to re-hacking of the API headers. The hacked headers were not L33T. They deserved D34TH. |
||
#12 | 1599 | Sam Stafford |
Make filename comparisons case-insensitive when running against a case-insensitive server. |
||
#11 | 1584 | Sam Stafford | New "numarrows" member of FLC to keep track of FileRevArrows. | ||
#10 | 1556 | Sam Stafford |
Undo 1540 and 1552 and do things right. Preliminary tests seem to indicate that everything works, but I've been taught to tread more cautiously in the future. Need to re-implement the error-checking to enforce the "one file per FileHead" rule. |
||
#9 | 1552 | Sam Stafford |
Quick and kludgey fix to bug introduced by change 1540. Fix probably has to do with combination of using filelog output to fill in the name of a FileHead, using tags to run filelogs asynchronously, and preloading a bunch of FileHead pointers at once. The kludge: store the name which was originally used to create the FileHead and use that in comparisons. The better fix (to be done later): call WaitTag() if needed to fill in the FileHead and get the name of the file. The problem with the current kludge is that it still won't work if the file's "oname" isn't in depot syntax, which is what change 1540 was supposed to address in the first place. Grahr. |
||
#8 | 1538 | Sam Stafford |
Add a "size" var to FileLogCache to figure out how much space will be needed to draw it. |
||
#7 | 1520 | Sam Stafford |
Make variable names slightly more sensical - expressions like "foo->file->file.Text()" look really bad. Now it's more like "fr->fh->name.Text()", which makes quite a bit more sense, at least if you're familiar with the structure. Infrastructure change. |
||
#6 | 1456 | Sam Stafford |
Use RunTag() and WaitTag() to perform filelogs asynchronously. This is risky because queueing multiple commands with RunTag() is unsupported and known to have problems, but it can also potentially cut lag time in half. |
||
#5 | 1451 | Sam Stafford |
Reverse integrate the move of client->Final() from destructor to constructor. Dummy integrate FileHead.h because the two branches are in sync now. |
||
#4 | 1449 | Sam Stafford |
Removed single-argument constructor and associated behavior from FileLogCache. Clients will now need to construct and pass in ClientApi and Error objects - the benefit is that connection settings can be set in the ClientApi, and connection errors will be returned in the Error. |
||
#3 | 1441 | Sam Stafford |
A FileLogCache now maintains a single ClientApi and Error object to be used for all filelog requests. Should be faster. A new constructor is available which takes a ClientApi* and Error* - this is to allow you to handle connection errors yourself rather than having FileLogCache call Error::Abort(). |
||
#2 | 1432 | Sam Stafford |
Visible change: ALL revisions are now kept in the ChangeSorter, not just those that are "relevant". I've decided that the mechanism of filtering for revisions with direct relationships isn't all that useful, even if it's sort of interesting - it prevents you from seeing work in ancestor branches that you haven't yet integrated, for example. Infrastructure change: New set of FileHead* links to help in navigation of the FileLogCache: pointers in the FileLogCache to "head" and "tail" FileHeads, and "next_from" and "next_into" pointers on each FileHead. The idea is you can start at the "head" and then follow "next_into" pointers all the way to the "tail". |
||
#1 | 1417 | Sam Stafford |
Branching backend stuff off for rigorous testing. Grahr. |
||
//guest/sam_stafford/p4hl/src/dlls/FileLogCache.cpp | |||||
#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. |