changed sync behavior

Sat, 08 Nov 2014 20:27:10 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 08 Nov 2014 20:27:10 +0100
changeset 64
112dbf7ba8b0
parent 63
ee9da935645d
child 65
d4077e8175f3

changed sync behavior

dav/sync.c file | annotate | diff | comparison | revisions
dav/sync.h file | annotate | diff | comparison | revisions
--- 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;
 }
 
 
--- 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

mercurial