# HG changeset patch # User Olaf Wintermann # Date 1415474830 -3600 # Node ID 112dbf7ba8b0e709a0e12ce2ba618e8328b3118c # Parent ee9da935645d99e31e0128ed59b1937d39162b40 changed sync behavior diff -r ee9da935645d -r 112dbf7ba8b0 dav/sync.c --- a/dav/sync.c Mon Nov 03 15:44:17 2014 +0100 +++ b/dav/sync.c Sat Nov 08 20:27:10 2014 +0100 @@ -193,6 +193,9 @@ fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); } + // add every resource from the server to svrres + // then db-resources only contains resources which are not on the + // server LocalResource *local = ucx_map_cstr_get(db->resources, res->path); ucx_map_cstr_put(svrres, res->path, local); ucx_map_cstr_remove(db->resources, res->path); @@ -204,12 +207,14 @@ } } + // delete every remotely removed resource UcxMapIterator i = ucx_map_iterator(db->resources); LocalResource *local; UCX_MAP_FOREACH(key, local, i) { if (res_matches_filter(dir, local->path)) { continue; } + // sync_remove_resource does all necessary tests sync_remove_resource(dir, local); } ucx_map_free(db->resources); @@ -231,23 +236,19 @@ if(removed) { return 0; } - int cdt = cmd_getoption(a, "conflict") ? 0 : 1; + int cdt = cmd_getoption(a, "conflict") ? 0 : 1; // conflict detection LocalResource *local = ucx_map_cstr_get(db->resources, res->path); char *local_path = util_concat_path(dir->path, res->path); char *etag = dav_get_property(res, "D:getetag"); struct stat s; - if(local) { + if(local) { if(stat(local_path, &s)) { - if(errno == ENOENT) { - printf("removed: %s\n", res->path); - // the file is in the database, but doesn't exists - // mark the file as removed to delete it on next push - ucx_map_cstr_remove(db->resources, local->path); - ucx_map_cstr_put(db->remove, local->path, local); - return 0; - } else { + // Ignore the fact, that the file is locally removed. If the + // server has an updated version, we readd the file or the + // next push will delete it on the server. + if(errno != ENOENT) { fprintf(stderr, "Cannot stat file: %s\n", local_path); free(local_path); return -1; @@ -274,7 +275,10 @@ if(errno != ENOENT) { fprintf(stderr, "Cannot stat file: %s\n", local_path); } - } else if(cdt && !S_ISDIR(s.st_mode)) { + } else if(S_ISDIR(s.st_mode)) { + //fprintf(stderr, "Error: file %s is a directory\n", local_path); + } else if(cdt) { + // rename file on conflict rename_local_file(dir, db, res->path); } } @@ -423,24 +427,34 @@ UcxList *resources = cmd_getoption(a, "read") ? read_changes(dir, db) : local_scan(dir, db); + UcxMap *lclres = ucx_map_new(db->resources->count); UCX_FOREACH(elm, resources) { LocalResource *local_res = elm->data; if (!res_matches_filter(dir, local_res->path+1)) { - printf("put: %s\n", local_res->path); - ucx_map_cstr_put(db->resources, local_res->path, local_res); - DavResource *res = dav_resource_new(sn, local_res->path); - if(sync_put_resource(dir, res, db)) { - ucx_map_cstr_remove(db->resources, local_res->path); + // upload every changed file + if (local_resource_is_changed(dir, db, local_res)) { + printf("put: %s\n", local_res->path); + DavResource *res = dav_resource_new(sn, local_res->path); + if(sync_put_resource(dir, res, local_res)) { + // TODO: I don't know what to do now + } + dav_resource_free(res); } - dav_resource_free(res); + + // remove every locally available resource from db->resource + // the remaining elements are all deleted files + ucx_map_cstr_put(lclres, local_res->path, local_res); + ucx_map_cstr_remove(db->resources, local_res->path); // TODO: element leaked } } ucx_list_free(resources); // delete all removed files - UcxMapIterator i = ucx_map_iterator(db->remove); + UcxMapIterator i = ucx_map_iterator(db->resources); LocalResource *local; UCX_MAP_FOREACH(key, local, i) { + // TODO: save deletion: check for remote changes + DavResource *res = dav_resource_new(sn, local->path); printf("delete: %s\n", res->path); if(dav_delete(res)) { @@ -452,6 +466,8 @@ // TODO: free local resource ucx_map_remove(db->remove, key); } + ucx_map_free(db->resources); + db->resources = lclres; // TODO: free res @@ -472,7 +488,6 @@ while(stack) { // get a directory path from the stack and read all entries // if an entry is a directory, put it on the stack - // otherwise compare the metadata with the db content char *p = stack->data; stack = ucx_list_remove(stack, stack); @@ -490,7 +505,7 @@ char *new_path = util_concat_path(p, ent->d_name); int isdir; - LocalResource *res = path_to_local_resource(dir, db, new_path, &isdir); + LocalResource *res = local_resource_new(dir, db, new_path, &isdir); if(isdir) { stack = ucx_list_prepend(stack, new_path); } else if(res) { @@ -540,7 +555,7 @@ if(!sstrcmp(name, S("put"))) { int isdir; - LocalResource *res = path_to_local_resource(dir, db, value.ptr, &isdir); + LocalResource *res = local_resource_new(dir, db, value.ptr, &isdir); if(res) { resources = ucx_list_append(resources, res); } @@ -562,8 +577,7 @@ return resources; } -LocalResource* path_to_local_resource(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir) { - +LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir) { char *file_path = util_concat_path(dir->path, path); struct stat s; if(stat(file_path, &s)) { @@ -575,38 +589,34 @@ if(!S_ISDIR(s.st_mode)) { *isdir = 0; - LocalResource *res = ucx_map_cstr_get(db->resources, path); - if(res) { - // the file is already in the database - // compare length and lastmodified date - - if(res->last_modified == s.st_mtime - && res->size == s.st_size) - { - // file unchanged - return NULL; - } else { - // update db entries - res->size = s.st_size; - res->last_modified = s.st_mtime; - - return res; - } - } else { - LocalResource *res = calloc(1, sizeof(LocalResource)); - res->path = strdup(path); - res->etag = NULL; - res->last_modified = s.st_mtime; - res->size = s.st_size; - return res; - } + LocalResource *res = calloc(1, sizeof(LocalResource)); + res->path = strdup(path); + res->etag = NULL; + res->last_modified = s.st_mtime; + res->size = s.st_size; + return res; } else { *isdir = 1; } return NULL; } -int sync_put_resource(SyncDirectory *dir, DavResource *res, SyncDatabase *db) { +int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res) { + LocalResource *db_res = ucx_map_cstr_get(db->resources, res->path); + if(db_res) { + if(db_res->etag) { + res->etag = strdup(db_res->etag); + } + + if(db_res->last_modified == res->last_modified && db_res->size == res->size) { + return 0; + } + } + return 1; +} + + +int sync_put_resource(SyncDirectory *dir, DavResource *res, LocalResource *local) { char *local_path = util_concat_path(dir->path, res->path); FILE *in = fopen(local_path, "r"); if(!in) { @@ -630,12 +640,8 @@ break; } - if(ret == 0) { - LocalResource *local_res = ucx_map_cstr_get(db->resources, res->path); - if(local_res->etag) { - free(local_res->etag); - } - + if(ret == 0) { + // get new etag DavResource *up_res = dav_get(res->session, res->path, "D:getetag"); char *etag = dav_get_property(up_res, "D:getetag"); if(etag) { @@ -644,17 +650,21 @@ } } + if(local->etag) { + free(local->etag); + } if(etag) { - local_res->etag = strdup(etag); + local->etag = strdup(etag); } else { - local_res->etag = NULL; + local->etag = NULL; } + dav_resource_free(up_res); } fclose(in); - return 0; + return ret; } diff -r ee9da935645d -r 112dbf7ba8b0 dav/sync.h --- a/dav/sync.h Mon Nov 03 15:44:17 2014 +0100 +++ b/dav/sync.h Sat Nov 08 20:27:10 2014 +0100 @@ -52,9 +52,11 @@ void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path); UcxList* local_scan(SyncDirectory *dir, SyncDatabase *db); UcxList* read_changes(SyncDirectory *dir, SyncDatabase *db); -LocalResource* path_to_local_resource(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir); +LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir); +int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res); +void local_resource_update_etag(LocalResource *local_res, DavResource *dav_res); -int sync_put_resource(SyncDirectory *dir, DavResource *res, SyncDatabase *db); +int sync_put_resource(SyncDirectory *dir, DavResource *res, LocalResource *local); #ifdef __cplusplus