This commit is contained in:
gallaert
2018-09-30 16:25:33 +01:00
8 changed files with 119 additions and 97 deletions
+47 -57
View File
@@ -182,17 +182,11 @@ class HTTPDirectory
ChildInfo(Type ty, const std::string & nameData, const std::string & hashData) : ChildInfo(Type ty, const std::string & nameData, const std::string & hashData) :
type(ty), type(ty),
name(nameData), name(nameData),
hash(hashData), hash(hashData)
sizeInBytes(0)
{ {
} }
ChildInfo(const ChildInfo& other) : ChildInfo(const ChildInfo& other) = default;
type(other.type),
name(other.name),
hash(other.hash),
sizeInBytes(other.sizeInBytes)
{ }
void setSize(const std::string & sizeData) void setSize(const std::string & sizeData)
{ {
@@ -206,7 +200,8 @@ class HTTPDirectory
Type type; Type type;
std::string name, hash; std::string name, hash;
size_t sizeInBytes; size_t sizeInBytes = 0;
SGPath path; // absolute path on disk
}; };
typedef std::vector<ChildInfo> ChildInfoList; typedef std::vector<ChildInfo> ChildInfoList;
@@ -273,44 +268,45 @@ public:
return; return;
} }
string_list indexNames = indexChildren(); char* buf = nullptr;
const_string_list_iterator nameIt = indexNames.begin(); size_t bufSize = 0;
for (; nameIt != indexNames.end(); ++nameIt) {
SGPath p(absolutePath());
p.append(*nameIt);
if (p.exists()) {
continue; // only copy if the file is missing entirely
}
ChildInfoList::iterator c = findIndexChild(*nameIt); for (const auto& child : children) {
if (c->type == ChildInfo::DirectoryType) { if (child.type != ChildInfo::FileType)
continue; // only care about files continue;
}
SGPath cp = _repository->installedCopyPath; if (child.path.exists())
cp.append(relativePath()); continue;
cp.append(*nameIt);
if (!cp.exists()) {
continue;
}
SGBinaryFile src(cp); SGPath cp = _repository->installedCopyPath;
SGBinaryFile dst(p); cp.append(relativePath());
src.open(SG_IO_IN); cp.append(child.name);
dst.open(SG_IO_OUT); if (!cp.exists()) {
continue;
}
char* buf = (char*) malloc(cp.sizeInBytes()); SGBinaryFile src(cp);
if (!buf) { SGBinaryFile dst(child.path);
continue; src.open(SG_IO_IN);
} dst.open(SG_IO_OUT);
src.read(buf, cp.sizeInBytes()); if (bufSize < cp.sizeInBytes()) {
dst.write(buf, cp.sizeInBytes()); bufSize = cp.sizeInBytes();
src.close(); free(buf);
dst.close(); 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() void updateChildrenBasedOnHash()
@@ -319,19 +315,20 @@ public:
copyInstalledChildren(); copyInstalledChildren();
string_list indexNames = indexChildren(), string_list toBeUpdated, orphans,
toBeUpdated, orphans; indexNames = indexChildren();
simgear::Dir d(absolutePath()); simgear::Dir d(absolutePath());
PathList fsChildren = d.children(0); PathList fsChildren = d.children(0);
for (const auto& child : fsChildren) { for (const auto& child : fsChildren) {
const auto& fileName = child.file(); const auto& fileName = child.file();
if ((fileName == ".dirindex") || (fileName == ".hashes")) { if ((fileName == ".dirindex") || (fileName == ".hashes")) {
continue; 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); std::string hash = hashForChild(info);
ChildInfoList::iterator c = findIndexChild(fileName); ChildInfoList::iterator c = findIndexChild(fileName);
@@ -428,19 +425,16 @@ public:
void didUpdateFile(const std::string& file, const std::string& hash, size_t sz) void didUpdateFile(const std::string& file, const std::string& hash, size_t sz)
{ {
// check hash matches what we expected // check hash matches what we expected
ChildInfoList::iterator it = findIndexChild(file); auto it = findIndexChild(file);
if (it == children.end()) { if (it == children.end()) {
SG_LOG(SG_TERRASYNC, SG_WARN, "updated file but not found in dir:" << _relativePath << " " << file); SG_LOG(SG_TERRASYNC, SG_WARN, "updated file but not found in dir:" << _relativePath << " " << file);
} else { } else {
SGPath fpath(absolutePath());
fpath.append(file);
if (it->hash != hash) { if (it->hash != hash) {
// we don't erase the file on a hash mismatch, becuase if we're syncing during the // 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. // middle of a server-side update, the downloaded file may actually become valid.
_repository->failedToUpdateChild(_relativePath, HTTPRepository::REPO_ERROR_CHECKSUM); _repository->failedToUpdateChild(_relativePath, HTTPRepository::REPO_ERROR_CHECKSUM);
} else { } else {
_repository->updatedFileContents(fpath, hash); _repository->updatedFileContents(it->path, hash);
_repository->totalDownloaded += sz; _repository->totalDownloaded += sz;
} // of hash matches } // of hash matches
} // of found in child list } // of found in child list
@@ -539,8 +533,8 @@ private:
continue; 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) { if (tokens.size() > 3) {
children.back().setSize(tokens[3]); children.back().setSize(tokens[3]);
} }
@@ -572,8 +566,7 @@ private:
std::string hashForChild(const ChildInfo& child) const std::string hashForChild(const ChildInfo& child) const
{ {
SGPath p(absolutePath()); SGPath p(child.path);
p.append(child.name);
if (child.type == ChildInfo::DirectoryType) { if (child.type == ChildInfo::DirectoryType) {
p.append(".dirindex"); p.append(".dirindex");
} }
@@ -1056,9 +1049,6 @@ HTTPRepository::failure() const
entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10); entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10);
hashes.push_back(entry); hashes.push_back(entry);
} }
SG_LOG(SG_TERRASYNC, SG_INFO, "restored hashes:" << hashes.size());
} }
class DirectoryWithPath class DirectoryWithPath
+1 -1
View File
@@ -160,7 +160,7 @@ public:
} }
} }
float readInt() int32_t readInt()
{ {
unsigned int* p = reinterpret_cast<unsigned int*>(ptr + offset); unsigned int* p = reinterpret_cast<unsigned int*>(ptr + offset);
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
+3 -3
View File
@@ -160,7 +160,7 @@ void test_path_dir()
SG_VERIFY(sub2.isFile()); SG_VERIFY(sub2.isFile());
SG_CHECK_EQUAL(sub2.sizeInBytes(), 250); SG_CHECK_EQUAL(sub2.sizeInBytes(), 250);
SGPath sub3 = p / "subß" / "file𝕽"; SGPath sub3 = p / "subß" / u8"file𝕽";
sub3.create_dir(0755); sub3.create_dir(0755);
{ {
@@ -174,7 +174,7 @@ void test_path_dir()
sub3.set_cached(false); sub3.set_cached(false);
SG_VERIFY(sub3.exists()); SG_VERIFY(sub3.exists());
SG_CHECK_EQUAL(sub3.sizeInBytes(), 100); 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::Dir subD(p / "subA");
simgear::PathList dirChildren = subD.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT); 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()); simgear::Dir subS(sub3.dirPath());
fileChildren = subS.children(simgear::Dir::TYPE_FILE | simgear::Dir::NO_DOT_OR_DOTDOT); fileChildren = subS.children(simgear::Dir::TYPE_FILE | simgear::Dir::NO_DOT_OR_DOTDOT);
SG_CHECK_EQUAL(fileChildren.size(), 1); SG_CHECK_EQUAL(fileChildren.size(), 1);
SG_CHECK_EQUAL(fileChildren[0], subS.path() / "file𝕽"); SG_CHECK_EQUAL(fileChildren[0], subS.path() / u8"file𝕽");
} }
+40 -35
View File
@@ -1136,44 +1136,49 @@ bool matchPropPathToTemplate(const std::string& path, const std::string& templat
bool parseStringAsLatLonValue(const std::string& s, double& degrees) bool parseStringAsLatLonValue(const std::string& s, double& degrees)
{ {
string ss = simplify(s); try {
auto spacePos = ss.find_first_of(" *"); 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));
double minutes = 0.0, seconds = 0.0; if (spacePos == std::string::npos) {
degrees = std::stod(ss);
// check for minutes marker } else {
auto quotePos = ss.find('\''); degrees = std::stod(ss.substr(0, spacePos));
if (quotePos == std::string::npos) {
const auto minutesStr = ss.substr(spacePos+1); double minutes = 0.0, seconds = 0.0;
if (!minutesStr.empty()) {
minutes = std::stod(minutesStr); // 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)); // since we simplified, any trailing N/S/E/W must be the last char
const auto secondsStr = ss.substr(quotePos+1); const char lastChar = ::toupper(ss.back());
if (!secondsStr.empty()) { if ((lastChar == 'W') || (lastChar == 'S')) {
seconds = std::stod(secondsStr); degrees = -degrees;
} }
} } catch (std::exception&) {
// std::stdo can throw
if ((seconds < 0.0) || (minutes < 0.0)) { return false;
// 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;
} }
return true; return true;
+7
View File
@@ -676,6 +676,13 @@ void test_parseGeod()
SG_VERIFY(strutils::parseStringAsGeod("\t40 30'50\"S, 12 34'56\"W ", &a, true)); 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.getLongitudeDeg(), -12.58222222);
SG_CHECK_EQUAL_EP(a.getLatitudeDeg(), -40.5138888); 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() void test_formatGeod()
+16
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 // SGTimerQueue
// This is the priority queue implementation: // This is the priority queue implementation:
@@ -270,3 +278,11 @@ SGTimer* SGTimerQueue::findByName(const std::string& name) const
return NULL; 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);
}
}
+4
View File
@@ -38,6 +38,8 @@ public:
double nextTime() { return -_table[0].pri; } double nextTime() { return -_table[0].pri; }
SGTimer* findByName(const std::string& name) const; SGTimer* findByName(const std::string& name) const;
void dump();
private: private:
// The "priority" is stored as a negative time. This allows the // The "priority" is stored as a negative time. This allows the
// implementation to treat the "top" of the heap as the largest // implementation to treat the "top" of the heap as the largest
@@ -119,6 +121,8 @@ public:
void removeTask(const std::string& name); void removeTask(const std::string& name);
void dump();
private: private:
friend class SGTimer; friend class SGTimer;
+1 -1
View File
@@ -1 +1 @@
2018.3.0 2018.4.0