OSyncMappingEngine *_osync_obj_engine_create_mapping_engine(OSyncObjEngine *engine, OSyncError **error) { /* If there is none, create one */ OSyncMapping *mapping = osync_mapping_new(error); GList *s = NULL; OSyncMappingEngine *mapping_engine = NULL; if (!mapping) goto error; osync_mapping_set_id(mapping, osync_mapping_table_get_next_id(engine->mapping_table)); osync_mapping_table_add_mapping(engine->mapping_table, mapping); for (s = engine->sink_engines; s; s = s->next) { OSyncSinkEngine *sink_engine = s->data; OSyncMember *member = osync_client_proxy_get_member(sink_engine->proxy); OSyncMappingEntry *mapping_entry = osync_mapping_entry_new(error); osync_mapping_entry_set_member_id(mapping_entry, osync_member_get_id(member)); osync_mapping_add_entry(mapping, mapping_entry); osync_mapping_entry_unref(mapping_entry); } mapping_engine = osync_mapping_engine_new(engine, mapping, error); if (!mapping_engine) goto error_free_mapping; osync_mapping_unref(mapping); return mapping_engine; error_free_mapping: osync_mapping_unref(mapping); error: return NULL; }
/** @brief Searches for a member by its id * * @param group The group in which to search * @param id The id of the member * @returns The member, or NULL if not found * */ OSyncMember *osync_group_find_member(OSyncGroup *group, int id) { GList *m = NULL; for (m = group->members; m; m = m->next) { OSyncMember *member = m->data; if (osync_member_get_id(member) == id) return member; } return NULL; }
static osync_bool check_mappings(OSyncEngine *engine) { member_info *meminfo = NULL; GList *m; for (m = members; m; m = m->next) { meminfo = m->data; if (g_list_length(engine->maptable->mappings) != g_list_length(meminfo->changes)) { printf("Number of mappings do not match for member %lli, %i compared to %i\n", osync_member_get_id(meminfo->member), g_list_length(engine->maptable->mappings), g_list_length(meminfo->changes)); return FALSE; } } return TRUE; }
/** @brief Solves the conflict by duplicating the conflicting entries * * @param engine The engine * @param dupe_mapping The conflicting mapping to duplicate * */ osync_bool osync_mapping_engine_duplicate(OSyncMappingEngine *existingMapping, OSyncError **error) { int elevation = 0; OSyncObjEngine *objengine = NULL; GList *entries = NULL, *e = NULL, *mappings = NULL; osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, existingMapping, error); g_assert(existingMapping); objengine = existingMapping->parent; /* Remove all deleted items first and copy the changes to a list */ e = existingMapping->entries; for (; e; e = e->next) { OSyncMappingEntryEngine *entry = e->data; if (entry->change) { if (osync_change_get_changetype(entry->change) == OSYNC_CHANGE_TYPE_MODIFIED || osync_change_get_changetype(entry->change) == OSYNC_CHANGE_TYPE_ADDED) { osync_trace(TRACE_INTERNAL, "Appending entry %s, changetype %i from member %lli", osync_change_get_uid(entry->change), osync_change_get_changetype(entry->change), osync_member_get_id(osync_client_proxy_get_member(entry->sink_engine->proxy))); entries = g_list_append(entries, entry); } else { osync_trace(TRACE_INTERNAL, "Removing entry %s, changetype %i from member %lli", osync_change_get_uid(entry->change), osync_change_get_changetype(entry->change), osync_member_get_id(osync_client_proxy_get_member(entry->sink_engine->proxy))); osync_entry_engine_update(entry, NULL); } } else { osync_trace(TRACE_INTERNAL, "member %lli does not have a entry", osync_member_get_id(osync_client_proxy_get_member(entry->sink_engine->proxy))); } } /* Create a list with mappings. In the beginning, only the exisiting mapping is in the list */ mappings = g_list_append(NULL, existingMapping); osync_mapping_engine_ref(existingMapping); while (entries) { OSyncMappingEntryEngine *existingEntry = entries->data; /* Now lets see which mapping is the correct one for the entry */ GList *m = NULL; OSyncMappingEngine *mapping = NULL; OSyncChange *existingChange = NULL; osync_bool dirty = FALSE; OSyncMappingEntryEngine *newEntry = NULL; elevation = 0; for (m = mappings; m; m = m->next) { GList *e = NULL; OSyncChange *change = NULL; OSyncMappingEntryEngine *entry = NULL; mapping = m->data; /* Get the first change of the mapping to test. Compare the given change with this change. * If they are not the same, we have found a new mapping */ for (e = mapping->entries; e; e = e->next) { entry = e->data; change = entry->change; if (change) break; } if (!change || osync_change_compare(existingEntry->change, change) == OSYNC_CONV_DATA_SAME){ existingChange = existingEntry->change; osync_change_ref(existingChange); osync_assert(osync_change_get_uid(existingChange)); break; } mapping = NULL; elevation++; existingChange = osync_change_clone(existingEntry->change, error); osync_assert(osync_change_get_uid(existingChange)); } if (!mapping) { /* Unable to find a mapping. We have to create a new one */ mapping = _osync_obj_engine_create_mapping_engine(objengine, error); if (!mapping) goto error; mappings = g_list_append(mappings, mapping); objengine->mapping_engines = g_list_append(objengine->mapping_engines, mapping); osync_mapping_engine_ref(mapping); } /* update the uid and the content to suit the new level */ if (!_osync_change_elevate(existingChange, elevation, &dirty, error)) goto error; /* Lets add the entry to the mapping */ newEntry = osync_mapping_engine_get_entry(mapping, existingEntry->sink_engine); osync_assert(newEntry); osync_entry_engine_update(newEntry, existingChange); osync_mapping_entry_set_uid(newEntry->entry, osync_change_get_uid(existingChange)); osync_change_unref(existingChange); /* Set the last entry as the master */ osync_mapping_engine_set_master(mapping, newEntry); /* Update the dirty status. If the duplicate function said * that the returned item needs to be written, we will set * this information here */ newEntry->dirty = dirty; entries = g_list_remove(entries, existingEntry); } while (mappings) { OSyncMappingEngine *mapping = mappings->data; osync_mapping_engine_unref(mapping); mappings = g_list_remove(mappings, mapping); } objengine->conflicts = g_list_remove(objengine->conflicts, existingMapping); osync_status_update_mapping(objengine->parent, existingMapping, OSYNC_MAPPING_EVENT_SOLVED, NULL); if (osync_engine_check_get_changes(objengine->parent) && osync_bitcount(objengine->sink_errors | objengine->sink_get_changes) == g_list_length(objengine->sink_engines)) { if (!osync_obj_engine_command(objengine, OSYNC_ENGINE_COMMAND_WRITE, error)) goto error; } else osync_trace(TRACE_INTERNAL, "Not triggering write. didnt receive all reads yet"); osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; error: while (mappings) { OSyncMappingEngine *mapping = mappings->data; osync_mapping_engine_unref(mapping); mappings = g_list_remove(mappings, mapping); } osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return FALSE; }
OSyncMappingEngine *osync_mapping_engine_new(OSyncObjEngine *parent, OSyncMapping *mapping, OSyncError **error) { OSyncMappingEngine *engine = NULL; GList *s = NULL; osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parent, mapping, error); osync_assert(parent); osync_assert(mapping); engine = osync_try_malloc0(sizeof(OSyncMappingEngine), error); if (!engine) goto error; engine->ref_count = 1; engine->mapping = mapping; osync_mapping_ref(mapping); engine->parent = parent; engine->synced = TRUE; for (s = parent->sink_engines; s; s = s->next) { OSyncSinkEngine *sink_engine = s->data; OSyncMappingEntryEngine *entry_engine = NULL; OSyncMember *member = osync_client_proxy_get_member(sink_engine->proxy); OSyncMappingEntry *mapping_entry = osync_mapping_find_entry_by_member_id(mapping, osync_member_get_id(member)); osync_assert(mapping_entry); entry_engine = osync_entry_engine_new(mapping_entry, engine, sink_engine, parent, error); if (!entry_engine) goto error_free_engine; engine->entries = g_list_append(engine->entries, entry_engine); } osync_trace(TRACE_EXIT, "%s: %p", __func__, engine); return engine; error_free_engine: osync_mapping_engine_unref(engine); error: osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return NULL; }
osync_bool osync_sink_engine_write(OSyncSinkEngine *engine, OSyncArchive *archive, OSyncError **error) { OSyncList *o; const char *objtype; OSyncMember *member; osync_assert(engine); osync_assert(archive); objtype = osync_obj_engine_get_objtype(engine->engine); member = osync_client_proxy_get_member(engine->proxy); for (o = engine->entries; o; o = o->next) { OSyncMappingEntryEngine *entry_engine = o->data; osync_assert(entry_engine); if (osync_entry_engine_is_dirty(entry_engine)) { OSyncChange *change = osync_entry_engine_get_change(entry_engine); osync_assert(change); osync_trace(TRACE_INTERNAL, "Writing change %s, changetype %i, format %s , objtype %s from member %i", osync_change_get_uid(change), osync_change_get_changetype(change), osync_objformat_get_name(osync_change_get_objformat(change)), osync_change_get_objtype(change), osync_member_get_id(member)); if (!osync_client_proxy_commit_change(engine->proxy, osync_obj_engine_commit_change_callback, entry_engine, change, error)) goto error; } else if (entry_engine->change) { OSyncMapping *mapping = entry_engine->mapping_engine->mapping; OSyncMappingEntry *entry = entry_engine->entry; /* FIXME: Don't mix up in this function objtypes */ /* osync_assert_msg(!strcmp(objtype, osync_change_get_objtype(entry_engine->change), "Mixed-objtype in final write!")); */ if (osync_change_get_changetype(entry_engine->change) == OSYNC_CHANGE_TYPE_DELETED) { if (!osync_archive_delete_change(archive, osync_mapping_entry_get_id(entry), osync_change_get_objtype(entry_engine->change), error)) goto error; } else { if (!osync_archive_save_change(archive, osync_mapping_entry_get_id(entry), osync_change_get_uid(entry_engine->change), osync_change_get_objtype(entry_engine->change), osync_mapping_get_id(mapping), osync_member_get_id(member), objtype, error)) goto error; } } } if (!osync_client_proxy_committed_all(engine->proxy, osync_obj_engine_written_callback, engine, objtype, error)) goto error; return TRUE; error: return FALSE; }
osync_bool osync_obj_engine_command(OSyncObjEngine *engine, OSyncEngineCmd cmd, OSyncError **error) { GList *p = NULL; GList *m = NULL; GList *e = NULL; OSyncSinkEngine *sinkengine = NULL; osync_trace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, engine, cmd, error); osync_assert(engine); switch (cmd) { int write_sinks = 0; osync_bool proxy_disconnect = FALSE; case OSYNC_ENGINE_COMMAND_CONNECT: for (p = engine->sink_engines; p; p = p->next) { sinkengine = p->data; if (!osync_client_proxy_connect(sinkengine->proxy, _osync_obj_engine_connect_callback, sinkengine, engine->objtype, engine->slowsync, error)) goto error; } break; case OSYNC_ENGINE_COMMAND_READ: for (p = engine->sink_engines; p; p = p->next) { sinkengine = p->data; for (m = sinkengine->entries; m; m = m->next) { OSyncMappingEntryEngine *entry = m->data; OSyncChange *change = entry->change; if (!change) continue; if (!osync_client_proxy_read(sinkengine->proxy, _osync_obj_engine_read_ignored_callback, sinkengine, change, error)) goto error; } } if (engine->archive) { /* Flush the changelog - to avoid double entries of ignored entries */ if (!osync_archive_flush_ignored_conflict(engine->archive, engine->objtype, error)) goto error; } write_sinks = _osync_obj_engine_num_write_sinks(engine); /* Get change entries since last sync. (get_changes) */ for (p = engine->sink_engines; p; p = p->next) { OSyncMember *member = NULL; OSyncObjTypeSink *objtype_sink = NULL; sinkengine = p->data; member = osync_client_proxy_get_member(sinkengine->proxy); objtype_sink = osync_member_find_objtype_sink(member, engine->objtype); /* Is there at least one other writeable sink? */ if (objtype_sink && osync_objtype_sink_get_write(objtype_sink) && write_sinks) { _osync_obj_engine_read_callback(sinkengine->proxy, sinkengine, *error); osync_trace(TRACE_INTERNAL, "no other writable sinks .... SKIP"); continue; } if (!osync_client_proxy_get_changes(sinkengine->proxy, _osync_obj_engine_read_callback, sinkengine, engine->objtype, engine->slowsync, error)) goto error; } break; case OSYNC_ENGINE_COMMAND_WRITE: if (engine->conflicts) { osync_trace(TRACE_INTERNAL, "We still have conflict. Delaying write"); break; } if (engine->written) { osync_trace(TRACE_INTERNAL, "Already written"); break; } engine->written = TRUE; /* Write the changes. First, we can multiply the winner in the mapping */ osync_trace(TRACE_INTERNAL, "Preparing write. multiplying %i mappings", g_list_length(engine->mapping_engines)); for (m = engine->mapping_engines; m; m = m->next) { OSyncMappingEngine *mapping_engine = m->data; if (!osync_mapping_engine_multiply(mapping_engine, error)) goto error; } osync_trace(TRACE_INTERNAL, "Starting to write"); for (p = engine->sink_engines; p; p = p->next) { OSyncMember *member = NULL; long long int memberid = 0; OSyncObjTypeSink *objtype_sink = NULL; OSyncFormatConverterPath *path = NULL; sinkengine = p->data; member = osync_client_proxy_get_member(sinkengine->proxy); memberid = osync_member_get_id(member); objtype_sink = osync_member_find_objtype_sink(member, engine->objtype); /* If sink could not be found use "data" sink if available */ if (!objtype_sink) objtype_sink = osync_member_find_objtype_sink(member, "data"); /* TODO: Review if objtype_sink = NULL is valid at all. */ for (e = sinkengine->entries; e; e = e->next) { OSyncMappingEntryEngine *entry_engine = e->data; osync_assert(entry_engine); /* Merger - Save the entire xml and demerge */ /* TODO: is here the right place to save the xml???? */ if (osync_group_get_merger_enabled(osync_engine_get_group(engine->parent)) && osync_group_get_converter_enabled(osync_engine_get_group(engine->parent)) && entry_engine->change && (osync_change_get_changetype(entry_engine->change) != OSYNC_CHANGE_TYPE_DELETED) && !strncmp(osync_objformat_get_name(osync_change_get_objformat(entry_engine->change)), "xmlformat-", 10) ) { char *buffer = NULL; unsigned int xmlformat_size = 0, size = 0; OSyncXMLFormat *xmlformat = NULL; const char *objtype = NULL; OSyncMapping *mapping = NULL; OSyncMerger *merger = NULL; osync_trace(TRACE_INTERNAL, "Entry %s for member %lli: Dirty: %i", osync_change_get_uid(entry_engine->change), memberid, osync_entry_engine_is_dirty(entry_engine)); osync_trace(TRACE_INTERNAL, "Save the entire XMLFormat and demerge."); objtype = osync_change_get_objtype(entry_engine->change); mapping = entry_engine->mapping_engine->mapping; osync_data_get_data(osync_change_get_data(entry_engine->change), (char **) &xmlformat, &xmlformat_size); osync_assert(xmlformat_size == osync_xmlformat_size()); if(!osync_xmlformat_assemble(xmlformat, &buffer, &size)) { osync_error_set(error, OSYNC_ERROR_GENERIC, "Could not assamble the xmlformat"); goto error; } if(!osync_archive_save_data(engine->archive, osync_mapping_get_id(mapping), objtype, buffer, size, error)) { g_free(buffer); goto error; } g_free(buffer); merger = osync_member_get_merger(osync_client_proxy_get_member(sinkengine->proxy)); if(merger) osync_merger_demerge(merger, xmlformat); } /* Only commit change if the objtype sink is able/allowed to write. */ if (objtype_sink && osync_objtype_sink_get_write(objtype_sink) && osync_entry_engine_is_dirty(entry_engine)) { OSyncChange *change = entry_engine->change; osync_assert(entry_engine->change); /* Convert to requested target format if the changetype is not DELETED */ if (osync_group_get_converter_enabled(osync_engine_get_group(engine->parent)) && (osync_change_get_changetype(change) != OSYNC_CHANGE_TYPE_DELETED)) { char *objtype = NULL; OSyncList *format_sinks = NULL; unsigned int length = 0; OSyncFormatConverter *converter = NULL; osync_trace(TRACE_INTERNAL, "Starting to convert from objtype %s and format %s", osync_change_get_objtype(entry_engine->change), osync_objformat_get_name(osync_change_get_objformat(entry_engine->change))); /* We have to save the objtype of the change so that it does not get * overwritten by the conversion */ objtype = g_strdup(osync_change_get_objtype(change)); /* Now we have to convert to one of the formats * that the client can understand */ format_sinks = osync_objtype_sink_get_objformat_sinks(objtype_sink); if (!format_sinks) { osync_error_set(error, OSYNC_ERROR_GENERIC, "There are no available format sinks."); goto error; } /* We cache the converter path for each sink/member couple */ if (!path) { path = osync_format_env_find_path_formats_with_detectors(engine->formatenv, osync_change_get_data(entry_engine->change), format_sinks, osync_objtype_sink_get_preferred_format(objtype_sink), error); } if (!path) goto error; length = osync_converter_path_num_edges(path); converter = osync_converter_path_nth_edge(path, length - 1); if (converter) { OSyncObjFormat *format = osync_converter_get_targetformat(converter); OSyncObjFormatSink *formatsink = osync_objtype_sink_find_objformat_sink(objtype_sink, format); osync_converter_path_set_config(path, osync_objformat_sink_get_config(formatsink)); } if (!osync_format_env_convert(engine->formatenv, path, osync_change_get_data(entry_engine->change), error)) { osync_converter_path_unref(path); goto error; } osync_trace(TRACE_INTERNAL, "converted to format %s", osync_objformat_get_name(osync_change_get_objformat(entry_engine->change))); osync_change_set_objtype(change, objtype); g_free(objtype); } osync_trace(TRACE_INTERNAL, "Writing change %s, changetype %i, format %s , objtype %s from member %lli", osync_change_get_uid(change), osync_change_get_changetype(change), osync_objformat_get_name(osync_change_get_objformat(change)), osync_change_get_objtype(change), osync_member_get_id(osync_client_proxy_get_member(sinkengine->proxy))); if (!osync_client_proxy_commit_change(sinkengine->proxy, _osync_obj_engine_commit_change_callback, entry_engine, osync_entry_engine_get_change(entry_engine), error)) goto error; } else if (entry_engine->change) { OSyncMapping *mapping = entry_engine->mapping_engine->mapping; OSyncMember *member = osync_client_proxy_get_member(sinkengine->proxy); OSyncMappingEntry *entry = entry_engine->entry; const char *objtype = osync_change_get_objtype(entry_engine->change); if (engine->archive) { if (osync_change_get_changetype(entry_engine->change) == OSYNC_CHANGE_TYPE_DELETED) { if (!osync_archive_delete_change(engine->archive, osync_mapping_entry_get_id(entry), objtype, error)) goto error; } else { if (!osync_archive_save_change(engine->archive, osync_mapping_entry_get_id(entry), osync_change_get_uid(entry_engine->change), objtype, osync_mapping_get_id(mapping), osync_member_get_id(member), error)) goto error; } } } } if (path) osync_converter_path_unref(path); if (!osync_client_proxy_committed_all(sinkengine->proxy, _osync_obj_engine_written_callback, sinkengine, engine->objtype, error)) goto error; } break; case OSYNC_ENGINE_COMMAND_SYNC_DONE: for (p = engine->sink_engines; p; p = p->next) { sinkengine = p->data; if (!osync_client_proxy_sync_done(sinkengine->proxy, _osync_obj_engine_sync_done_callback, sinkengine, engine->objtype, error)) goto error; } break; case OSYNC_ENGINE_COMMAND_DISCONNECT:; for (p = engine->sink_engines; p; p = p->next) { sinkengine = p->data; /* Don't call client disconnect functions if the sink is already disconnected. This avoids unintended disconnect calls of clients/plugins which might not prepared for a disconnect call when their never got connected. (testcases: *_connect_error, *_connect_timeout ..) */ if (!osync_sink_engine_is_connected(sinkengine)) continue; proxy_disconnect = TRUE; if (!osync_client_proxy_disconnect(sinkengine->proxy, _osync_obj_engine_disconnect_callback, sinkengine, engine->objtype, error)) goto error; } /* If no client needs to be disconnected, we MUST NOT expected any disconnected_callback which generates an OSYNC_ENGINE_EVENT_DISCONNECTED event. So we directly generate such event on our own. (testcases: double_connect_*, triple_connnect_*) */ if (!proxy_disconnect) _osync_obj_engine_generate_event_disconnected(engine, NULL); break; case OSYNC_ENGINE_COMMAND_SOLVE: case OSYNC_ENGINE_COMMAND_DISCOVER: case OSYNC_ENGINE_COMMAND_ABORT: break; } osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; error: osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return FALSE; }
static void _osync_obj_engine_commit_change_callback(OSyncClientProxy *proxy, void *userdata, const char *uid, OSyncError *error) { OSyncMappingEntryEngine *entry_engine = userdata; OSyncObjEngine *engine = entry_engine->objengine; OSyncSinkEngine *sinkengine = entry_engine->sink_engine; OSyncError *locerror = NULL; OSyncMapping *mapping = NULL; OSyncMember *member = NULL; OSyncMappingEntry *entry = NULL; const char *objtype = NULL; long long int id = 0; osync_trace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, proxy, userdata, uid, error); osync_entry_engine_set_dirty(entry_engine, FALSE); mapping = entry_engine->mapping_engine->mapping; member = osync_client_proxy_get_member(proxy); entry = entry_engine->entry; objtype = osync_change_get_objtype(entry_engine->change); id = osync_mapping_entry_get_id(entry); if (error) { /* Error handling (tests: single_commit_error, ...) */ /* TODO: Review differences between Mapping and Change status events - Are both really needed?! */ osync_status_update_change(engine->parent, entry_engine->change, osync_client_proxy_get_member(proxy), entry_engine->mapping_engine->mapping, OSYNC_CHANGE_EVENT_ERROR, error); osync_status_update_mapping(engine->parent, entry_engine->mapping_engine, OSYNC_MAPPING_EVENT_ERROR, error); osync_obj_engine_set_error(engine, error); engine->sink_errors = engine->sink_errors | (0x1 << sinkengine->position); goto error; } if (uid) osync_change_set_uid(entry_engine->change, uid); if (engine->archive) { if (osync_change_get_changetype(entry_engine->change) == OSYNC_CHANGE_TYPE_DELETED) { /* TODO error handling */ osync_archive_delete_change(engine->archive, id, objtype, &locerror); } else { /* TODO error handling */ osync_archive_save_change(engine->archive, id, osync_change_get_uid(entry_engine->change), objtype, osync_mapping_get_id(mapping), osync_member_get_id(member), &locerror); } } osync_assert(entry_engine->mapping_engine); osync_status_update_change(engine->parent, entry_engine->change, osync_client_proxy_get_member(proxy), entry_engine->mapping_engine->mapping, OSYNC_CHANGE_EVENT_WRITTEN, NULL); osync_entry_engine_update(entry_engine, NULL); osync_trace(TRACE_EXIT, "%s", __func__); return; error: _osync_obj_engine_generate_written_event(engine, error); osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&error)); }
osync_bool osync_obj_engine_map_changes(OSyncObjEngine *engine, OSyncError **error) { OSyncMappingEngine *mapping_engine = NULL; GList *new_mappings = NULL, *v = NULL; osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine); //osync_trace_disable(); /* Go through all sink engines that are available */ for (v = engine->sink_engines; v; v = v->next) { OSyncSinkEngine *sinkengine = v->data; /* We use a temp list to speed things up. We dont have to compare with newly created mappings for * the current sinkengine, since there will be only one entry (for the current sinkengine) so there * is no need to compare */ new_mappings = NULL; /* For each sinkengine, go through all unmapped changes */ while (sinkengine->unmapped) { OSyncChange *change = sinkengine->unmapped->data; OSyncConvCmpResult result = 0; OSyncMappingEntryEngine *entry_engine = NULL; osync_trace(TRACE_INTERNAL, "Looking for mapping for change %s, changetype %i from member %lli", osync_change_get_uid(change), osync_change_get_changetype(change), osync_member_get_id(osync_client_proxy_get_member(sinkengine->proxy))); /* See if there is an exisiting mapping, which fits the unmapped change */ result = _osync_obj_engine_mapping_find(engine, change, sinkengine, &mapping_engine); if (result == OSYNC_CONV_DATA_MISMATCH) { /* If there is none, create one */ mapping_engine = _osync_obj_engine_create_mapping_engine(engine, error); if (!mapping_engine) goto error; osync_trace(TRACE_INTERNAL, "Unable to find mapping. Creating new mapping with id %lli", osync_mapping_get_id(mapping_engine->mapping)); new_mappings = g_list_append(new_mappings, mapping_engine); } else if (result == OSYNC_CONV_DATA_SIMILAR) { mapping_engine->conflict = TRUE; } /* Update the entry which belongs to our sinkengine with the the change */ entry_engine = osync_mapping_engine_get_entry(mapping_engine, sinkengine); osync_assert(entry_engine); osync_entry_engine_update(entry_engine, change); sinkengine->unmapped = g_list_remove(sinkengine->unmapped, sinkengine->unmapped->data); osync_change_unref(change); } engine->mapping_engines = g_list_concat(engine->mapping_engines, new_mappings); } //osync_trace_enable(); osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; error: osync_trace_enable(); osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return FALSE; }
static osync_bool check_hashtables(OSyncEngine *engine) { GList *m; for (m = members; m; m = m->next) { member_info *meminfo = m->data; OSyncHashTable *table = osync_hashtable_new(); osync_hashtable_load(table, meminfo->member, NULL); /*if (osync_hashtable_num_entries(table) != g_list_length(meminfo->changes)) { printf("Hashtable for member %i has wrong number %i compared to %i\n", osync_member_get_id(meminfo->member), osync_hashtable_num_entries(table), g_list_length(meminfo->changes)); abort(); }*/ printf("hashtable %p\n", table); if (osync_hashtable_num_entries(table) && g_list_length(engine->maptable->mappings) != osync_hashtable_num_entries(table)) { printf("Number of mappings do not match hastable for member %lli, %i compared to %i\n", osync_member_get_id(meminfo->member), g_list_length(engine->maptable->mappings), osync_hashtable_num_entries(table)); return FALSE; } osync_hashtable_close(table); } return TRUE; }
void change_content(OSyncEngine *engine) { GList *m; for (m = members; m; m = m->next) { member_info *meminfo = m->data; busy = TRUE; osync_member_connect(meminfo->member, (OSyncEngCallback)stress_message_callback, NULL); if (busy) g_main_loop_run(loop); GList *c = NULL; for (c = meminfo->changes; c; c = c->next) { change_info *chinfo = c->data; if (g_random_int_range(0, 3) == 0) { switch (g_random_int_range(1, 6)) { case 1: case 5: if (osync_member_modify_random_data(meminfo->member, chinfo->change)) { printf("Modifying data %s for member %lli. Objtype: %s Format: %s\n", osync_change_get_uid(chinfo->change), osync_member_get_id(meminfo->member), osync_objtype_get_name(osync_change_get_objtype(chinfo->change)), osync_objformat_get_name(osync_change_get_objformat(chinfo->change))); chinfo->type = CHANGE_MODIFIED; } break; case 2: if (osync_member_delete_data(meminfo->member, chinfo->change)) { printf("Deleting data %s for member %lli. Objtype: %s Format: %s\n", osync_change_get_uid(chinfo->change), osync_member_get_id(meminfo->member), osync_objtype_get_name(osync_change_get_objtype(chinfo->change)), osync_objformat_get_name(osync_change_get_objformat(chinfo->change))); if (!osync_group_get_slow_sync(engine->group, osync_objtype_get_name(osync_change_get_objtype(chinfo->change)))); chinfo->type = CHANGE_DELETED; } break; case 3: //printf("Modifying all for %s\n", osync_change_get_uid(change)); break; case 4: //printf("Deleting all for %s\n", osync_change_get_uid(change)); break; default: printf("error\n"); } } } int num_new = g_random_int_range(0, 8); int n = 0;; for (n = 0; n < num_new; n++) { change_info *chinfo = g_malloc0(sizeof(change_info)); if ((chinfo->change = osync_member_add_random_data(meminfo->member, NULL))) { if (find_change_info(meminfo, chinfo->change)) continue; meminfo->changes = g_list_append(meminfo->changes, chinfo); chinfo->type = CHANGE_ADDED; chinfo->uid = g_strdup(osync_change_get_uid(chinfo->change)); printf("Adding new data %s for member %lli. Objtype: %s Format: %s\n", osync_change_get_uid(chinfo->change), osync_member_get_id(meminfo->member), osync_objtype_get_name(osync_change_get_objtype(chinfo->change)), osync_objformat_get_name(osync_change_get_objformat(chinfo->change))); } } busy = TRUE; osync_member_disconnect(meminfo->member, (OSyncEngCallback)stress_message_callback, NULL); if (busy) g_main_loop_run(loop); } }
$NetBSD$ Don't continue the if block. --- tools/osyncstress.c.orig 2009-09-20 20:14:18.000000000 +0000 +++ tools/osyncstress.c @@ -184,7 +184,7 @@ void change_content(OSyncEngine *engine) case 2: if (osync_member_delete_data(meminfo->member, chinfo->change)) { printf("Deleting data %s for member %lli. Objtype: %s Format: %s\n", osync_change_get_uid(chinfo->change), osync_member_get_id(meminfo->member), osync_objtype_get_name(osync_change_get_objtype(chinfo->change)), osync_objformat_get_name(osync_change_get_objformat(chinfo->change))); - if (!osync_group_get_slow_sync(engine->group, osync_objtype_get_name(osync_change_get_objtype(chinfo->change)))); + if (!osync_group_get_slow_sync(engine->group, osync_objtype_get_name(osync_change_get_objtype(chinfo->change)))) chinfo->type = CHANGE_DELETED; } break;