diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2019-03-05 22:58:47 +0100 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2019-04-12 18:19:07 +0300 |
commit | e2df38d868324f2a767d2109cdd8727acb866ca2 (patch) | |
tree | 614b560431d2c61f3f2b1e2f986c7806bd175ae9 /core | |
parent | c22fd9f4fd6699333629b8acb1e9c135a9783082 (diff) | |
download | subsurface-e2df38d868324f2a767d2109cdd8727acb866ca2.tar.gz |
Dive site: add dive site ref-counting
Instead of setting dive->dive_site directly, call the
add_dive_to_dive_site() and unregister_dive_from_dive_site()
functions. In the parser this turned out to be a bit tricky.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'core')
-rw-r--r-- | core/datatrak.c | 6 | ||||
-rw-r--r-- | core/dive.c | 37 | ||||
-rw-r--r-- | core/dive.h | 2 | ||||
-rw-r--r-- | core/divelist.c | 18 | ||||
-rw-r--r-- | core/divesite.c | 9 | ||||
-rw-r--r-- | core/gpslocation.cpp | 2 | ||||
-rw-r--r-- | core/import-cobalt.c | 2 | ||||
-rw-r--r-- | core/import-divinglog.c | 2 | ||||
-rw-r--r-- | core/libdivecomputer.c | 6 | ||||
-rw-r--r-- | core/liquivision.c | 2 | ||||
-rw-r--r-- | core/load-git.c | 12 | ||||
-rw-r--r-- | core/parse-xml.c | 28 | ||||
-rw-r--r-- | core/parse.c | 19 | ||||
-rw-r--r-- | core/uemis-downloader.c | 9 |
14 files changed, 93 insertions, 61 deletions
diff --git a/core/datatrak.c b/core/datatrak.c index 0f7886158..553f0da05 100644 --- a/core/datatrak.c +++ b/core/datatrak.c @@ -195,9 +195,9 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive */ snprintf(buffer, sizeof(buffer), "%s, %s", locality, dive_point); ds = get_dive_site_by_name(buffer, sites); - dt_dive->dive_site = ds; - if (!dt_dive->dive_site) - dt_dive->dive_site = create_dive_site(buffer, sites); + if (!ds) + ds = create_dive_site(buffer, sites); + add_dive_to_dive_site(dt_dive, ds); free(locality); locality = NULL; free(dive_point); diff --git a/core/dive.c b/core/dive.c index b05030c60..f43697c65 100644 --- a/core/dive.c +++ b/core/dive.c @@ -662,8 +662,10 @@ void selective_copy_dive(const struct dive *s, struct dive *d, struct dive_compo d->rating = s->rating; if (what.visibility) d->visibility = s->visibility; - if (what.divesite) - d->dive_site = s->dive_site; + if (what.divesite) { + unregister_dive_from_dive_site(d); + add_dive_to_dive_site(d, s->dive_site); + } if (what.tags) STRUCTURED_LIST_COPY(struct tag_entry, s->tag_list, d->tag_list, copy_tl); if (what.cylinders) @@ -2988,12 +2990,21 @@ static int likely_same_dive(const struct dive *a, const struct dive *b) * be the old dive and dive b is supposed to be the newly imported * dive. If the flag "prefer_downloaded" is set, data of the latter * will take priority over the former. + * + * Attn: The dive_site parameter of the dive will be set, but the caller + * still has to register the dive in the dive site! */ struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded) { - if (likely_same_dive(a, b)) - return merge_dives(a, b, 0, prefer_downloaded, NULL); - return NULL; + struct dive *res; + struct dive_site *site; + + if (!likely_same_dive(a, b)) + return NULL; + + res = merge_dives(a, b, 0, prefer_downloaded, NULL, &site); + res->dive_site = site; /* Caller has to call add_dive_to_dive_site()! */ + return res; } void free_events(struct event *ev) @@ -3440,10 +3451,12 @@ bool has_planned(const struct dive *dive, bool planned) { * will take priority over the former. * * The trip the new dive should be associated with (if any) is returned - * in the "trip" output paramater. If "trip" is NULL, then the dive will - * instead be added to this trip. + * in the "trip" output parameter. + * + * The dive site the new dive should be added to (if any) is returned + * in the "dive_site" output parameter. */ -struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip) +struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip, struct dive_site **site) { struct dive *res = alloc_dive(); int cylinders_map_a[MAX_CYLINDERS], cylinders_map_b[MAX_CYLINDERS]; @@ -3490,10 +3503,7 @@ struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, join_dive_computers(res, &res->dc, &a->dc, &b->dc, cylinders_map_a, cylinders_map_b, 0); /* we take the first dive site, unless it's empty */ - if (a->dive_site && !dive_site_is_empty(a->dive_site)) - res->dive_site = a->dive_site; - else - res->dive_site = b->dive_site; + *site = a->dive_site && !dive_site_is_empty(a->dive_site) ? a->dive_site : b->dive_site; fixup_dive(res); return res; } @@ -4034,7 +4044,8 @@ static void dive_set_geodata_from_picture(struct dive *dive, struct picture *pic if (ds) { ds->location = picture->location; } else { - dive->dive_site = create_dive_site_with_gps("", &picture->location, table); + ds = create_dive_site_with_gps("", &picture->location, table); + add_dive_to_dive_site(dive, ds); invalidate_dive_cache(dive); } } diff --git a/core/dive.h b/core/dive.h index 7c41f6c73..25df599e4 100644 --- a/core/dive.h +++ b/core/dive.h @@ -538,7 +538,7 @@ extern unsigned int dc_airtemp(const struct divecomputer *dc); extern unsigned int dc_watertemp(const struct divecomputer *dc); extern int split_dive(const struct dive *dive, struct dive **new1, struct dive **new2); extern int split_dive_at_time(const struct dive *dive, duration_t time, struct dive **new1, struct dive **new2); -extern struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip); +extern struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip, struct dive_site **site); extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded); extern struct event *clone_event(const struct event *src_ev); extern void copy_events(const struct divecomputer *s, struct divecomputer *d); diff --git a/core/divelist.c b/core/divelist.c index 67a71ca14..5fe41a7d9 100644 --- a/core/divelist.c +++ b/core/divelist.c @@ -1169,6 +1169,7 @@ void delete_single_dive(int idx) if (dive->selected) deselect_dive(dive); remove_dive_from_trip(dive, &trip_table); + unregister_dive_from_dive_site(dive); delete_dive_from_table(&dive_table, idx); } @@ -1337,6 +1338,7 @@ static void merge_imported_dives(struct dive_table *table) struct dive *prev = table->dives[i - 1]; struct dive *dive = table->dives[i]; struct dive *merged; + struct dive_site *ds; /* only try to merge overlapping dives - or if one of the dives has * zero duration (that might be a gps marker from the webservice) */ @@ -1348,6 +1350,13 @@ static void merge_imported_dives(struct dive_table *table) if (!merged) continue; + /* Add dive to dive site; try_to_merge() does not do that! */ + ds = merged->dive_site; + if (ds) { + merged->dive_site = NULL; + add_dive_to_dive_site(merged, ds); + } + /* Overwrite the first of the two dives and remove the second */ free_dive(prev); table->dives[i - 1] = merged; @@ -1531,15 +1540,15 @@ void add_imported_dives(struct dive_table *import_table, struct trip_table *impo process_imported_dives(import_table, import_trip_table, import_sites_table, flags, &dives_to_add, &dives_to_remove, &trips_to_add, &dive_sites_to_add); - /* Add new dives to trip, so that trips don't get deleted - * on deletion of old dives */ + /* Add new dives to trip and site to get reference count correct. */ for (i = 0; i < dives_to_add.nr; i++) { struct dive *d = dives_to_add.dives[i]; struct dive_trip *trip = d->divetrip; - if (!trip) - continue; + struct dive_site *site = d->dive_site; d->divetrip = NULL; + d->dive_site = NULL; add_dive_to_trip(d, trip); + add_dive_to_dive_site(d, site); } /* Remove old dives */ @@ -1716,6 +1725,7 @@ void process_imported_dives(struct dive_table *import_table, struct trip_table * if (!old_ds) { /* Dive site doesn't exist. Add it to list of dive sites to be added. */ + new_ds->dives.nr = 0; /* Caller is responsible for adding dives to site */ add_dive_site_to_table(new_ds, sites_to_add); continue; } diff --git a/core/divesite.c b/core/divesite.c index d53b72b4b..45a3221be 100644 --- a/core/divesite.c +++ b/core/divesite.c @@ -339,7 +339,8 @@ void merge_dive_sites(struct dive_site *ref, struct dive_site *dive_sites[], int for_each_dive(curr_dive, d) { if (d->dive_site != dive_sites[i] ) continue; - d->dive_site = ref; + unregister_dive_from_dive_site(d); + add_dive_to_dive_site(d, ref); invalidate_dive_cache(d); } } @@ -377,7 +378,7 @@ void purge_empty_dive_sites(struct dive_site_table *ds_table) continue; for_each_dive(j, d) { if (d->dive_site == ds) - d->dive_site = NULL; + unregister_dive_from_dive_site(d); } } } @@ -387,8 +388,10 @@ void add_dive_to_dive_site(struct dive *d, struct dive_site *ds) int idx; if (d->dive_site == ds) return; - if (d->dive_site) + if (d->dive_site) { fprintf(stderr, "Warning: adding dive that already belongs to a dive site to a different site\n"); + unregister_dive_from_dive_site(d); + } idx = dive_table_get_insertion_index(&ds->dives, d); add_to_dive_table(&ds->dives, idx, d); d->dive_site = ds; diff --git a/core/gpslocation.cpp b/core/gpslocation.cpp index 188cfd81c..3c63d4dbd 100644 --- a/core/gpslocation.cpp +++ b/core/gpslocation.cpp @@ -213,7 +213,7 @@ static void copy_gps_location(struct gpsTracker &gps, struct dive *d) struct dive_site *ds = d->dive_site; if (!ds) { ds = create_dive_site(qPrintable(gps.name), &dive_site_table); - d->dive_site = ds; + add_dive_to_dive_site(d, ds); } ds->location = gps.location; } diff --git a/core/import-cobalt.c b/core/import-cobalt.c index a51d4b9fa..191692e28 100644 --- a/core/import-cobalt.c +++ b/core/import-cobalt.c @@ -197,7 +197,7 @@ static int cobalt_dive(void *param, int columns, char **data, char **column) return 1; } sprintf(tmp, "%s / %s", location, location_site); - state->cur_dive->dive_site = find_or_create_dive_site_with_name(tmp, state->sites); + add_dive_to_dive_site(state->cur_dive, find_or_create_dive_site_with_name(tmp, state->sites)); free(tmp); } free(location); diff --git a/core/import-divinglog.c b/core/import-divinglog.c index 4f2b1e932..6051cc8bd 100644 --- a/core/import-divinglog.c +++ b/core/import-divinglog.c @@ -287,7 +287,7 @@ static int divinglog_dive(void *param, int columns, char **data, char **column) state->cur_dive->when = (time_t)(atol(data[1])); if (data[2]) - state->cur_dive->dive_site = find_or_create_dive_site_with_name(data[2], state->sites); + add_dive_to_dive_site(state->cur_dive, find_or_create_dive_site_with_name(data[2], state->sites)); if (data[3]) utf8_string(data[3], &state->cur_dive->buddy); diff --git a/core/libdivecomputer.c b/core/libdivecomputer.c index 5519afe46..aeca1b94c 100644 --- a/core/libdivecomputer.c +++ b/core/libdivecomputer.c @@ -596,8 +596,10 @@ static void parse_string_field(device_data_t *devdata, struct dive *dive, dc_fie parse_location(line, &location); - if (location.lat.udeg && location.lon.udeg) - dive->dive_site = create_dive_site_with_gps(str->value, &location, devdata->sites); + if (location.lat.udeg && location.lon.udeg) { + unregister_dive_from_dive_site(dive); + add_dive_to_dive_site(dive, create_dive_site_with_gps(str->value, &location, devdata->sites)); + } } } #endif diff --git a/core/liquivision.c b/core/liquivision.c index 621a921be..01e9843c1 100644 --- a/core/liquivision.c +++ b/core/liquivision.c @@ -191,7 +191,7 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int /* Store the location only if we have one */ if (len || place_len) { - dive->dive_site = find_or_create_dive_site_with_name(location, sites); + add_dive_to_dive_site(dive, find_or_create_dive_site_with_name(location, sites)); free(location); } diff --git a/core/load-git.c b/core/load-git.c index 84af37196..f74950248 100644 --- a/core/load-git.c +++ b/core/load-git.c @@ -159,9 +159,8 @@ static void parse_dive_gps(char *line, struct membuffer *str, void *_dive) if (!ds) { ds = get_dive_site_by_gps(&location, &dive_site_table); if (!ds) - dive->dive_site = create_dive_site_with_gps("", &location, &dive_site_table); - else - dive->dive_site = ds; + ds = create_dive_site_with_gps("", &location, &dive_site_table); + add_dive_to_dive_site(dive, ds); } else { if (dive_site_has_gps_location(ds) && !same_location(&ds->location, &location)) { char *coords = printGPSCoordsC(&location); @@ -183,9 +182,8 @@ static void parse_dive_location(char *line, struct membuffer *str, void *_dive) if (!ds) { ds = get_dive_site_by_name(name, &dive_site_table); if (!ds) - dive->dive_site = create_dive_site(name, &dive_site_table); - else - dive->dive_site = ds; + ds = create_dive_site(name, &dive_site_table); + add_dive_to_dive_site(dive, ds); } else { // we already had a dive site linked to the dive if (empty_string(ds->name)) { @@ -212,7 +210,7 @@ static void parse_dive_notes(char *line, struct membuffer *str, void *_dive) { UNUSED(line); struct dive *dive = _dive; dive->notes = get_utf8(str); } static void parse_dive_divesiteid(char *line, struct membuffer *str, void *_dive) -{ UNUSED(str); struct dive *dive = _dive; dive->dive_site = get_dive_site_by_uuid(get_hex(line), &dive_site_table); } +{ UNUSED(str); struct dive *dive = _dive; add_dive_to_dive_site(dive, get_dive_site_by_uuid(get_hex(line), &dive_site_table)); } /* * We can have multiple tags in the membuffer. They are separated by diff --git a/core/parse-xml.c b/core/parse-xml.c index 99aef7904..d3ee13b57 100644 --- a/core/parse-xml.c +++ b/core/parse-xml.c @@ -558,11 +558,11 @@ static void hex_value(char *buffer, uint32_t *i) *i = strtoul(buffer, NULL, 16); } -static void dive_site(char *buffer, struct dive_site **ds, struct parser_state *state) +static void dive_site(char *buffer, struct dive *d, struct parser_state *state) { uint32_t uuid; hex_value(buffer, &uuid); - *ds = get_dive_site_by_uuid(uuid, state->sites); + add_dive_to_dive_site(d, get_dive_site_by_uuid(uuid, state->sites)); } static void get_notrip(char *buffer, bool *notrip) @@ -972,9 +972,10 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu nonmatch("sample", name, buf); } -static void divinglog_place(char *place, struct dive_site **ds, struct parser_state *state) +static void divinglog_place(char *place, struct dive *d, struct parser_state *state) { char buffer[1024]; + struct dive_site *ds; snprintf(buffer, sizeof(buffer), "%s%s%s%s%s", @@ -983,9 +984,10 @@ static void divinglog_place(char *place, struct dive_site **ds, struct parser_st state->city ? state->city : "", state->country ? ", " : "", state->country ? state->country : ""); - *ds = get_dive_site_by_name(buffer, state->sites); - if (!*ds) - *ds = create_dive_site(buffer, state->sites); + ds = get_dive_site_by_name(buffer, state->sites); + if (!ds) + ds = create_dive_site(buffer, state->sites); + add_dive_to_dive_site(d, ds); // TODO: capture the country / city info in the taxonomy instead free(state->city); @@ -1010,7 +1012,7 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf, MATCH("names.buddy", utf8_string, &dive->buddy) || MATCH("name.country", utf8_string, &state->country) || MATCH("name.city", utf8_string, &state->city) || - MATCH_STATE("name.place", divinglog_place, &dive->dive_site) || + MATCH_STATE("name.place", divinglog_place, dive) || 0; } @@ -1137,7 +1139,7 @@ static void gps_lat(char *buffer, struct dive *dive, struct parser_state *state) location.lat = parse_degrees(buffer, &end); if (!ds) { - dive->dive_site = create_dive_site_with_gps(NULL, &location, state->sites); + add_dive_to_dive_site(dive, create_dive_site_with_gps(NULL, &location, state->sites)); } else { if (ds->location.lat.udeg && ds->location.lat.udeg != location.lat.udeg) fprintf(stderr, "Oops, changing the latitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)"); @@ -1153,7 +1155,7 @@ static void gps_long(char *buffer, struct dive *dive, struct parser_state *state location.lon = parse_degrees(buffer, &end); if (!ds) { - dive->dive_site = create_dive_site_with_gps(NULL, &location, state->sites); + add_dive_to_dive_site(dive, create_dive_site_with_gps(NULL, &location, state->sites)); } else { if (ds->location.lon.udeg && ds->location.lon.udeg != location.lon.udeg) fprintf(stderr, "Oops, changing the longitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)"); @@ -1189,10 +1191,10 @@ static void gps_in_dive(char *buffer, struct dive *dive, struct parser_state *st // found a site nearby; in case it turns out this one had a different name let's // remember the original coordinates so we can create the correct dive site later state->cur_location = location; - dive->dive_site = ds; } else { - dive->dive_site = create_dive_site_with_gps("", &location, state->sites); + ds = create_dive_site_with_gps("", &location, state->sites); } + add_dive_to_dive_site(dive, ds); } else { if (dive_site_has_gps_location(ds) && has_location(&location) && !same_location(&ds->location, &location)) { @@ -1234,7 +1236,7 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str default: break; } - if (MATCH_STATE("divesiteid", dive_site, &dive->dive_site)) + if (MATCH_STATE("divesiteid", dive_site, dive)) return; if (MATCH("number", get_index, &dive->number)) return; @@ -2122,7 +2124,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct dive_table *tabl /* Measure GPS */ state.cur_location.lat.udeg = (int)((ptr[7] << 24) + (ptr[6] << 16) + (ptr[5] << 8) + (ptr[4] << 0)); state.cur_location.lon.udeg = (int)((ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + (ptr[8] << 0)); - state.cur_dive->dive_site = create_dive_site_with_gps("DLF imported", &state.cur_location, state.sites); + add_dive_to_dive_site(state.cur_dive, create_dive_site_with_gps("DLF imported", &state.cur_location, state.sites)); break; default: break; diff --git a/core/parse.c b/core/parse.c index 87d2b8ea3..b40d2ce90 100644 --- a/core/parse.c +++ b/core/parse.c @@ -415,14 +415,14 @@ void add_dive_site(char *ds_name, struct dive *dive, struct parser_state *state) char *buffer = ds_name; char *to_free = NULL; int size = trimspace(buffer); - if(size) { + if (size) { struct dive_site *ds = dive->dive_site; if (!ds) { - // if the dive doesn't have a uuid, check if there's already a dive site by this name + // if the dive doesn't have a dive site, check if there's already a dive site by this name ds = get_dive_site_by_name(buffer, state->sites); } if (ds) { - // we have a uuid, let's hope there isn't a different name + // we have a dive site, let's hope there isn't a different name if (empty_string(ds->name)) { ds->name = copy_string(buffer); } else if (!same_string(ds->name, buffer)) { @@ -432,10 +432,12 @@ void add_dive_site(char *ds_name, struct dive *dive, struct parser_state *state) // way around struct dive_site *exact_match = get_dive_site_by_gps_and_name(buffer, &ds->location, state->sites); if (exact_match) { - dive->dive_site = exact_match; + unregister_dive_from_dive_site(dive); + add_dive_to_dive_site(dive, exact_match); } else { struct dive_site *newds = create_dive_site(buffer, state->sites); - dive->dive_site = newds; + unregister_dive_from_dive_site(dive); + add_dive_to_dive_site(dive, newds); if (has_location(&state->cur_location)) { // we started this uuid with GPS data, so lets use those newds->location = state->cur_location; @@ -444,12 +446,13 @@ void add_dive_site(char *ds_name, struct dive *dive, struct parser_state *state) } newds->notes = add_to_string(newds->notes, translate("gettextFromC", "additional name for site: %s\n"), ds->name); } - } else { + } else if (dive->dive_site != ds) { // add the existing dive site to the current dive - dive->dive_site = ds; + unregister_dive_from_dive_site(dive); + add_dive_to_dive_site(dive, ds); } } else { - dive->dive_site = create_dive_site(buffer, state->sites); + add_dive_to_dive_site(dive, create_dive_site(buffer, state->sites)); } } free(to_free); diff --git a/core/uemis-downloader.c b/core/uemis-downloader.c index 76e6dcf09..593b94617 100644 --- a/core/uemis-downloader.c +++ b/core/uemis-downloader.c @@ -996,7 +996,8 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, char * int divespot_id = atoi(val); if (divespot_id != -1) { struct dive_site *ds = create_dive_site("from Uemis", devdata->sites); - dive->dive_site = ds; + unregister_dive_from_dive_site(dive); + add_dive_to_dive_site(dive, ds); uemis_mark_divelocation(dive->dc.diveid, divespot_id, ds); } #if UEMIS_DEBUG & 2 @@ -1182,7 +1183,8 @@ static void get_uemis_divespot(device_data_t *devdata, const char *mountpath, in if (is_divespot_mappable(divespot_id)) { struct dive_site *ds = get_dive_site_by_divespot_id(divespot_id); - dive->dive_site = ds; + unregister_dive_from_dive_site(dive); + add_dive_to_dive_site(dive, ds); } else if (nds && nds->name && strstr(nds->name,"from Uemis")) { if (load_uemis_divespot(mountpath, divespot_id)) { /* get the divesite based on the diveid, this should give us @@ -1198,7 +1200,8 @@ static void get_uemis_divespot(device_data_t *devdata, const char *mountpath, in /* if the uuid's are the same, the new site is a duplicate and can be deleted */ if (nds->uuid != ods->uuid) { delete_dive_site(nds, devdata->sites); - dive->dive_site = ods; + unregister_dive_from_dive_site(dive); + add_dive_to_dive_site(dive, ods); } } add_to_divespot_mapping(divespot_id, dive->dive_site); |