This commit is contained in:
gallaert 2018-09-30 16:25:33 +01:00
commit e755735ac2
8 changed files with 119 additions and 97 deletions

View File

@ -182,17 +182,11 @@ class HTTPDirectory
ChildInfo(Type ty, const std::string & nameData, const std::string & hashData) :
type(ty),
name(nameData),
hash(hashData),
sizeInBytes(0)
hash(hashData)
{
}
ChildInfo(const ChildInfo& other) :
type(other.type),
name(other.name),
hash(other.hash),
sizeInBytes(other.sizeInBytes)
{ }
ChildInfo(const ChildInfo& other) = default;
void setSize(const std::string & sizeData)
{
@ -206,7 +200,8 @@ class HTTPDirectory
Type type;
std::string name, hash;
size_t sizeInBytes;
size_t sizeInBytes = 0;
SGPath path; // absolute path on disk
};
typedef std::vector<ChildInfo> ChildInfoList;
@ -273,44 +268,45 @@ public:
return;
}
string_list indexNames = indexChildren();
const_string_list_iterator nameIt = indexNames.begin();
for (; nameIt != indexNames.end(); ++nameIt) {
SGPath p(absolutePath());
p.append(*nameIt);
if (p.exists()) {
continue; // only copy if the file is missing entirely
}
char* buf = nullptr;
size_t bufSize = 0;
ChildInfoList::iterator c = findIndexChild(*nameIt);
if (c->type == ChildInfo::DirectoryType) {
continue; // only care about files
}
for (const auto& child : children) {
if (child.type != ChildInfo::FileType)
continue;
SGPath cp = _repository->installedCopyPath;
cp.append(relativePath());
cp.append(*nameIt);
if (!cp.exists()) {
continue;
}
if (child.path.exists())
continue;
SGBinaryFile src(cp);
SGBinaryFile dst(p);
src.open(SG_IO_IN);
dst.open(SG_IO_OUT);
SGPath cp = _repository->installedCopyPath;
cp.append(relativePath());
cp.append(child.name);
if (!cp.exists()) {
continue;
}
char* buf = (char*) malloc(cp.sizeInBytes());
if (!buf) {
continue;
}
SGBinaryFile src(cp);
SGBinaryFile dst(child.path);
src.open(SG_IO_IN);
dst.open(SG_IO_OUT);
src.read(buf, cp.sizeInBytes());
dst.write(buf, cp.sizeInBytes());
src.close();
dst.close();
if (bufSize < cp.sizeInBytes()) {
bufSize = cp.sizeInBytes();
free(buf);
buf = (char*) malloc(bufSize);
if (!buf) {
continue;
}
}
free(buf);
}
src.read(buf, cp.sizeInBytes());
dst.write(buf, cp.sizeInBytes());
src.close();
dst.close();
}
free(buf);
}
void updateChildrenBasedOnHash()
@ -319,19 +315,20 @@ public:
copyInstalledChildren();
string_list indexNames = indexChildren(),
toBeUpdated, orphans;
string_list toBeUpdated, orphans,
indexNames = indexChildren();
simgear::Dir d(absolutePath());
PathList fsChildren = d.children(0);
for (const auto& child : fsChildren) {
const auto& fileName = child.file();
if ((fileName == ".dirindex") || (fileName == ".hashes")) {
continue;
}
ChildInfo info(child.isDir() ? ChildInfo::DirectoryType : ChildInfo::FileType, fileName, "");
ChildInfo info(child.isDir() ? ChildInfo::DirectoryType : ChildInfo::FileType,
fileName, "");
info.path = child;
std::string hash = hashForChild(info);
ChildInfoList::iterator c = findIndexChild(fileName);
@ -428,19 +425,16 @@ public:
void didUpdateFile(const std::string& file, const std::string& hash, size_t sz)
{
// check hash matches what we expected
ChildInfoList::iterator it = findIndexChild(file);
auto it = findIndexChild(file);
if (it == children.end()) {
SG_LOG(SG_TERRASYNC, SG_WARN, "updated file but not found in dir:" << _relativePath << " " << file);
} else {
SGPath fpath(absolutePath());
fpath.append(file);
if (it->hash != hash) {
// we don't erase the file on a hash mismatch, becuase if we're syncing during the
// middle of a server-side update, the downloaded file may actually become valid.
_repository->failedToUpdateChild(_relativePath, HTTPRepository::REPO_ERROR_CHECKSUM);
} else {
_repository->updatedFileContents(fpath, hash);
_repository->updatedFileContents(it->path, hash);
_repository->totalDownloaded += sz;
} // of hash matches
} // of found in child list
@ -539,8 +533,8 @@ private:
continue;
}
children.push_back(ChildInfo(typeData == "f" ? ChildInfo::FileType : ChildInfo::DirectoryType, tokens[1], tokens[2]));
children.emplace_back(ChildInfo(typeData == "f" ? ChildInfo::FileType : ChildInfo::DirectoryType, tokens[1], tokens[2]));
children.back().path = absolutePath() / tokens[1];
if (tokens.size() > 3) {
children.back().setSize(tokens[3]);
}
@ -572,8 +566,7 @@ private:
std::string hashForChild(const ChildInfo& child) const
{
SGPath p(absolutePath());
p.append(child.name);
SGPath p(child.path);
if (child.type == ChildInfo::DirectoryType) {
p.append(".dirindex");
}
@ -1056,9 +1049,6 @@ HTTPRepository::failure() const
entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10);
hashes.push_back(entry);
}
SG_LOG(SG_TERRASYNC, SG_INFO, "restored hashes:" << hashes.size());
}
class DirectoryWithPath

View File

@ -160,7 +160,7 @@ public:
}
}
float readInt()
int32_t readInt()
{
unsigned int* p = reinterpret_cast<unsigned int*>(ptr + offset);
if ( sgIsBigEndian() ) {

View File

@ -160,7 +160,7 @@ void test_path_dir()
SG_VERIFY(sub2.isFile());
SG_CHECK_EQUAL(sub2.sizeInBytes(), 250);
SGPath sub3 = p / "subß" / "file𝕽";
SGPath sub3 = p / "subß" / u8"file𝕽";
sub3.create_dir(0755);
{
@ -174,7 +174,7 @@ void test_path_dir()
sub3.set_cached(false);
SG_VERIFY(sub3.exists());
SG_CHECK_EQUAL(sub3.sizeInBytes(), 100);
SG_CHECK_EQUAL(sub3.file(), "file𝕽");
SG_CHECK_EQUAL(sub3.file(), u8"file𝕽");
simgear::Dir subD(p / "subA");
simgear::PathList dirChildren = subD.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT);
@ -188,7 +188,7 @@ void test_path_dir()
simgear::Dir subS(sub3.dirPath());
fileChildren = subS.children(simgear::Dir::TYPE_FILE | simgear::Dir::NO_DOT_OR_DOTDOT);
SG_CHECK_EQUAL(fileChildren.size(), 1);
SG_CHECK_EQUAL(fileChildren[0], subS.path() / "file𝕽");
SG_CHECK_EQUAL(fileChildren[0], subS.path() / u8"file𝕽");
}

View File

@ -1136,44 +1136,49 @@ bool matchPropPathToTemplate(const std::string& path, const std::string& templat
bool parseStringAsLatLonValue(const std::string& s, double& degrees)
{
string ss = simplify(s);
auto spacePos = ss.find_first_of(" *");
if (spacePos == std::string::npos) {
degrees = std::stod(ss);
} else {
degrees = std::stod(ss.substr(0, spacePos));
try {
string ss = simplify(s);
auto spacePos = ss.find_first_of(" *");
double minutes = 0.0, seconds = 0.0;
// check for minutes marker
auto quotePos = ss.find('\'');
if (quotePos == std::string::npos) {
const auto minutesStr = ss.substr(spacePos+1);
if (!minutesStr.empty()) {
minutes = std::stod(minutesStr);
if (spacePos == std::string::npos) {
degrees = std::stod(ss);
} else {
degrees = std::stod(ss.substr(0, spacePos));
double minutes = 0.0, seconds = 0.0;
// check for minutes marker
auto quotePos = ss.find('\'');
if (quotePos == std::string::npos) {
const auto minutesStr = ss.substr(spacePos+1);
if (!minutesStr.empty()) {
minutes = std::stod(minutesStr);
}
} else {
minutes = std::stod(ss.substr(spacePos+1, quotePos - spacePos));
const auto secondsStr = ss.substr(quotePos+1);
if (!secondsStr.empty()) {
seconds = std::stod(secondsStr);
}
}
if ((seconds < 0.0) || (minutes < 0.0)) {
// don't allow sign information in minutes or seconds
return false;
}
double offset = (minutes / 60.0) + (seconds / 3600.0);
degrees += (degrees >= 0.0) ? offset : -offset;
}
} else {
minutes = std::stod(ss.substr(spacePos+1, quotePos - spacePos));
const auto secondsStr = ss.substr(quotePos+1);
if (!secondsStr.empty()) {
seconds = std::stod(secondsStr);
// since we simplified, any trailing N/S/E/W must be the last char
const char lastChar = ::toupper(ss.back());
if ((lastChar == 'W') || (lastChar == 'S')) {
degrees = -degrees;
}
}
if ((seconds < 0.0) || (minutes < 0.0)) {
// don't allow sign information in minutes or seconds
return false;
}
double offset = (minutes / 60.0) + (seconds / 3600.0);
degrees += (degrees >= 0.0) ? offset : -offset;
}
// since we simplified, any trailing N/S/E/W must be the last char
const char lastChar = ::toupper(ss.back());
if ((lastChar == 'W') || (lastChar == 'S')) {
degrees = -degrees;
} catch (std::exception&) {
// std::stdo can throw
return false;
}
return true;

View File

@ -676,6 +676,13 @@ void test_parseGeod()
SG_VERIFY(strutils::parseStringAsGeod("\t40 30'50\"S, 12 34'56\"W ", &a, true));
SG_CHECK_EQUAL_EP(a.getLongitudeDeg(), -12.58222222);
SG_CHECK_EQUAL_EP(a.getLatitudeDeg(), -40.5138888);
// malformed inputs
SG_VERIFY(strutils::parseStringAsGeod("12.345,", &a, true) == false);
double d;
SG_VERIFY(strutils::parseStringAsLatLonValue("", d) == false);
}
void test_formatGeod()

View File

@ -119,6 +119,14 @@ void SGEventMgr::removeTask(const std::string& name)
}
}
void SGEventMgr::dump()
{
SG_LOG(SG_GENERAL, SG_INFO, "EventMgr: sim-time queue:");
_simQueue.dump();
SG_LOG(SG_GENERAL, SG_INFO, "EventMgr: real-time queue:");
_rtQueue.dump();
}
////////////////////////////////////////////////////////////////////////
// SGTimerQueue
// This is the priority queue implementation:
@ -270,3 +278,11 @@ SGTimer* SGTimerQueue::findByName(const std::string& name) const
return NULL;
}
void SGTimerQueue::dump()
{
for (int i=0; i < _numEntries; ++i) {
const auto t = _table[i].timer;
SG_LOG(SG_GENERAL, SG_INFO, "\ttimer:" << t->name << ", interval=" << t->interval);
}
}

View File

@ -38,6 +38,8 @@ public:
double nextTime() { return -_table[0].pri; }
SGTimer* findByName(const std::string& name) const;
void dump();
private:
// The "priority" is stored as a negative time. This allows the
// implementation to treat the "top" of the heap as the largest
@ -119,6 +121,8 @@ public:
void removeTask(const std::string& name);
void dump();
private:
friend class SGTimer;

View File

@ -1 +1 @@
2018.3.0
2018.4.0