Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next
This commit is contained in:
commit
e755735ac2
@ -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
|
||||
|
@ -160,7 +160,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
float readInt()
|
||||
int32_t readInt()
|
||||
{
|
||||
unsigned int* p = reinterpret_cast<unsigned int*>(ptr + offset);
|
||||
if ( sgIsBigEndian() ) {
|
||||
|
@ -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𝕽");
|
||||
|
||||
}
|
||||
|
||||
|
@ -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(" *");
|
||||
try {
|
||||
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));
|
||||
if (spacePos == std::string::npos) {
|
||||
degrees = std::stod(ss);
|
||||
} else {
|
||||
degrees = std::stod(ss.substr(0, spacePos));
|
||||
|
||||
double minutes = 0.0, seconds = 0.0;
|
||||
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);
|
||||
// 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;
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user