When downloading from a dive computer, stop at mergeable dives

Jef Driesen jefdriesen at telenet.be
Fri Nov 23 22:52:13 PST 2012


On 2012-11-21 18:09, Dirk Hohndel wrote:
> On Wed, 2012-11-21 at 17:56 +0100, Jef Driesen wrote:
>> On 2012-11-20 02:31, Linus Torvalds wrote:
>> > We do want to have some way of saying "force download of all dives
>> > from today" or something like that, I suspect. Because while I 
>> don't
>> > want to re-download *every* dive, I might want to force-merge the
>> > last
>> > <N> dives.
>>
>> Have you considered using the libdivecomputer fingerprint feature 
>> for
>> this purpose? It has been explicitly designed for this scenario. It
>> supports multiple devices out-of-the box, without needing any sort 
>> of
>> heuristics like matching start times. It will also give you the 
>> shortest
>> possible download times, something which is not always possible to
>> achieve with a custom implementation.
>>
>> Anyway, if you want to play with this feature, have a look at the 
>> "-c"
>> option of the universal application. In a multi device scenario, you
>> download both devices with the command:
>>
>> ./universal -c <cachedir> -d <xmlfile> -b <backend> <devname>
>>
>> The fingerprint of the most recent dive will get stored in the
>> cachedir. When you run the same command again, it will load this
>> fingerprint again and only download the new dives (if any of 
>> course).
>> Because the universal app uses a different fingerprint file per 
>> device
>> (based on the device serial number), you get multi device support 
>> for
>> free.
>
> How do we use this via the API? As you know, Subsurface doesn't run 
> the
> universal app to download dives, it is linked against libdivecomputer
> and uses that API...

Of course it's also available through the api! I referred to the 
universal application because it's already implemented there, so you 
could give it a try before implementing anything yourself.

It's very simple. The first step is to register a callback function for 
DC_EVENT_DEVINFO. When you receive this event, you look-up in your 
fingerprint "database" whether you have a fingerprint for that device. 
If you do, call the dc_device_set_fingerprint function, and then you're 
done. You'll automatically only get those dives that are newer than the 
dive corresponding to that fingerprint. The second step is updating the 
fingerprint database. When the download has finished successfully, you 
store the fingerprint of the most recent dive into your "database". Keep 
in mind that because libdivecomputer always returns the dives in reverse 
order, the most recent dive is always the first dive you get!

If the download fails, then you should not update the fingerprint 
database, or you may not be able to download some dives again. This is 
due to downloading in the reverse order. Let's illustrate with an 
example. Assume you have 6 dives, where D6 is the oldest, and D1 is the 
most recent:

D6 D5 D4 D3 D2 D1

Let's assume you have already download D6 to D4. According the logic 
above, the current fingerprint belongs to dive D4. When trying to 
download the remaining dives, you'll get dive D1, then D2 and finally 
D3. Suppose there is an error downloading D2. Then you'll get the most 
recent dive D1 successfully, but not the other two. So if you update 
your fingerprint database with D1, then from then on you'll never be 
able to get D3 and D2 again. Because due to the fingerprint the download 
will already stop at D1.

In case of a failure, you should not update the fingerprint, and then 
the user has an opportunity to try again. You may get some duplicates 
(e.g. D1 in my example scenario), but never the older dives (D6 to D4). 
The duplication detection is something that will have to be done on the 
application side. You can still use the fingerprints for this of course, 
but then you'll need more than just the fingerprint of the most recent 
dive.

Note that the fingerprint look-up should take into account the device 
family type and serial number, to be able to uniquely identify each 
individual device. For example if you have an ostc and a vyper, then the 
family type is already sufficient. But if you have two devices from the 
same family (e.g. two vypers, or a vyper and a gekko), then you'll need 
the serial number too.

The fingerprint is usually the raw date/time data of each dive, but 
that's not guaranteed (there are already backends where it's something 
different). Applications should just consider it as an opaque piece of 
binary data. This is in fact one of the reasons why relying on the 
fingerprints is superior to using some parsed fields like the date/time 
value. Fingerprints can't be altered by the application, and thus the 
logic will always work, even after significant modifications by the 
user.

Jef


More information about the subsurface mailing list