When we receive an expired tile, we don't immediately retry
because in case the server keeps serving an expired tile, that
would cause an infinite retry cycle.
Now we add an exponential delay, similarly to what we do for
connection errors.
When looking for child tiles that cover a parent tile, we're computing the lower bound of the child tile in the set of tiles. Three things can happen:
- all remaining tiles are sorted before the child tile we're looking for. in that case, there can not be a child tile.
- the lower bound is the child tile; in this case, we want to continue checking the other children of the parent tile.
- the lower bound isn't the child tile we're looking for, but there are still tiles sorted after the tile we were looking for. these could be four children of the child tile we're looking for, so we're recursively descending.
what the current algorithm didn't take into account so far is that tiles with a higher w number (i.e. tiles that are outside the "main" tile pyramid of 0/0/0) were always sorted *after* the current w number. this meant that we thought there were still remaining children to be checked, so continued our recursive descent until eventually the number overflowed and we aborted our search. unfortunately, on Android this recursive descent and accompanying overflow caused a crash.
this patch fixes this by making sure that before we're continuing to descent, we're sure that the w numbers match: all tiles with a different (= higher) w number essentially mean the same as "all remaining tiles are sorted before the child tile we're looking for" for the purpose of finding covering children
Addresses https://github.com/mapbox/mapbox-gl-native/issues/3704
This introduces a new utility class that wraps networking via
NSURLSession. All related code that used to live inside the telemetry
MGLMapboxEvents class has been pulled into the new MGLAPIClient.
An API client instance is used as a service by telemetry and can be
reused in the future when and if our networking needs grow or become
more complex.
SQLite REPLACE is *not* UPSERT. If a conflict occurs, it first deletes the existing row, then inserts a new row. This means that AUTOINCREMENT primary keys change. This will break foreign keys to that value, which we use.
Instead we must try an UPDATE, and fall back to an INSERT if the UPDATE changes zero rows.
Coverage compiler and linker flags are used only when (1) in debug build
and (2) with ENABLE_COVERAGE set to 1. Besides, because OS X's libtool
is unable to understand '--coverage', this linker flag is only used
genrating executable targets. Also, using 'link_settings' to specify
linker options and separate instructions for OSX and Linux.
The last map object to get destroyed will also destroy
the RunLoop (which will also destroy the AsyncTask).
This will clear any reference to the Node default main
loop and let it close.
Downside is that we need to make sure we are always calling
`map.release()`.
The run loop will be kept alive because it has an `AsyncTask`. We
also can simple stop the loop with `uv_stop()`.
The `RunLoop` is still gonna be the last object to be destroyed
because it is the first object to be created in the thread, so
by design it won't outlive `Timer`s and `AsyncTask`s.
This patch won't change the current behavior, will just make
the code simpler.