|
// Copyright (C) 2011 Fog Creek Software
// Copyright (C) 2009 Benjamin Pollack
// Copyright (C) 2009 Adrian Buehlmann
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdafx.h"
#include "Dirstatecache.h"
#include "Dirstate.h"
#include "THgStatus.h"
#include "Winstat.h"
CAtlList<CDirstateCache::CEntry>& CDirstateCache::Cache()
{
static CAtlList<CDirstateCache::CEntry> c;
return c;
}
CDirstate* CDirstateCache::Get(const CString& strHgRoot, const CString& strCwd,
bool& bUnset, bool bUseKbfiles)
{
bUnset = false;
POSITION position = Cache().GetHeadPosition();
while (position != NULL)
{
CEntry& rItem = Cache().GetAt(position);
if (strHgRoot == rItem.strHgRoot && bUseKbfiles == rItem.bUseKbfiles) break;
Cache().GetNext(position);
}
CWinstat stat;
CString strPath = strHgRoot + (bUseKbfiles ? "\\.hg\\kilnbfiles\\dirstate"
: "\\.hg\\dirstate");
unsigned tc = ::GetTickCount();
bool bNewStat = false;
if (position == NULL)
{
if (stat.lstat(strPath, true) != 0)
{
ATLTRACE("CDirstateCache::get: lstat('%s') failed\n", (LPCTSTR)strPath);
return 0;
}
ATLTRACE("CDirstateCache::get: lstat('%s') ok\n", (LPCTSTR)strPath);
bNewStat = true;
if (Cache().GetCount() >= 10)
{
CEntry e = Cache().RemoveTail();
ATLTRACE("CDirstateCache::get: dropping '%s'\n", (LPCTSTR)e.strHgRoot);
delete e.pDirstate;
}
CEntry e;
e.strHgRoot = strHgRoot;
e.bUseKbfiles = bUseKbfiles;
e.uTickCount = tc;
Cache().AddHead(e);
position = Cache().GetHeadPosition();
}
CEntry& rItem = Cache().GetAt(position);
if (!bNewStat && tc - rItem.uTickCount > 500)
{
if (0 != stat.lstat(strPath, true))
{
ATLTRACE("CDirstateCache::get: lstat('%s') failed\n", (LPCTSTR)strPath);
ATLTRACE("CDirstateCache::get: dropping '%s'\n", (LPCTSTR)rItem.strHgRoot);
delete rItem.pDirstate;
Cache().RemoveAt(position);
return 0;
}
rItem.uTickCount = tc;
ATLTRACE("CDirstateCache::get: lstat('%s') ok\n", (LPCTSTR)strPath);
bNewStat = true;
}
if (rItem.pDirstate)
{
bUnset = rItem.bUnset;
if (!bNewStat) return rItem.pDirstate;
if (rItem.llMTime == stat.ullMTime && rItem.llSize == stat.ullSize)
{
return rItem.pDirstate;
}
ATLTRACE("CDirstateCache::get: refreshing '%s'\n", (LPCTSTR)strHgRoot);
}
else
{
ATLTRACE("CDirstateCache::get: reading '%s'\n", (LPCTSTR)strHgRoot);
}
bUnset = false;
unsigned tc0 = ::GetTickCount();
CAutoPtr<CDirstate> ds = CDirstate::Read(strPath, bUnset);
unsigned tc1 = ::GetTickCount();
bool bRequestTHgStatusUpdate = true;
if (bUnset)
{
if (rItem.bUnset)
{
ATLTRACE("CDirstateCache::get: **** old and new have unset entries\n");
bRequestTHgStatusUpdate = false;
}
else
{
ATLTRACE("CDirstateCache::get: new has unset entries\n");
}
}
rItem.bUnset = bUnset;
delete rItem.pDirstate;
rItem.pDirstate = ds.Detach();
unsigned delta = tc1 - tc0;
ATLTRACE("CDirstateCache::get: read done in %d ticks, %d repos in cache\n",
delta, Cache().GetCount());
rItem.llMTime = stat.ullMTime;
rItem.llSize = stat.ullSize;
if (bRequestTHgStatusUpdate)
{
ATLTRACE("CDirstateCache::get: calling Thgstatus::update\n");
CTHgStatus::Update(strCwd);
}
else
{
ATLTRACE("CDirstateCache::get: omitting Thgstatus::update\n");
}
return rItem.pDirstate;
}
void CDirstateCache::Invalidate(const CString& strHgRoot, bool bUseKbfiles)
{
if (strHgRoot.IsEmpty()) return;
POSITION position = Cache().GetHeadPosition();
while (position != NULL)
{
CEntry& rItem = Cache().GetAt(position);
if (strHgRoot == rItem.strHgRoot && bUseKbfiles == rItem.bUseKbfiles)
{
delete rItem.pDirstate;
Cache().RemoveAt(position);
ATLTRACE("Dirstatecache::invalidate('%s')\n", (LPCTSTR)strHgRoot);
break;
}
}
}
|
Loading...