| | @@ -1266,11 +1266,23 @@ |
| 1266 | 1266 | /* |
| 1267 | 1267 | ** Format strings for progress reporting. |
| 1268 | 1268 | */ |
| 1269 | 1269 | static const char zLabelFormat[] = "%-10s %10s %10s %10s %10s\n"; |
| 1270 | 1270 | static const char zValueFormat[] = "\r%-10s %10d %10d %10d %10d\n"; |
| 1271 | +static const char zBriefFormat[] = |
| 1272 | + "Round-trips: %d Artifacts sent: %d received: %d\r"; |
| 1271 | 1273 | |
| 1274 | +#if INTERFACE |
| 1275 | +/* |
| 1276 | +** Flag options for controlling client_sync() |
| 1277 | +*/ |
| 1278 | +#define SYNC_PUSH 0x0001 |
| 1279 | +#define SYNC_PULL 0x0002 |
| 1280 | +#define SYNC_CLONE 0x0004 |
| 1281 | +#define SYNC_PRIVATE 0x0008 |
| 1282 | +#define SYNC_VERBOSE 0x0010 |
| 1283 | +#endif |
| 1272 | 1284 | |
| 1273 | 1285 | /* |
| 1274 | 1286 | ** Sync to the host identified in g.urlName and g.urlPath. This |
| 1275 | 1287 | ** routine is called by the client. |
| 1276 | 1288 | ** |
| | @@ -1277,16 +1289,13 @@ |
| 1277 | 1289 | ** Records are pushed to the server if pushFlag is true. Records |
| 1278 | 1290 | ** are pulled if pullFlag is true. A full sync occurs if both are |
| 1279 | 1291 | ** true. |
| 1280 | 1292 | */ |
| 1281 | 1293 | int client_sync( |
| 1282 | | - int pushFlag, /* True to do a push (or a sync) */ |
| 1283 | | - int pullFlag, /* True to do a pull (or a sync) */ |
| 1284 | | - int cloneFlag, /* True if this is a clone */ |
| 1285 | | - int privateFlag, /* True to exchange private branches */ |
| 1286 | | - int configRcvMask, /* Receive these configuration items */ |
| 1287 | | - int configSendMask /* Send these configuration items */ |
| 1294 | + unsigned syncFlags, /* Mask of SYNC_* flags */ |
| 1295 | + unsigned configRcvMask, /* Receive these configuration items */ |
| 1296 | + unsigned configSendMask /* Send these configuration items */ |
| 1288 | 1297 | ){ |
| 1289 | 1298 | int go = 1; /* Loop until zero */ |
| 1290 | 1299 | int nCardSent = 0; /* Number of cards sent */ |
| 1291 | 1300 | int nCardRcvd = 0; /* Number of cards received */ |
| 1292 | 1301 | int nCycle = 0; /* Number of round trips to the server */ |
| | @@ -1304,27 +1313,30 @@ |
| 1304 | 1313 | int lastPctDone = -1; /* Last displayed pctDone */ |
| 1305 | 1314 | double rArrivalTime; /* Time at which a message arrived */ |
| 1306 | 1315 | const char *zSCode = db_get("server-code", "x"); |
| 1307 | 1316 | const char *zPCode = db_get("project-code", 0); |
| 1308 | 1317 | int nErr = 0; /* Number of errors */ |
| 1318 | + int nRoundtrip= 0; /* Number of HTTP requests */ |
| 1319 | + int nArtifactSent = 0; /* Total artifacts sent */ |
| 1320 | + int nArtifactRcvd = 0; /* Total artifacts received */ |
| 1321 | + const char *zOpType = 0;/* Push, Pull, Sync, Clone */ |
| 1309 | 1322 | |
| 1310 | | - if( db_get_boolean("dont-push", 0) ) pushFlag = 0; |
| 1311 | | - if( pushFlag + pullFlag + cloneFlag == 0 |
| 1323 | + if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH; |
| 1324 | + if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0 |
| 1312 | 1325 | && configRcvMask==0 && configSendMask==0 ) return 0; |
| 1313 | 1326 | |
| 1314 | 1327 | transport_stats(0, 0, 1); |
| 1315 | 1328 | socket_global_init(); |
| 1316 | 1329 | memset(&xfer, 0, sizeof(xfer)); |
| 1317 | 1330 | xfer.pIn = &recv; |
| 1318 | 1331 | xfer.pOut = &send; |
| 1319 | 1332 | xfer.mxSend = db_get_int("max-upload", 250000); |
| 1320 | | - if( privateFlag ){ |
| 1333 | + if( syncFlags & SYNC_PRIVATE ){ |
| 1321 | 1334 | g.perm.Private = 1; |
| 1322 | 1335 | xfer.syncPrivate = 1; |
| 1323 | 1336 | } |
| 1324 | 1337 | |
| 1325 | | - assert( pushFlag | pullFlag | cloneFlag | configRcvMask | configSendMask ); |
| 1326 | 1338 | db_begin_transaction(); |
| 1327 | 1339 | db_record_repository_filename(0); |
| 1328 | 1340 | db_multi_exec( |
| 1329 | 1341 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1330 | 1342 | ); |
| | @@ -1335,33 +1347,39 @@ |
| 1335 | 1347 | blob_zero(&xfer.line); |
| 1336 | 1348 | origConfigRcvMask = 0; |
| 1337 | 1349 | |
| 1338 | 1350 | |
| 1339 | 1351 | /* Send the send-private pragma if we are trying to sync private data */ |
| 1340 | | - if( privateFlag ) blob_append(&send, "pragma send-private\n", -1); |
| 1352 | + if( syncFlags & SYNC_PRIVATE ){ |
| 1353 | + blob_append(&send, "pragma send-private\n", -1); |
| 1354 | + } |
| 1341 | 1355 | |
| 1342 | 1356 | /* |
| 1343 | 1357 | ** Always begin with a clone, pull, or push message |
| 1344 | 1358 | */ |
| 1345 | | - if( cloneFlag ){ |
| 1359 | + if( syncFlags & SYNC_CLONE ){ |
| 1346 | 1360 | blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 1347 | | - pushFlag = 0; |
| 1348 | | - pullFlag = 0; |
| 1361 | + syncFlags &= ~(SYNC_PUSH|SYNC_PULL); |
| 1349 | 1362 | nCardSent++; |
| 1350 | 1363 | /* TBD: Request all transferable configuration values */ |
| 1351 | 1364 | content_enable_dephantomize(0); |
| 1352 | | - }else if( pullFlag ){ |
| 1365 | + zOpType = "Clone"; |
| 1366 | + }else if( syncFlags & SYNC_PULL ){ |
| 1353 | 1367 | blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); |
| 1354 | 1368 | nCardSent++; |
| 1369 | + zOpType = "Pull"; |
| 1355 | 1370 | } |
| 1356 | | - if( pushFlag ){ |
| 1371 | + if( syncFlags & SYNC_PUSH ){ |
| 1357 | 1372 | blob_appendf(&send, "push %s %s\n", zSCode, zPCode); |
| 1358 | 1373 | nCardSent++; |
| 1374 | + if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push"; |
| 1359 | 1375 | } |
| 1360 | 1376 | manifest_crosslink_begin(); |
| 1361 | 1377 | transport_global_startup(); |
| 1362 | | - fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas"); |
| 1378 | + if( syncFlags & SYNC_VERBOSE ){ |
| 1379 | + fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas"); |
| 1380 | + } |
| 1363 | 1381 | |
| 1364 | 1382 | while( go ){ |
| 1365 | 1383 | int newPhantom = 0; |
| 1366 | 1384 | char *zRandomness; |
| 1367 | 1385 | |
| | @@ -1374,25 +1392,28 @@ |
| 1374 | 1392 | } |
| 1375 | 1393 | |
| 1376 | 1394 | /* Generate gimme cards for phantoms and leaf cards |
| 1377 | 1395 | ** for all leaves. |
| 1378 | 1396 | */ |
| 1379 | | - if( pullFlag || (cloneFlag && cloneSeqno==1) ){ |
| 1397 | + if( (syncFlags & SYNC_PULL)!=0 |
| 1398 | + || ((syncFlags & SYNC_CLONE)!=0 && cloneSeqno==1) |
| 1399 | + ){ |
| 1380 | 1400 | request_phantoms(&xfer, mxPhantomReq); |
| 1381 | 1401 | } |
| 1382 | | - if( pushFlag ){ |
| 1402 | + if( syncFlags & SYNC_PUSH ){ |
| 1383 | 1403 | send_unsent(&xfer); |
| 1384 | 1404 | nCardSent += send_unclustered(&xfer); |
| 1385 | | - if( privateFlag ) send_private(&xfer); |
| 1405 | + if( syncFlags & SYNC_PRIVATE ) send_private(&xfer); |
| 1386 | 1406 | } |
| 1387 | 1407 | |
| 1388 | 1408 | /* Send configuration parameter requests. On a clone, delay sending |
| 1389 | 1409 | ** this until the second cycle since the login card might fail on |
| 1390 | 1410 | ** the first cycle. |
| 1391 | 1411 | */ |
| 1392 | | - if( configRcvMask && (cloneFlag==0 || nCycle>0) ){ |
| 1412 | + if( configRcvMask && ((syncFlags & SYNC_CLONE)==0 || nCycle>0) ){ |
| 1393 | 1413 | const char *zName; |
| 1414 | + if( zOpType==0 ) zOpType = "Pull"; |
| 1394 | 1415 | zName = configure_first_name(configRcvMask); |
| 1395 | 1416 | while( zName ){ |
| 1396 | 1417 | blob_appendf(&send, "reqconfig %s\n", zName); |
| 1397 | 1418 | zName = configure_next_name(configRcvMask); |
| 1398 | 1419 | nCardSent++; |
| | @@ -1407,10 +1428,11 @@ |
| 1407 | 1428 | configRcvMask = 0; |
| 1408 | 1429 | } |
| 1409 | 1430 | |
| 1410 | 1431 | /* Send configuration parameters being pushed */ |
| 1411 | 1432 | if( configSendMask ){ |
| 1433 | + if( zOpType==0 ) zOpType = "Push"; |
| 1412 | 1434 | if( configSendMask & CONFIGSET_OLDFORMAT ){ |
| 1413 | 1435 | const char *zName; |
| 1414 | 1436 | zName = configure_first_name(configSendMask); |
| 1415 | 1437 | while( zName ){ |
| 1416 | 1438 | send_legacy_config_card(&xfer, zName); |
| | @@ -1430,42 +1452,50 @@ |
| 1430 | 1452 | zRandomness = db_text(0, "SELECT hex(randomblob(20))"); |
| 1431 | 1453 | blob_appendf(&send, "# %s\n", zRandomness); |
| 1432 | 1454 | free(zRandomness); |
| 1433 | 1455 | |
| 1434 | 1456 | /* Exchange messages with the server */ |
| 1435 | | - fossil_print(zValueFormat, "Sent:", |
| 1436 | | - blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent, |
| 1437 | | - xfer.nFileSent, xfer.nDeltaSent); |
| 1457 | + if( syncFlags & SYNC_VERBOSE ){ |
| 1458 | + fossil_print(zValueFormat, "Sent:", |
| 1459 | + blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent, |
| 1460 | + xfer.nFileSent, xfer.nDeltaSent); |
| 1461 | + }else{ |
| 1462 | + nRoundtrip++; |
| 1463 | + nArtifactSent += xfer.nFileSent + xfer.nDeltaSent; |
| 1464 | + fossil_print(zBriefFormat, nRoundtrip, nArtifactSent, nArtifactRcvd); |
| 1465 | + } |
| 1438 | 1466 | nCardSent = 0; |
| 1439 | 1467 | nCardRcvd = 0; |
| 1440 | 1468 | xfer.nFileSent = 0; |
| 1441 | 1469 | xfer.nDeltaSent = 0; |
| 1442 | 1470 | xfer.nGimmeSent = 0; |
| 1443 | 1471 | xfer.nIGotSent = 0; |
| 1444 | | - if( !g.cgiOutput && !g.fQuiet ){ |
| 1472 | + if( syncFlags & SYNC_VERBOSE ){ |
| 1445 | 1473 | fossil_print("waiting for server..."); |
| 1446 | 1474 | } |
| 1447 | 1475 | fflush(stdout); |
| 1448 | | - if( http_exchange(&send, &recv, cloneFlag==0 || nCycle>0) ){ |
| 1476 | + if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0) ){ |
| 1449 | 1477 | nErr++; |
| 1450 | 1478 | break; |
| 1451 | 1479 | } |
| 1452 | 1480 | lastPctDone = -1; |
| 1453 | 1481 | blob_reset(&send); |
| 1454 | 1482 | rArrivalTime = db_double(0.0, "SELECT julianday('now')"); |
| 1455 | 1483 | |
| 1456 | 1484 | /* Send the send-private pragma if we are trying to sync private data */ |
| 1457 | | - if( privateFlag ) blob_append(&send, "pragma send-private\n", -1); |
| 1485 | + if( syncFlags & SYNC_PRIVATE ){ |
| 1486 | + blob_append(&send, "pragma send-private\n", -1); |
| 1487 | + } |
| 1458 | 1488 | |
| 1459 | 1489 | /* Begin constructing the next message (which might never be |
| 1460 | 1490 | ** sent) by beginning with the pull or push cards |
| 1461 | 1491 | */ |
| 1462 | | - if( pullFlag ){ |
| 1492 | + if( syncFlags & SYNC_PULL ){ |
| 1463 | 1493 | blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); |
| 1464 | 1494 | nCardSent++; |
| 1465 | 1495 | } |
| 1466 | | - if( pushFlag ){ |
| 1496 | + if( syncFlags & SYNC_PUSH ){ |
| 1467 | 1497 | blob_appendf(&send, "push %s %s\n", zSCode, zPCode); |
| 1468 | 1498 | nCardSent++; |
| 1469 | 1499 | } |
| 1470 | 1500 | go = 0; |
| 1471 | 1501 | |
| | @@ -1493,11 +1523,11 @@ |
| 1493 | 1523 | nCardRcvd++; |
| 1494 | 1524 | continue; |
| 1495 | 1525 | } |
| 1496 | 1526 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 1497 | 1527 | nCardRcvd++; |
| 1498 | | - if( !g.cgiOutput && !g.fQuiet && recv.nUsed>0 ){ |
| 1528 | + if( (syncFlags & SYNC_VERBOSE)!=0 && recv.nUsed>0 ){ |
| 1499 | 1529 | pctDone = (recv.iCursor*100)/recv.nUsed; |
| 1500 | 1530 | if( pctDone!=lastPctDone ){ |
| 1501 | 1531 | fossil_print("\rprocessed: %d%% ", pctDone); |
| 1502 | 1532 | lastPctDone = pctDone; |
| 1503 | 1533 | fflush(stdout); |
| | @@ -1508,20 +1538,22 @@ |
| 1508 | 1538 | ** file UUID DELTASRC SIZE \n CONTENT |
| 1509 | 1539 | ** |
| 1510 | 1540 | ** Receive a file transmitted from the server. |
| 1511 | 1541 | */ |
| 1512 | 1542 | if( blob_eq(&xfer.aToken[0],"file") ){ |
| 1513 | | - xfer_accept_file(&xfer, cloneFlag); |
| 1543 | + xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0); |
| 1544 | + nArtifactRcvd++; |
| 1514 | 1545 | }else |
| 1515 | 1546 | |
| 1516 | 1547 | /* cfile UUID USIZE CSIZE \n CONTENT |
| 1517 | 1548 | ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT |
| 1518 | 1549 | ** |
| 1519 | 1550 | ** Receive a compressed file transmitted from the server. |
| 1520 | 1551 | */ |
| 1521 | 1552 | if( blob_eq(&xfer.aToken[0],"cfile") ){ |
| 1522 | 1553 | xfer_accept_compressed_file(&xfer); |
| 1554 | + nArtifactRcvd++; |
| 1523 | 1555 | }else |
| 1524 | 1556 | |
| 1525 | 1557 | /* gimme UUID |
| 1526 | 1558 | ** |
| 1527 | 1559 | ** Server is requesting a file. If the file is a manifest, assume |
| | @@ -1530,11 +1562,11 @@ |
| 1530 | 1562 | */ |
| 1531 | 1563 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 1532 | 1564 | && xfer.nToken==2 |
| 1533 | 1565 | && blob_is_uuid(&xfer.aToken[1]) |
| 1534 | 1566 | ){ |
| 1535 | | - if( pushFlag ){ |
| 1567 | + if( syncFlags & SYNC_PUSH ){ |
| 1536 | 1568 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1537 | 1569 | if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0); |
| 1538 | 1570 | } |
| 1539 | 1571 | }else |
| 1540 | 1572 | |
| | @@ -1559,11 +1591,11 @@ |
| 1559 | 1591 | rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1560 | 1592 | if( rid>0 ){ |
| 1561 | 1593 | if( !isPriv ) content_make_public(rid); |
| 1562 | 1594 | }else if( isPriv && !g.perm.Private ){ |
| 1563 | 1595 | /* ignore private files */ |
| 1564 | | - }else if( pullFlag || cloneFlag ){ |
| 1596 | + }else if( (syncFlags & (SYNC_PULL|SYNC_CLONE))!=0 ){ |
| 1565 | 1597 | rid = content_new(blob_str(&xfer.aToken[1]), isPriv); |
| 1566 | 1598 | if( rid ) newPhantom = 1; |
| 1567 | 1599 | } |
| 1568 | 1600 | remote_has(rid); |
| 1569 | 1601 | }else |
| | @@ -1574,11 +1606,11 @@ |
| 1574 | 1606 | ** Should only happen in response to a clone. This message tells |
| 1575 | 1607 | ** the client what product to use for the new database. |
| 1576 | 1608 | */ |
| 1577 | 1609 | if( blob_eq(&xfer.aToken[0],"push") |
| 1578 | 1610 | && xfer.nToken==3 |
| 1579 | | - && cloneFlag |
| 1611 | + && (syncFlags & SYNC_CLONE)!=0 |
| 1580 | 1612 | && blob_is_uuid(&xfer.aToken[1]) |
| 1581 | 1613 | && blob_is_uuid(&xfer.aToken[2]) |
| 1582 | 1614 | ){ |
| 1583 | 1615 | if( blob_eq_str(&xfer.aToken[1], zSCode, -1) ){ |
| 1584 | 1616 | fossil_fatal("server loop"); |
| | @@ -1604,11 +1636,12 @@ |
| 1604 | 1636 | Blob content; |
| 1605 | 1637 | blob_zero(&content); |
| 1606 | 1638 | blob_extract(xfer.pIn, size, &content); |
| 1607 | 1639 | g.perm.Admin = g.perm.RdAddr = 1; |
| 1608 | 1640 | configure_receive(zName, &content, origConfigRcvMask); |
| 1609 | | - nCardSent++; |
| 1641 | + nCardRcvd++; |
| 1642 | + nArtifactRcvd++; |
| 1610 | 1643 | blob_reset(&content); |
| 1611 | 1644 | blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR); |
| 1612 | 1645 | }else |
| 1613 | 1646 | |
| 1614 | 1647 | |
| | @@ -1655,12 +1688,12 @@ |
| 1655 | 1688 | ** to the next cycle. |
| 1656 | 1689 | */ |
| 1657 | 1690 | if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){ |
| 1658 | 1691 | char *zMsg = blob_terminate(&xfer.aToken[1]); |
| 1659 | 1692 | defossilize(zMsg); |
| 1660 | | - if( pushFlag && zMsg && strglob("pull only *", zMsg) ){ |
| 1661 | | - pushFlag = 0; |
| 1693 | + if( (syncFlags & SYNC_PUSH) && zMsg && strglob("pull only *", zMsg) ){ |
| 1694 | + syncFlags &= ~SYNC_PUSH; |
| 1662 | 1695 | zMsg = 0; |
| 1663 | 1696 | } |
| 1664 | 1697 | fossil_print("\rServer says: %s\n", zMsg); |
| 1665 | 1698 | }else |
| 1666 | 1699 | |
| | @@ -1683,11 +1716,11 @@ |
| 1683 | 1716 | ** is returned in the reply before the error card, so second and |
| 1684 | 1717 | ** subsequent messages should be OK. Nevertheless, we need to ignore |
| 1685 | 1718 | ** the error card on the first message of a clone. |
| 1686 | 1719 | */ |
| 1687 | 1720 | if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){ |
| 1688 | | - if( !cloneFlag || nCycle>0 ){ |
| 1721 | + if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){ |
| 1689 | 1722 | char *zMsg = blob_terminate(&xfer.aToken[1]); |
| 1690 | 1723 | defossilize(zMsg); |
| 1691 | 1724 | if( fossil_strcmp(zMsg, "login failed")==0 ){ |
| 1692 | 1725 | if( nCycle<2 ){ |
| 1693 | 1726 | if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0); |
| | @@ -1727,14 +1760,16 @@ |
| 1727 | 1760 | && (configRcvMask & CONFIGSET_OLDFORMAT)!=0 |
| 1728 | 1761 | ){ |
| 1729 | 1762 | configure_finalize_receive(); |
| 1730 | 1763 | } |
| 1731 | 1764 | origConfigRcvMask = 0; |
| 1732 | | - if( nCardRcvd>0 ){ |
| 1765 | + if( nCardRcvd>0 && (syncFlags & SYNC_VERBOSE) ){ |
| 1733 | 1766 | fossil_print(zValueFormat, "Received:", |
| 1734 | 1767 | blob_size(&recv), nCardRcvd, |
| 1735 | 1768 | xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile); |
| 1769 | + }else{ |
| 1770 | + fossil_print(zBriefFormat, nRoundtrip, nArtifactSent, nArtifactRcvd); |
| 1736 | 1771 | } |
| 1737 | 1772 | blob_reset(&recv); |
| 1738 | 1773 | nCycle++; |
| 1739 | 1774 | |
| 1740 | 1775 | /* If we received one or more files on the previous exchange but |
| | @@ -1743,11 +1778,11 @@ |
| 1743 | 1778 | nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile; |
| 1744 | 1779 | if( (nFileRecv>0 || newPhantom) && db_exists("SELECT 1 FROM phantom") ){ |
| 1745 | 1780 | go = 1; |
| 1746 | 1781 | mxPhantomReq = nFileRecv*2; |
| 1747 | 1782 | if( mxPhantomReq<200 ) mxPhantomReq = 200; |
| 1748 | | - }else if( cloneFlag && nFileRecv>0 ){ |
| 1783 | + }else if( (syncFlags & SYNC_CLONE)!=0 && nFileRecv>0 ){ |
| 1749 | 1784 | go = 1; |
| 1750 | 1785 | } |
| 1751 | 1786 | nCardRcvd = 0; |
| 1752 | 1787 | xfer.nFileRcvd = 0; |
| 1753 | 1788 | xfer.nDeltaRcvd = 0; |
| | @@ -1759,25 +1794,27 @@ |
| 1759 | 1794 | if( xfer.nFileSent+xfer.nDeltaSent>0 ){ |
| 1760 | 1795 | go = 1; |
| 1761 | 1796 | } |
| 1762 | 1797 | |
| 1763 | 1798 | /* If this is a clone, the go at least two rounds */ |
| 1764 | | - if( cloneFlag && nCycle==1 ) go = 1; |
| 1799 | + if( (syncFlags & SYNC_CLONE)!=0 && nCycle==1 ) go = 1; |
| 1765 | 1800 | |
| 1766 | 1801 | /* Stop the cycle if the server sends a "clone_seqno 0" card and |
| 1767 | 1802 | ** we have gone at least two rounds. Always go at least two rounds |
| 1768 | 1803 | ** on a clone in order to be sure to retrieve the configuration |
| 1769 | 1804 | ** information which is only sent on the second round. |
| 1770 | 1805 | */ |
| 1771 | 1806 | if( cloneSeqno<=0 && nCycle>1 ) go = 0; |
| 1772 | 1807 | }; |
| 1773 | 1808 | transport_stats(&nSent, &nRcvd, 1); |
| 1774 | | - fossil_print("Total network traffic: %lld bytes sent, %lld bytes received\n", |
| 1775 | | - nSent, nRcvd); |
| 1809 | + if( (syncFlags & SYNC_VERBOSE)==0 ) fossil_print("\n"); |
| 1810 | + fossil_print( |
| 1811 | + "%s finished with %lld bytes sent, %lld bytes received\n", |
| 1812 | + zOpType, nSent, nRcvd); |
| 1776 | 1813 | transport_close(); |
| 1777 | 1814 | transport_global_shutdown(); |
| 1778 | 1815 | db_multi_exec("DROP TABLE onremote"); |
| 1779 | 1816 | manifest_crosslink_end(); |
| 1780 | 1817 | content_enable_dephantomize(1); |
| 1781 | 1818 | db_end_transaction(0); |
| 1782 | 1819 | return nErr; |
| 1783 | 1820 | } |
| 1784 | 1821 | |