| | @@ -65,12 +65,12 @@ |
| 65 | 65 | Blob *pOut; /* Compose our reply here */ |
| 66 | 66 | Blob line; /* The current line of input */ |
| 67 | 67 | Blob aToken[5]; /* Tokenized version of line */ |
| 68 | 68 | Blob err; /* Error message text */ |
| 69 | 69 | int nToken; /* Number of tokens in line */ |
| 70 | | - int nIGotSent; /* Number of "igot" messages sent */ |
| 71 | | - int nGimmeSent; /* Number of gimme messages sent */ |
| 70 | + int nIGotSent; /* Number of "igot" cards sent */ |
| 71 | + int nGimmeSent; /* Number of gimme cards sent */ |
| 72 | 72 | int nFileSent; /* Number of files sent */ |
| 73 | 73 | int nDeltaSent; /* Number of deltas sent */ |
| 74 | 74 | int nFileRcvd; /* Number of files received */ |
| 75 | 75 | int nDeltaRcvd; /* Number of deltas received */ |
| 76 | 76 | int nDanglingFile; /* Number of dangling deltas received */ |
| | @@ -170,15 +170,16 @@ |
| 170 | 170 | } |
| 171 | 171 | sha1sum_blob(&content, &hash); |
| 172 | 172 | if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){ |
| 173 | 173 | blob_appendf(&pXfer->err, "content does not match sha1 hash"); |
| 174 | 174 | } |
| 175 | + rid = content_put(&content, blob_str(&hash), 0); |
| 175 | 176 | blob_reset(&hash); |
| 176 | | - rid = content_put(&content, 0, 0); |
| 177 | 177 | if( rid==0 ){ |
| 178 | 178 | blob_appendf(&pXfer->err, "%s", g.zErrMsg); |
| 179 | 179 | }else{ |
| 180 | + /* db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); */ |
| 180 | 181 | manifest_crosslink(rid, &content); |
| 181 | 182 | } |
| 182 | 183 | remote_has(rid); |
| 183 | 184 | } |
| 184 | 185 | |
| | @@ -460,11 +461,11 @@ |
| 460 | 461 | blob_reset(&cluster); |
| 461 | 462 | } |
| 462 | 463 | |
| 463 | 464 | /* |
| 464 | 465 | ** Send an igot message for every entry in unclustered table. |
| 465 | | -** Return the number of messages sent. |
| 466 | +** Return the number of cards sent. |
| 466 | 467 | */ |
| 467 | 468 | static int send_unclustered(Xfer *pXfer){ |
| 468 | 469 | Stmt q; |
| 469 | 470 | int cnt = 0; |
| 470 | 471 | db_prepare(&q, |
| | @@ -476,10 +477,22 @@ |
| 476 | 477 | cnt++; |
| 477 | 478 | } |
| 478 | 479 | db_finalize(&q); |
| 479 | 480 | return cnt; |
| 480 | 481 | } |
| 482 | + |
| 483 | +/* |
| 484 | +** Send an igot message for every artifact. |
| 485 | +*/ |
| 486 | +static void send_all(Xfer *pXfer){ |
| 487 | + Stmt q; |
| 488 | + db_prepare(&q, "SELECT uuid FROM blob"); |
| 489 | + while( db_step(&q)==SQLITE_ROW ){ |
| 490 | + blob_appendf(pXfer->pOut, "igot %s\n", db_column_text(&q, 0)); |
| 491 | + } |
| 492 | + db_finalize(&q); |
| 493 | +} |
| 481 | 494 | |
| 482 | 495 | /* |
| 483 | 496 | ** If this variable is set, disable login checks. Used for debugging |
| 484 | 497 | ** only. |
| 485 | 498 | */ |
| | @@ -496,10 +509,12 @@ |
| 496 | 509 | int isPull = 0; |
| 497 | 510 | int isPush = 0; |
| 498 | 511 | int nErr = 0; |
| 499 | 512 | Xfer xfer; |
| 500 | 513 | int deltaFlag = 0; |
| 514 | + int isClone = 0; |
| 515 | + int nGimme = 0; |
| 501 | 516 | |
| 502 | 517 | memset(&xfer, 0, sizeof(xfer)); |
| 503 | 518 | blobarray_zero(xfer.aToken, count(xfer.aToken)); |
| 504 | 519 | cgi_set_content_type(g.zContentType); |
| 505 | 520 | blob_zero(&xfer.err); |
| | @@ -541,10 +556,11 @@ |
| 541 | 556 | */ |
| 542 | 557 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 543 | 558 | && xfer.nToken==2 |
| 544 | 559 | && blob_is_uuid(&xfer.aToken[1]) |
| 545 | 560 | ){ |
| 561 | + nGimme++; |
| 546 | 562 | if( isPull ){ |
| 547 | 563 | int rid = rid_from_uuid(&xfer.aToken[1], 0); |
| 548 | 564 | if( rid ){ |
| 549 | 565 | send_file(&xfer, rid, &xfer.aToken[1], deltaFlag); |
| 550 | 566 | } |
| | @@ -634,10 +650,11 @@ |
| 634 | 650 | cgi_reset_content(); |
| 635 | 651 | @ error not\sauthorized\sto\sclone |
| 636 | 652 | nErr++; |
| 637 | 653 | break; |
| 638 | 654 | } |
| 655 | + isClone = 1; |
| 639 | 656 | isPull = 1; |
| 640 | 657 | deltaFlag = 1; |
| 641 | 658 | @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x")) |
| 642 | 659 | }else |
| 643 | 660 | |
| | @@ -698,11 +715,20 @@ |
| 698 | 715 | blobarray_reset(xfer.aToken, xfer.nToken); |
| 699 | 716 | } |
| 700 | 717 | if( isPush ){ |
| 701 | 718 | request_phantoms(&xfer, 500); |
| 702 | 719 | } |
| 703 | | - if( isPull ){ |
| 720 | + if( isClone && nGimme==0 ){ |
| 721 | + /* The initial "clone" message from client to server contains no |
| 722 | + ** "gimme" cards. On that initial message, send the client an "igot" |
| 723 | + ** card for every artifact currently in the respository. This will |
| 724 | + ** cause the client to create phantoms for all artifacts, which will |
| 725 | + ** in turn make sure that the entire repository is sent efficiently |
| 726 | + ** and expeditiously. |
| 727 | + */ |
| 728 | + send_all(&xfer); |
| 729 | + }else if( isPull ){ |
| 704 | 730 | create_cluster(); |
| 705 | 731 | send_unclustered(&xfer); |
| 706 | 732 | } |
| 707 | 733 | db_end_transaction(0); |
| 708 | 734 | } |
| | @@ -738,10 +764,16 @@ |
| 738 | 764 | disableLogin = 1; |
| 739 | 765 | page_xfer(); |
| 740 | 766 | printf("%s\n", cgi_extract_content(¬Used)); |
| 741 | 767 | } |
| 742 | 768 | |
| 769 | +/* |
| 770 | +** Format strings for progress reporting. |
| 771 | +*/ |
| 772 | +static const char zLabel[] = "%-10s %10s %10s %10s %10s %10s\n"; |
| 773 | +static const char zValue[] = "\r%-10s %10d %10d %10d %10d %10d\n"; |
| 774 | + |
| 743 | 775 | |
| 744 | 776 | /* |
| 745 | 777 | ** Sync to the host identified in g.urlName and g.urlPath. This |
| 746 | 778 | ** routine is called by the client. |
| 747 | 779 | ** |
| | @@ -751,11 +783,11 @@ |
| 751 | 783 | */ |
| 752 | 784 | void client_sync(int pushFlag, int pullFlag, int cloneFlag){ |
| 753 | 785 | int go = 1; /* Loop until zero */ |
| 754 | 786 | const char *zSCode = db_get("server-code", "x"); |
| 755 | 787 | const char *zPCode = db_get("project-code", 0); |
| 756 | | - int nMsg = 0; /* Number of messages sent or received */ |
| 788 | + int nCard = 0; /* Number of cards sent or received */ |
| 757 | 789 | int nCycle = 0; /* Number of round trips to the server */ |
| 758 | 790 | int nFileSend = 0; |
| 759 | 791 | int nFileRecv; /* Number of files received */ |
| 760 | 792 | int mxPhantomReq = 200; /* Max number of phantoms to request per comm */ |
| 761 | 793 | const char *zCookie; /* Server cookie */ |
| | @@ -786,21 +818,21 @@ |
| 786 | 818 | */ |
| 787 | 819 | if( cloneFlag ){ |
| 788 | 820 | blob_appendf(&send, "clone\n"); |
| 789 | 821 | pushFlag = 0; |
| 790 | 822 | pullFlag = 0; |
| 791 | | - nMsg++; |
| 823 | + nCard++; |
| 792 | 824 | /* TBD: Request all transferable configuration values */ |
| 793 | 825 | }else if( pullFlag ){ |
| 794 | 826 | blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); |
| 795 | | - nMsg++; |
| 827 | + nCard++; |
| 796 | 828 | } |
| 797 | 829 | if( pushFlag ){ |
| 798 | 830 | blob_appendf(&send, "push %s %s\n", zSCode, zPCode); |
| 799 | | - nMsg++; |
| 831 | + nCard++; |
| 800 | 832 | } |
| 801 | | - |
| 833 | + printf(zLabel, "", "Bytes", "Cards", "Artifacts", "Deltas", "Dangling"); |
| 802 | 834 | |
| 803 | 835 | while( go ){ |
| 804 | 836 | int newPhantom = 0; |
| 805 | 837 | |
| 806 | 838 | /* Send make the most recently received cookie. Let the server |
| | @@ -809,54 +841,59 @@ |
| 809 | 841 | zCookie = db_get("cookie", 0); |
| 810 | 842 | if( zCookie ){ |
| 811 | 843 | blob_appendf(&send, "cookie %s\n", zCookie); |
| 812 | 844 | } |
| 813 | 845 | |
| 814 | | - /* Generate gimme messages for phantoms and leaf messages |
| 846 | + /* Generate gimme cards for phantoms and leaf cards |
| 815 | 847 | ** for all leaves. |
| 816 | 848 | */ |
| 817 | 849 | if( pullFlag || cloneFlag ){ |
| 818 | 850 | request_phantoms(&xfer, mxPhantomReq); |
| 819 | 851 | } |
| 820 | 852 | if( pushFlag ){ |
| 821 | 853 | send_unsent(&xfer); |
| 822 | | - nMsg += send_unclustered(&xfer); |
| 854 | + nCard += send_unclustered(&xfer); |
| 823 | 855 | } |
| 824 | 856 | |
| 825 | 857 | /* Exchange messages with the server */ |
| 826 | 858 | nFileSend = xfer.nFileSent + xfer.nDeltaSent; |
| 827 | | - printf("Sent: %10d bytes, %5d messages, %5d files (%d+%d)\n", |
| 828 | | - blob_size(&send), nMsg+xfer.nGimmeSent+xfer.nIGotSent, |
| 859 | + printf(zValue, "Send:", |
| 860 | + blob_size(&send), nCard+xfer.nGimmeSent+xfer.nIGotSent, |
| 861 | + xfer.nFileSent, xfer.nDeltaSent, 0); |
| 862 | +#if 0 |
| 863 | + printf("Sent: %10d bytes, %5d cards, %5d files (%d+%d)\n", |
| 864 | + blob_size(&send), nCard+xfer.nGimmeSent+xfer.nIGotSent, |
| 829 | 865 | nFileSend, xfer.nFileSent, xfer.nDeltaSent); |
| 830 | | - nMsg = 0; |
| 866 | +#endif |
| 867 | + nCard = 0; |
| 831 | 868 | xfer.nFileSent = 0; |
| 832 | 869 | xfer.nDeltaSent = 0; |
| 833 | 870 | xfer.nGimmeSent = 0; |
| 834 | 871 | fflush(stdout); |
| 835 | 872 | http_exchange(&send, &recv); |
| 836 | 873 | blob_reset(&send); |
| 837 | 874 | |
| 838 | 875 | /* Begin constructing the next message (which might never be |
| 839 | | - ** sent) by beginning with the pull or push messages |
| 876 | + ** sent) by beginning with the pull or push cards |
| 840 | 877 | */ |
| 841 | 878 | if( pullFlag ){ |
| 842 | 879 | blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); |
| 843 | | - nMsg++; |
| 880 | + nCard++; |
| 844 | 881 | } |
| 845 | 882 | if( pushFlag ){ |
| 846 | 883 | blob_appendf(&send, "push %s %s\n", zSCode, zPCode); |
| 847 | | - nMsg++; |
| 884 | + nCard++; |
| 848 | 885 | } |
| 849 | 886 | |
| 850 | 887 | /* Process the reply that came back from the server */ |
| 851 | 888 | while( blob_line(&recv, &xfer.line) ){ |
| 852 | 889 | if( blob_buffer(&xfer.line)[0]=='#' ){ |
| 853 | 890 | continue; |
| 854 | 891 | } |
| 855 | 892 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 856 | | - nMsg++; |
| 857 | | - printf("\r%d", nMsg); |
| 893 | + nCard++; |
| 894 | + printf("\r%d", nCard); |
| 858 | 895 | fflush(stdout); |
| 859 | 896 | |
| 860 | 897 | /* file UUID SIZE \n CONTENT |
| 861 | 898 | ** file UUID DELTASRC SIZE \n CONTENT |
| 862 | 899 | ** |
| | @@ -920,11 +957,11 @@ |
| 920 | 957 | if( zPCode==0 ){ |
| 921 | 958 | zPCode = mprintf("%b", &xfer.aToken[2]); |
| 922 | 959 | db_set("project-code", zPCode, 0); |
| 923 | 960 | } |
| 924 | 961 | blob_appendf(&send, "clone\n"); |
| 925 | | - nMsg++; |
| 962 | + nCard++; |
| 926 | 963 | }else |
| 927 | 964 | |
| 928 | 965 | /* config NAME SIZE \n CONTENT |
| 929 | 966 | ** |
| 930 | 967 | ** Receive a configuration value from the server. |
| | @@ -978,15 +1015,19 @@ |
| 978 | 1015 | fossil_fatal("%b", &xfer.err); |
| 979 | 1016 | } |
| 980 | 1017 | blobarray_reset(xfer.aToken, xfer.nToken); |
| 981 | 1018 | blob_reset(&xfer.line); |
| 982 | 1019 | } |
| 983 | | - printf("\rReceived: %10d bytes, %5d messages, %5d files (%d+%d+%d)\n", |
| 984 | | - blob_size(&recv), nMsg, |
| 1020 | + printf(zValue, "Received:", |
| 1021 | + blob_size(&recv), nCard, |
| 1022 | + xfer.nFileRcvd, xfer.nDeltaRcvd, xfer.nDanglingFile); |
| 1023 | +#if 0 |
| 1024 | + printf("\rReceived: %10d bytes, %5d cards, %5d files (%d+%d+%d)\n", |
| 1025 | + blob_size(&recv), nCard, |
| 985 | 1026 | xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile, |
| 986 | 1027 | xfer.nFileRcvd, xfer.nDeltaRcvd, xfer.nDanglingFile); |
| 987 | | - |
| 1028 | +#endif |
| 988 | 1029 | blob_reset(&recv); |
| 989 | 1030 | nCycle++; |
| 990 | 1031 | go = 0; |
| 991 | 1032 | |
| 992 | 1033 | /* If we received one or more files on the previous exchange but |
| | @@ -996,11 +1037,11 @@ |
| 996 | 1037 | if( (nFileRecv>0 || newPhantom) && db_exists("SELECT 1 FROM phantom") ){ |
| 997 | 1038 | go = 1; |
| 998 | 1039 | mxPhantomReq = nFileRecv*2; |
| 999 | 1040 | if( mxPhantomReq<200 ) mxPhantomReq = 200; |
| 1000 | 1041 | } |
| 1001 | | - nMsg = 0; |
| 1042 | + nCard = 0; |
| 1002 | 1043 | xfer.nFileRcvd = 0; |
| 1003 | 1044 | xfer.nDeltaRcvd = 0; |
| 1004 | 1045 | xfer.nDanglingFile = 0; |
| 1005 | 1046 | |
| 1006 | 1047 | /* If we have one or more files queued to send, then go |
| 1007 | 1048 | |