Fossil

Check-in [75c476cc]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Work on network synchronization
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:75c476ccd178dca0d970b2c5e6718c6eacaf149e
User & Date: drh 2007-07-23 20:33:04
Context
2007-07-23
20:40
More improvements to network sync. check-in: 4ee118a6 user: drh tags: trunk
20:33
Work on network synchronization check-in: 75c476cc user: drh tags: trunk
19:52
Improvements to the WWW interface. check-in: 66f4caa3 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/blob.c.

207
208
209
210
211
212
213




214
215
216
217
218
219
220
}

/*
** Return a pointer to a null-terminated string for a blob.
*/
char *blob_str(Blob *p){
  blob_is_init(p);




  if( p->aData[p->nUsed]!=0 ){
    blob_materialize(p);
  }
  return p->aData;
}

/*







>
>
>
>







207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
}

/*
** Return a pointer to a null-terminated string for a blob.
*/
char *blob_str(Blob *p){
  blob_is_init(p);
  if( p->nUsed==0 ){
    blob_append(p, "", 1);
    p->nUsed = 0;
  }
  if( p->aData[p->nUsed]!=0 ){
    blob_materialize(p);
  }
  return p->aData;
}

/*

Changes to src/content.c.

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  }

  if( rid>0 ){
    /* We are just adding data to a phantom */
    assert( pBlob!=0 );
    db_prepare(&s1,
      "UPDATE blob SET rcvid=%d, size=%d, content=:data WHERE rid=%d",
       g.rcvid, size, blob_str(&hash)
    );
    blob_compress(pBlob, &cmpr);
    db_bind_blob(&s1, ":data", &cmpr);
    db_exec(&s1);
  }else{
    /* We are creating a new entry */
    db_prepare(&s1,







|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  }

  if( rid>0 ){
    /* We are just adding data to a phantom */
    assert( pBlob!=0 );
    db_prepare(&s1,
      "UPDATE blob SET rcvid=%d, size=%d, content=:data WHERE rid=%d",
       g.rcvid, size, rid
    );
    blob_compress(pBlob, &cmpr);
    db_bind_blob(&s1, ":data", &cmpr);
    db_exec(&s1);
  }else{
    /* We are creating a new entry */
    db_prepare(&s1,

Changes to src/verify.c.

40
41
42
43
44
45
46
47
48

49

50
51
52
53
54
55
56
  blob_zero(&uuid);
  db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( blob_size(&uuid)!=UUID_SIZE ){
    fossil_panic("not a valid rid: %d", rid);
  }
  content_get(rid, &content);
  sha1sum_blob(&content, &hash);
  blob_reset(&content);
  if( blob_compare(&uuid, &hash) ){

    fossil_panic("hash of rid %d does not match its uuid", rid);

  }
  blob_reset(&uuid);
  blob_reset(&hash);
}

/*
**  







|

>
|
>







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  blob_zero(&uuid);
  db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( blob_size(&uuid)!=UUID_SIZE ){
    fossil_panic("not a valid rid: %d", rid);
  }
  content_get(rid, &content);
  sha1sum_blob(&content, &hash);
/*  blob_reset(&content); */
  if( blob_compare(&uuid, &hash) ){
printf("content=[%s]\n", blob_str(&content));
    fossil_panic("hash of rid %d (%b) does not match its uuid (%b)",
                  rid, &hash, &uuid);
  }
  blob_reset(&uuid);
  blob_reset(&hash);
}

/*
**  

Changes to src/xfer.c.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
...
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
...
158
159
160
161
162
163
164

165
166
167
168
169
170
171
...
176
177
178
179
180
181
182

183
184
185
186
187
188
189
...
478
479
480
481
482
483
484



485
486
487
488
489
490
491
...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
...
549
550
551
552
553
554
555

556
557
558
559
560
561
562
...
563
564
565
566
567
568
569

570
571
572
573
574
575
576
...
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
...
651
652
653
654
655
656
657


658
659
660
661
662
663
664
665
      return;
    }
    content_get(srcid, &src);
    blob_delta_apply(&src, &content, &content);
    blob_reset(&src);
  }
  sha1sum_blob(&content, &hash);
  if( !blob_eq_str(&aToken[1], blob_str(&content), -1) ){
    blob_appendf(pErr, "content does not match sha1 hash");
  }
  blob_reset(&hash);
  rid = content_put(&content, 0);
  manifest_crosslink(rid, &content);
  if( rid==0 ){
    blob_appendf(pErr, "%s", g.zErrMsg);
................................................................................
  return size;
}


/*
** Send all pending files.
*/
static void send_all_pending(Blob *pOut){
  int sent = 0;

  int maxSize = db_get_int("http-msg-size", 1000000);
  Stmt q;
#if 0
  db_multi_exec(
    "CREATE TEMP TABLE priority(rid INTEGER PRIMARY KEY);"
    "INSERT INTO priority"
    " SELECT srcid FROM delta"
................................................................................
  }
#endif
  db_prepare(&q, "SELECT rid FROM pending");
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    if( sent<maxSize ){
      sent += send_file(rid, pOut);

    }else{
      char *zUuid = db_text(0,
                      "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid);
      if( zUuid ){
        if( pOut ){
          blob_appendf(pOut, "igot %s\n", zUuid);
        }else{
................................................................................
    }
  }
  db_finalize(&q);
  
#if 0
  db_multi_exec("DROP TABLE priority");
#endif

}


/*
** Check the signature on an application/x-fossil payload received by
** the HTTP server.  The signature is a line of the following form:
**
................................................................................
** true.
*/
void client_sync(int pushFlag, int pullFlag, int cloneFlag){
  int go = 1;        /* Loop until zero */
  int nToken;
  const char *zSCode = db_get("server-code", "x");
  const char *zPCode = db_get("project-code", 0);



  Blob send;        /* Text we are sending to the server */
  Blob recv;        /* Reply we got back from the server */
  Blob line;        /* A single line of the reply */
  Blob aToken[5];   /* A tokenization of line */
  Blob errmsg;      /* Error message */

  assert( pushFlag || pullFlag || cloneFlag );
................................................................................
        blob_appendf(&send,"gimme %s\n", zUuid);
      }
      db_finalize(&q);
    }

    if( pushFlag ){
      /* Send the server any files that the server has requested */
      send_all_pending(&send);
    }

    if( pullFlag || pushFlag ){
      /* Always send our leaves */
      Stmt q;
      db_prepare(&q, 
         "SELECT uuid FROM blob WHERE rid IN"
................................................................................
        const char *zUuid = db_column_text(&q, 0);
        blob_appendf(&send, "leaf %s\n", zUuid);
      }
      db_finalize(&q);
    }

    /* Exchange messages with the server */

    http_exchange(&send, &recv);
    blob_reset(&send);

    /* Process the reply that came back from the server */
    while( blob_line(&recv, &line) ){
      nToken = blob_tokenize(&line, aToken, count(aToken));

................................................................................
      /*   file UUID SIZE \n CONTENT
      **   file UUID DELTASRC SIZE \n CONTENT
      **
      ** Receive a file transmitted from the other side
      */
      if( blob_eq(&aToken[0],"file") ){
        xfer_accept_file(&recv, aToken, nToken, &errmsg);

      }else

      /*   gimme UUID
      **
      ** Server is requesting a file
      */
      if( blob_eq(&aToken[0], "gimme") && nToken==2
................................................................................
        }
      }else
  
      /*   push  SERVERCODE  PRODUCTCODE
      **
      ** Should only happen in response to a clone.
      */
      if( blob_eq(&aToken[0],"push") && nToken==2 && cloneFlag
              && blob_is_uuid(&aToken[1]) && blob_is_uuid(&aToken[2]) ){

        if( blob_eq_str(&aToken[1], zSCode, -1) ){
          fossil_fatal("server loop");
        }
        if( zPCode==0 ){
          zPCode = mprintf("%b", &aToken[2]);
          db_set("product-code", zPCode);
        }
        cloneFlag = 0;
        pullFlag = 1;
      }else

      /*   error MESSAGE
      **
................................................................................

      if( blob_size(&errmsg) ){
        fossil_fatal("%b", &errmsg);
      }
      blobarray_reset(aToken, nToken);
    }
    blob_reset(&recv);


  };
  http_close();
  db_end_transaction(0);
  db_multi_exec(
    "DROP TABLE onremote;"
    "DROP TABLE pending;"
  );
}







|







 







|

>







 







>







 







>







 







>
>
>







 







|







 







>







 







>







 







|







|







 







>
>








65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
...
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
...
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
...
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
      return;
    }
    content_get(srcid, &src);
    blob_delta_apply(&src, &content, &content);
    blob_reset(&src);
  }
  sha1sum_blob(&content, &hash);
  if( !blob_eq_str(&aToken[1], blob_str(&hash), -1) ){
    blob_appendf(pErr, "content does not match sha1 hash");
  }
  blob_reset(&hash);
  rid = content_put(&content, 0);
  manifest_crosslink(rid, &content);
  if( rid==0 ){
    blob_appendf(pErr, "%s", g.zErrMsg);
................................................................................
  return size;
}


/*
** Send all pending files.
*/
static int send_all_pending(Blob *pOut){
  int sent = 0;
  int nSent = 0;
  int maxSize = db_get_int("http-msg-size", 1000000);
  Stmt q;
#if 0
  db_multi_exec(
    "CREATE TEMP TABLE priority(rid INTEGER PRIMARY KEY);"
    "INSERT INTO priority"
    " SELECT srcid FROM delta"
................................................................................
  }
#endif
  db_prepare(&q, "SELECT rid FROM pending");
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    if( sent<maxSize ){
      sent += send_file(rid, pOut);
      nSent++;
    }else{
      char *zUuid = db_text(0,
                      "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid);
      if( zUuid ){
        if( pOut ){
          blob_appendf(pOut, "igot %s\n", zUuid);
        }else{
................................................................................
    }
  }
  db_finalize(&q);
  
#if 0
  db_multi_exec("DROP TABLE priority");
#endif
  return nSent;
}


/*
** Check the signature on an application/x-fossil payload received by
** the HTTP server.  The signature is a line of the following form:
**
................................................................................
** true.
*/
void client_sync(int pushFlag, int pullFlag, int cloneFlag){
  int go = 1;        /* Loop until zero */
  int nToken;
  const char *zSCode = db_get("server-code", "x");
  const char *zPCode = db_get("project-code", 0);
  int nSent = 0;
  int nRcvd = 0;
  int nCycle = 0;
  Blob send;        /* Text we are sending to the server */
  Blob recv;        /* Reply we got back from the server */
  Blob line;        /* A single line of the reply */
  Blob aToken[5];   /* A tokenization of line */
  Blob errmsg;      /* Error message */

  assert( pushFlag || pullFlag || cloneFlag );
................................................................................
        blob_appendf(&send,"gimme %s\n", zUuid);
      }
      db_finalize(&q);
    }

    if( pushFlag ){
      /* Send the server any files that the server has requested */
      nSent += send_all_pending(&send);
    }

    if( pullFlag || pushFlag ){
      /* Always send our leaves */
      Stmt q;
      db_prepare(&q, 
         "SELECT uuid FROM blob WHERE rid IN"
................................................................................
        const char *zUuid = db_column_text(&q, 0);
        blob_appendf(&send, "leaf %s\n", zUuid);
      }
      db_finalize(&q);
    }

    /* Exchange messages with the server */
    printf("Sending %d files to server\n", nSent);
    http_exchange(&send, &recv);
    blob_reset(&send);

    /* Process the reply that came back from the server */
    while( blob_line(&recv, &line) ){
      nToken = blob_tokenize(&line, aToken, count(aToken));

................................................................................
      /*   file UUID SIZE \n CONTENT
      **   file UUID DELTASRC SIZE \n CONTENT
      **
      ** Receive a file transmitted from the other side
      */
      if( blob_eq(&aToken[0],"file") ){
        xfer_accept_file(&recv, aToken, nToken, &errmsg);
        nRcvd++;
      }else

      /*   gimme UUID
      **
      ** Server is requesting a file
      */
      if( blob_eq(&aToken[0], "gimme") && nToken==2
................................................................................
        }
      }else
  
      /*   push  SERVERCODE  PRODUCTCODE
      **
      ** Should only happen in response to a clone.
      */
      if( blob_eq(&aToken[0],"push") && nToken==3 && cloneFlag
              && blob_is_uuid(&aToken[1]) && blob_is_uuid(&aToken[2]) ){

        if( blob_eq_str(&aToken[1], zSCode, -1) ){
          fossil_fatal("server loop");
        }
        if( zPCode==0 ){
          zPCode = mprintf("%b", &aToken[2]);
          db_set("project-code", zPCode);
        }
        cloneFlag = 0;
        pullFlag = 1;
      }else

      /*   error MESSAGE
      **
................................................................................

      if( blob_size(&errmsg) ){
        fossil_fatal("%b", &errmsg);
      }
      blobarray_reset(aToken, nToken);
    }
    blob_reset(&recv);
    printf("Received %d files from server\n", nRcvd);
    nSent = nRcvd = 0;
  };
  http_close();
  db_end_transaction(0);
  db_multi_exec(
    "DROP TABLE onremote;"
    "DROP TABLE pending;"
  );
}