@@ -98,8 +98,11 @@
** content of DELTASRC.
**
** If any error occurs, write a message into pErr which has already
** be initialized to an empty string.
+**
+** Any artifact successfully received by this routine is considered to
+** be public and is therefore removed from the "private" table.
*/
static void xfer_accept_file(Xfer *pXfer){
int n;
int rid;
@@ -129,8 +132,9 @@
if( content_get(srcid, &src)==0 ){
rid = content_put(&content, blob_str(&pXfer->aToken[1]), srcid);
pXfer->nDanglingFile++;
db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
+ content_make_public(rid);
return;
}
pXfer->nDeltaRcvd++;
blob_delta_apply(&src, &content, &content);
@@ -146,9 +150,9 @@
blob_reset(&hash);
if( rid==0 ){
blob_appendf(&pXfer->err, "%s", g.zErrMsg);
}else{
- /* db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); */
+ content_make_public(rid);
manifest_crosslink(rid, &content);
}
remote_has(rid);
}
@@ -157,8 +161,10 @@
** Try to send a file as a delta against its parent.
** If successful, return the number of bytes in the delta.
** If we cannot generate an appropriate delta, then send
** nothing and return zero.
+**
+** Never send a delta against a private artifact.
*/
static int send_delta_parent(
Xfer *pXfer, /* The transfer context */
int rid, /* record id of the file to send */
@@ -185,9 +191,9 @@
for(i=0; srcId==0 && i<count(azQuery); i++){
srcId = db_int(0, azQuery[i], rid);
}
- if( srcId>0 && content_get(srcId, &src) ){
+ if( srcId>0 && !content_is_private(srcId) && content_get(srcId, &src) ){
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", srcId);
blob_delta_create(&src, pContent, &delta);
size = blob_size(&delta);
if( size>=blob_size(pContent)-50 ){
@@ -210,8 +216,10 @@
** Try to send a file as a native delta.
** If successful, return the number of bytes in the delta.
** If we cannot generate an appropriate delta, then send
** nothing and return zero.
+**
+** Never send a delta against a private artifact.
*/
static int send_delta_native(
Xfer *pXfer, /* The transfer context */
int rid, /* record id of the file to send */
@@ -221,9 +229,9 @@
int size = 0;
int srcId;
srcId = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", rid);
- if( srcId>0 ){
+ if( srcId>0 && !content_is_private(srcId) ){
blob_zero(&src);
db_blob(&src, "SELECT uuid FROM blob WHERE rid=%d", srcId);
if( uuid_is_shunned(blob_str(&src)) ){
blob_reset(&src);
@@ -251,13 +259,18 @@
** from the rid.
**
** Try to send the file as a native delta if nativeDelta is true, or
** as a parent delta if nativeDelta is false.
+**
+** It should never be the case that rid is a private artifact. But
+** as a precaution, this routine does check on rid and if it is private
+** this routine becomes a no-op.
*/
static void send_file(Xfer *pXfer, int rid, Blob *pUuid, int nativeDelta){
Blob content, uuid;
int size = 0;
+ if( content_is_private(rid) ) return;
if( db_exists("SELECT 1 FROM onremote WHERE rid=%d", rid) ){
return;
}
blob_zero(&uuid);
@@ -309,14 +322,18 @@
}
/*
** Send a gimme message for every phantom.
+**
+** It should not be possible to have a private phantom. But just to be
+** sure, take care not to send any "gimme" messagse on private artifacts.
*/
static void request_phantoms(Xfer *pXfer, int maxReq){
Stmt q;
db_prepare(&q,
"SELECT uuid FROM phantom JOIN blob USING(rid)"
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
+ " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
);
while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){
const char *zUuid = db_column_text(&q, 0);
blob_appendf(pXfer->pOut, "gimme %s\n", zUuid);
@@ -402,9 +419,9 @@
** It just might require an extra round trip or two.
*/
static void send_unsent(Xfer *pXfer){
Stmt q;
- db_prepare(&q, "SELECT rid FROM unsent");
+ db_prepare(&q, "SELECT rid FROM unsent EXCEPT SELECT rid FROM private");
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
send_file(pXfer, rid, 0, 0);
}
@@ -421,8 +438,15 @@
static void create_cluster(void){
Blob cluster, cksum;
Stmt q;
int nUncl;
+
+ /* We should not ever get any private artifacts in the unclustered table.
+ ** But if we do (because of a bug) now is a good time to delete them. */
+ db_multi_exec(
+ "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)"
+ );
+
nUncl = db_int(0, "SELECT count(*) FROM unclustered"
" WHERE NOT EXISTS(SELECT 1 FROM phantom"
" WHERE rid=unclustered.rid)");
if( nUncl<100 ){
@@ -456,8 +480,9 @@
int cnt = 0;
db_prepare(&q,
"SELECT uuid FROM unclustered JOIN blob USING(rid)"
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
+ " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
);
while( db_step(&q)==SQLITE_ROW ){
blob_appendf(pXfer->pOut, "igot %s\n", db_column_text(&q, 0));
cnt++;
@@ -473,8 +498,9 @@
Stmt q;
db_prepare(&q,
"SELECT uuid FROM blob "
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
+ " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
);
while( db_step(&q)==SQLITE_ROW ){
blob_appendf(pXfer->pOut, "igot %s\n", db_column_text(&q, 0));
}
@@ -1037,9 +1063,11 @@
&& blob_eq(&xfer.aToken[0], "igot")
&& blob_is_uuid(&xfer.aToken[1])
){
int rid = rid_from_uuid(&xfer.aToken[1], 0);
- if( rid==0 && (pullFlag || cloneFlag) ){
+ if( rid>0 ){
+ content_make_public(rid);
+ }else if( pullFlag || cloneFlag ){
rid = content_new(blob_str(&xfer.aToken[1]));
if( rid ) newPhantom = 1;
}
remote_has(rid);