Prevent FDM-derived properties being sent at full speed (120Hz) which
overloads telnet connections. Instead track dirty properties and
send them at the protocol’s update rate (which is presumably what
the user expects)
Using os.path.abspath() here in TerraSync.setTarget() adds a safety
layer in case the process later calls os.chdir() or similar[1], which
would change the meaning of the "." directory. Also remove the strip()
call which I don't consider useful here, see my message at:
https://sourceforge.net/p/flightgear/mailman/message/36208140/
[1] Not the case currently, but who knows what will happen in the
future...
You may now call terrasync.py with --mode=sync or --mode=check. 'sync'
mode is the default and corresponds to terrasync.py's usual behavior.
In 'check' mode, terrasync.py never writes to disk and aborts at the
first mismatch between local and remote data. The exit status in 'check'
mode is:
- 0 if the program terminated successfully and no mismatch was found
between the local and remote repositories;
- 1 in case an error was encountered;
- 2 if there was a mismatch between local and remote data.
In 'sync' mode, the exit status is:
- 0 if the program terminated successfully;
- 1 in case an error was encountered.
A mismatch in 'check' mode is *not* an error, it is just one of the two
expected results. An error is a worse condition (uncaught exception,
network retrieval aborted after retrying failed, stuff like that).
Additionally, calling terrasync.py with --report causes it to print
lists of:
- files and dirs that were missing or had mismatching hashes (this is
okay in 'sync' mode: these things have been "fixed" in the target
directory before the report was printed);
- files and dirs that have been found to be orphaned (i.e., found
under the target directory but not mentioned in the corresponding
.dirindex file). These are the ones removed in 'sync' mode when
--remove-orphan is passed.
- Add computeHash() utility function that can work with any file-like
object (e.g., a connected socket).
- Rename hash_of_file() to hashForFile(), and of course implement it
using our new computeHash().
- Add class HTTPSocketRequest derived from HTTPGetCallback. It allows
one to process data from the network without storing it to a file (it
uses the file-like interface provided by http.client.HTTPResponse).
The callback returns the http.client.HTTPResponse object, which can be
conveniently used in a 'with' statement.
- Simplify the API of TerraSync.updateDirectory(): its 'dirIndexHash'
argument must now be a hash (a string); the None object is not allowed
anymore (with the soon-to-come addition of --mode=check, having to
deal with this special case in updateDirectory() would make the logic
too difficult to follow, or we would have to really completely
separate check-only mode from update mode, which would entail code
duplication).
Since TerraSync.updateDirectory() must now always have a hash to work
with, compute the hash of the root '.dirindex' file from the server in
TerraSync.start(), using our new HTTPSocketRequest class---which was
written for this purpose, since that will have to work in check-only
mode (but not only), where we don't want to write any file to disk.
- TerraSync.updateFile(): correctly handle the case where a directory
inside the TerraSync repository is (now) a file according to the
server: the directory must be recursively removed before the file can
be downloaded in the place formerly occupied by the directory.
- Add stub class Report. Its methods do nothing for now, but are already
called in a couple of appropriate places. The class will be completed
in a future commit, of course.
The goal of removeDirectoryTree() is to provide a safety net around
recursive directory removal with shutil.rmtree(), in order to prevent
user or bug-caused catastrophic events such as /, /home /home/joeuser or
C:\ being recursively erased.
- Add method assembleUrl() to HTTPGetter.
- Raise a NetworkError exception with the particular URL and number of
retries when it has been exhausted.
- Number of retries is now trivial to expose as a parameter, and set to
5 in HTTPGetter.
- Sleep for one second between self.httpConnection.close() and
self.httpConnection.connect() when retrying a failed HTTP request.
- Apply DRY principle.
- New generic exception class TerraSyncPyException.
- Add subclass NetworkError of TerraSyncPyException.
- Raise a NetworkError exception when the HTTP return code is not 200.
- hash_of_file() does not silently ignore errors anymore; exceptions
should be dealt with wherever appropriate by the callers.
Whenever hash_of_file() returns, its return value is now the SHA-1
hash of the specified file. This is less error-prone IMHO than
returning None. Otherwise, calling code could erroneously conclude
that there is a matching hash when the file to check is actually
missing. For a concrete example, see the 'dirIndexHash' parameter of
TerraSync.updateDirectory(), which so far is used precisely with the
value None to express that "we are just starting the recursion and
have no hash from the server to compare to".
When called, the callback passed to HTTPGetter.get() is now explicitly
passed the URL and the http.client.HTTPResponse instance.
Remove the HTTPGetCallback.result attribute (not needed anymore, leaves
more freedom when implementating HTTPGetCallback subclasses...).
the current timestamp used in mp protocol and in AImultiplayer is not a good one:
it can pause, or even change speed if we change warp value.
we want it to be used for network protocol lag and jitter estimation, and
a time flowing linearly on both side is needed, here's a first introduction
of this timestamp relates to real elapsed time.
here it's initialised to the system clock, then follow the monotonic clock.
in future improvement, it will allow time synchronisation betwen mp players,
to have a very good close formation flight experience.
The "Airbus" callouts ("2500", "hundred above", "retard") are not issued
by the original mk-viii unit, but adding support helps with better
simulation for Airbus a/c. The new callouts are disabled by default, and
are enabled by a specific setting of the GPWS "category-4" configuration
value (see Wiki).
- /sim/multiplay/transmit-filter-property-base can now filter based on property index; or have the previous mode of transmitting only generics by setting to 1.
- Move emesary MP bridge property base index to 12000 - to allow filtering of all except these (to reduce packet size).
- Modify global_mouseInput in init() and in shutdown(), because *these*
are the places where FGMouseInput is enabled or disabled.
- reinit() does shutdown() followed by init().
Note: the commented-out block starting with "FIXME: memory leak" that is
removed here was just an outdated comment, because SGBindingList
is an std::vector<SGBinding_ptr>, where SGBinding_ptr is a smart
pointer type (SGSharedPtr<SGBinding>). In other words, there was
no leak in this place---at least, not recently.
Create the FGMouseInputPrivate instance in FGMouseInput::init() instead
of in FGMouseInput's constructor. This will allow straightforward
implementation of reinit() via shutdown() and init().
Also get rid of the 'initialized' bool, since bool(d) is now equivalent
(d being the std::unique_ptr<FGMouseInputPrivate> data member of
FGMouseInput).
Using std::vector<mouse_mode> instead of std::unique_ptr<mouse_mode[]>
would have been possible of course, but a bit more awkward as
vector<>::size() returns an std::size_t but all the "adjacent" code is
based on the 'int' type.
Octal escape sequences can be as short as 2 bytes (\0, ..., \7),
therefore they allow one to generate shorter files than hex escapes, for
the same resource contents. The line lengths won't be as even, but this
is purely cosmetic, virtually no one will ever read the resource data
string literals, so this is quite a negligible drawback compared to the
advantage of using less space in the Git repository every time resource
files are committed.