Diff
Not logged in

Differences From:

File src/xfer.c part of check-in [6dab6149b1] - From the vinfo webpage, provide a hyperlink to download a ZIP archive the version. by drh on 2007-08-01 13:32:11. [view]

To:

File src/xfer.c part of check-in [eea381f416] - Progress toward delta compression on the xfer protocol. The compression works well. But the client is not telling the server what files it has so the server does not have anything to delta against. by drh on 2007-08-09 03:19:18. [view]

@@ -26,8 +26,81 @@
 #include "config.h"
 #include "xfer.h"
 
 /*
+** Try to locate a record that is similar to rid and is a likely
+** candidate for delta against rid.  The similar record must be
+** referenced in the onremote table.
+**
+** Return the integer record ID of the similar record.  Or return
+** 0 if none is found.
+*/
+static int similar_record(int rid, int traceFlag){
+  int inCnt, outCnt;
+  Stmt q;
+  int queue[100];
+
+  db_prepare(&q,
+      "SELECT srcid, EXISTS(SELECT 1 FROM onremote WHERE rid=srcid)"
+      "  FROM delta"
+      " WHERE rid=:x"
+      " UNION ALL "
+      "SELECT rid, EXISTS(SELECT 1 FROM onremote WHERE rid=delta.rid)"
+      "  FROM delta"
+      " WHERE srcid=:x"
+  );
+  queue[0] = rid;
+  inCnt = 1;
+  outCnt = 0;
+  while( outCnt<inCnt ){
+    int xid = queue[outCnt%64];
+    outCnt++;
+    db_bind_int(&q, ":x", xid);
+    if( traceFlag ) printf("xid=%d\n", xid);
+    while( db_step(&q)==SQLITE_ROW ){
+      int nid = db_column_int(&q, 0);
+      int hit = db_column_int(&q, 1);
+      if( traceFlag ) printf("nid=%d hit=%d\n", nid, hit);
+      if( hit  ){
+        db_finalize(&q);
+        return nid;
+      }
+      if( inCnt<sizeof(queue)/sizeof(queue[0]) ){
+        int i;
+        for(i=0; i<inCnt && queue[i]!=nid; i++){}
+        if( i>=inCnt ){
+          queue[inCnt++] = nid;
+        }
+      }
+    }
+    db_reset(&q);
+  }
+  db_finalize(&q);
+  return 0;
+}
+
+/*
+** COMMAND: test-similar-record
+*/
+void test_similar_record(void){
+  int i;
+  if( g.argc<4 ){
+    usage("SRC ONREMOTE...");
+  }
+  db_must_be_within_tree();
+  db_multi_exec(
+    "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
+  );
+  for(i=3; i<g.argc; i++){
+    int rid = name_to_rid(g.argv[i]);
+    printf("%s -> %d\n", g.argv[i], rid);
+    db_multi_exec("INSERT INTO onremote VALUES(%d)", rid);
+  }
+  printf("similar: %d\n", similar_record(name_to_rid(g.argv[2]), 1));
+}
+
+
+/*
 ** The aToken[0..nToken-1] blob array is a parse of a "file" line
 ** message.  This routine finishes parsing that message and does
 ** a record insert of the file.
 **
@@ -88,41 +161,48 @@
 */
 static int send_file(int rid, Blob *pOut){
   Blob content, uuid;
   int size;
-
-#if 0
-SELECT srcid FROM delta
- WHERE rid=%d
-   AND EXISTS(SELECT 1 FROM onremote WHERE rid=srcid)
-UNION ALL
-SELECT id FROM delta
- WHERE srcid=%d
-   AND EXISTS(SELECT 1 FROM onremote WHERE rid=delta.rid)
-LIMIT 1
-#endif
-
-  /* TODO:
-  ** Check for related files in the onremote TEMP table.  If related
-  ** files are found, then send a delta rather than the whole file.
-  */
+  int srcid;
+
 
   blob_zero(&uuid);
   db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid);
   if( blob_size(&uuid)==0 ){
     return 0;
   }
   content_get(rid, &content);
-  size = blob_size(&content);
-  if( pOut ){
-    blob_appendf(pOut, "file %b %d\n", &uuid, size);
-    blob_append(pOut, blob_buffer(&content), size);
+
+  srcid = similar_record(rid, 0);
+  if( srcid ){
+    Blob src, delta;
+    Blob srcuuid;
+    content_get(srcid, &src);
+    blob_delta_create(&src, &content, &delta);
+    blob_reset(&src);
+    blob_reset(&content);
+    blob_zero(&srcuuid);
+    db_blob(&srcuuid, "SELECT uuid FROM blob WHERE rid=%d", srcid);
+    size = blob_size(&delta);
+    if( pOut ){
+      blob_appendf(pOut, "file %b %b %d\n", &uuid, &srcuuid, size);
+      blob_append(pOut, blob_buffer(&delta), size);
+    }else{
+      cgi_printf("file %b %b %d\n", &uuid, &srcuuid, size);
+      cgi_append_content(blob_buffer(&delta), size);
+    }
   }else{
-    cgi_printf("file %b %d\n", &uuid, size);
-    cgi_append_content(blob_buffer(&content), size);
-  }
-  blob_reset(&content);
-  blob_reset(&uuid);
+    size = blob_size(&content);
+    if( pOut ){
+      blob_appendf(pOut, "file %b %d\n", &uuid, size);
+      blob_append(pOut, blob_buffer(&content), size);
+    }else{
+      cgi_printf("file %b %d\n", &uuid, size);
+      cgi_append_content(blob_buffer(&content), size);
+    }
+    blob_reset(&content);
+    blob_reset(&uuid);
+  }
   db_multi_exec("INSERT OR IGNORE INTO onremote VALUES(%d)", rid);
   return size;
 }
 
@@ -135,31 +215,9 @@
   int sent = 0;
   int nSent = 0;
   int maxSize = db_get_int("http-msg-size", 500000);
   Stmt q;
-#if 0
-  db_multi_exec(
-    "CREATE TEMP TABLE priority(rid INTEGER PRIMARY KEY);"
-    "INSERT INTO priority"
-    " SELECT srcid FROM delta"
-    "  WHERE EXISTS(SELECT 1 FROM onremote WHERE onremote.rid=delta.rid)"
-    "    AND EXISTS(SELECT 1 FROM pending WHERE delta.srcid=pending.rid);"
-    "INSERT OR IGNORE INTO priority"
-    " SELECT rid FROM delta"
-    "  WHERE EXISTS(SELECT 1 FROM onremote WHERE onremote.rid=delta.srcid)"
-    "    AND EXISTS(SELECT 1 FROM pending WHERE delta.rid=pending.rid);"
-  );
-  while( sent<maxSize && (rid = db_int(0, "SELECT rid FROM priority"))!=0 ){
-    sent += send_file(rid, pOut);
-    db_multi_exec(
-      "INSERT OR IGNORE INTO priority"
-      " SELECT srcid FROM delta WHERE rid=%d"
-      " UNION ALL"
-      " SELECT rid FROM delta WHERE srcid=%d",
-      rid, rid
-    );
-  }
-#endif
+
   db_prepare(&q, "SELECT rid FROM pending ORDER BY rid");
   while( db_step(&q)==SQLITE_ROW ){
     int rid = db_column_int(&q, 0);
     if( sent<maxSize ){
@@ -187,11 +245,8 @@
   if( nSent>0 ){
     db_multi_exec("DELETE FROM pending WHERE rid <= %d", iRidSent);
   }
 
-#if 0
-  db_multi_exec("DROP TABLE priority");
-#endif
   return nSent;
 }
 
 
@@ -593,10 +648,10 @@
       db_finalize(&q);
     }
 
     /* Exchange messages with the server */
-    printf("Send:      %d files, %d requests, %d other messages\n",
-            nFile, nReq, nMsg);
+    printf("Send:      %3d files, %3d requests, %3d other msgs, %8d bytes\n",
+            nFile, nReq, nMsg, blob_size(&send));
     nFileSend = nFile;
     nFile = nReq = nMsg = 0;
     http_exchange(&send, &recv);
     blob_reset(&send);
@@ -705,11 +760,11 @@
         fossil_fatal("%b", &errmsg);
       }
       blobarray_reset(aToken, nToken);
     }
-    blob_reset(&recv);
-    printf("Received:  %d files, %d requests, %d other messages\n",
-            nFile, nReq, nMsg);
+    printf("Received:  %3d files, %3d requests, %3d other msgs, %8d bytes\n",
+            nFile, nReq, nMsg, blob_size(&recv));
+    blob_reset(&recv);
     if( nFileSend + nFile==0 ){
       nNoFileCycle++;
       if( nNoFileCycle>1 ){
         go = 0;