Fossil

Check-in [e2c53534]
Login

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

Overview
Comment:Improvements to the way mlink is computed. Some unnecessary mlink entries are suppressed. Running "fossil rebuild" is recommended.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e2c53534b59487b1fceb850f8cfe5f791fe8dfe8
User & Date: drh 2015-12-25 00:20:29
Context
2015-12-25
02:25
Add "Related" and "Branch Only" buttons to the t= and r= query parameters for /timeline. check-in: 95335751 user: drh tags: trunk
00:20
Improvements to the way mlink is computed. Some unnecessary mlink entries are suppressed. Running "fossil rebuild" is recommended. check-in: e2c53534 user: drh tags: trunk
2015-12-24
20:50
Fix some over-length source code lines. No functional changes. check-in: 9a8d0827 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/finfo.c.

   590    590          "SELECT"
   591    591          /* 0 */ "  datetime(event.mtime,toLocal()),"
   592    592          /* 1 */ "  (SELECT uuid FROM blob WHERE rid=mlink.mid),"
   593    593          /* 2 */ "  (SELECT uuid FROM blob WHERE rid=mlink.pmid),"
   594    594          /* 3 */ "  isaux,"
   595    595          /* 4 */ "  (SELECT uuid FROM blob WHERE rid=mlink.fid),"
   596    596          /* 5 */ "  (SELECT uuid FROM blob WHERE rid=mlink.pid),"
   597         -       /* 6 */ "  mperm,"
   598         -       /* 7 */ "  (SELECT name FROM filename WHERE fnid=mlink.pfnid)"
          597  +       /* 6 */ "  mlink.pid,"
          598  +       /* 7 */ "  mperm,"
          599  +       /* 8 */ "  (SELECT name FROM filename WHERE fnid=mlink.pfnid)"
   599    600          "  FROM mlink, event"
   600    601          " WHERE mlink.fnid=%d"
   601    602          "   AND event.objid=mlink.mid"
   602    603          " ORDER BY 1 DESC",
   603    604          fnid
   604    605       );
   605    606       @ <h1>MLINK table for file
................................................................................
   620    621       while( db_step(&q)==SQLITE_ROW ){
   621    622         const char *zDate = db_column_text(&q,0);
   622    623         const char *zCkin = db_column_text(&q,1);
   623    624         const char *zParent = db_column_text(&q,2);
   624    625         int isMerge = db_column_int(&q,3);
   625    626         const char *zFid = db_column_text(&q,4);
   626    627         const char *zPid = db_column_text(&q,5);
   627         -      int isExe = db_column_int(&q,6);
   628         -      const char *zPrior = db_column_text(&q,7);
          628  +      int isExe = db_column_int(&q,7);
          629  +      const char *zPrior = db_column_text(&q,8);
   629    630         @ <tr>
   630    631         @ <td><a href='%R/timeline?c=%!S(zCkin)'>%s(zDate)</a></td>
   631    632         @ <td><a href='%R/info/%!S(zCkin)'>%S(zCkin)</a></td>
   632    633         if( zParent ){
   633    634           @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td>
   634    635         }else{
   635    636           @ <td><i>(New)</i></td>
................................................................................
   638    639         if( zFid ){
   639    640           @ <td><a href='%R/info/%!S(zFid)'>%S(zFid)</a></td>
   640    641         }else{
   641    642           @ <td><i>(Deleted)</i></td>
   642    643         }
   643    644         if( zPid ){
   644    645           @ <td><a href='%R/info/%!S(zPid)'>%S(zPid)</a>
          646  +      }else if( db_column_int(&q,6)<0 ){
          647  +        @ <td><i>(Added by merge)</i></td>
   645    648         }else{
   646    649           @ <td><i>(New)</i></td>
   647    650         }
   648    651         @ <td align='center'>%s(isExe?"&#x2713;":"")</td>
   649    652         if( zPrior ){
   650    653           @ <td><a href='%R/finfo?name=%t(zPrior)'>%h(zPrior)</a></td>
   651    654         }else{
................................................................................
   659    662       @ </div>
   660    663       output_table_sorting_javascript("mlinktable","tttxtttt",1);
   661    664     }else{
   662    665       int mid = name_to_rid_www("ci");
   663    666       db_prepare(&q,
   664    667          "SELECT"
   665    668          /* 0 */ "  (SELECT name FROM filename WHERE fnid=mlink.fnid),"
   666         -       /* 1 */ "  fid,"
   667         -       /* 2 */ "  (SELECT uuid FROM blob WHERE rid=mlink.fid),"
   668         -       /* 3 */ "  pid,"
   669         -       /* 4 */ "  (SELECT uuid FROM blob WHERE rid=mlink.pid),"
   670         -       /* 5 */ "  (SELECT name FROM filename WHERE fnid=mlink.pfnid),"
   671         -       /* 6 */ "  pmid,"
   672         -       /* 7 */ "  (SELECT uuid FROM blob WHERE rid=mlink.pmid),"
   673         -       /* 8 */ "  mperm,"
   674         -       /* 9 */ "  isaux"
          669  +       /* 1 */ "  (SELECT uuid FROM blob WHERE rid=mlink.fid),"
          670  +       /* 2 */ "  pid,"
          671  +       /* 3 */ "  (SELECT uuid FROM blob WHERE rid=mlink.pid),"
          672  +       /* 4 */ "  (SELECT name FROM filename WHERE fnid=mlink.pfnid),"
          673  +       /* 5 */ "  (SELECT uuid FROM blob WHERE rid=mlink.pmid),"
          674  +       /* 6 */ "  mperm,"
          675  +       /* 7 */ "  isaux"
   675    676          "  FROM mlink WHERE mid=%d ORDER BY 1",
   676    677          mid
   677    678       );
   678    679       @ <h1>MLINK table for check-in %h(zCI)</h1>
   679    680       render_checkin_context(mid, 1);
   680    681       @ <hr>
   681    682       @ <div class='brlist'>
................................................................................
   688    689       @ <th>Old</th>
   689    690       @ <th>Exe Bit?</th>
   690    691       @ <th>Prior Name</th>
   691    692       @ </tr></thead>
   692    693       @ <tbody>
   693    694       while( db_step(&q)==SQLITE_ROW ){
   694    695         const char *zName = db_column_text(&q,0);
   695         -      const char *zFid = db_column_text(&q,2);
   696         -      const char *zPid = db_column_text(&q,4);
   697         -      const char *zParent = db_column_text(&q,7);
   698         -      const char *zPrior = db_column_text(&q,5);
   699         -      int isExec = db_column_int(&q,8);
   700         -      int isAux = db_column_int(&q,9);
          696  +      const char *zFid = db_column_text(&q,1);
          697  +      const char *zPid = db_column_text(&q,3);
          698  +      const char *zPrior = db_column_text(&q,4);
          699  +      const char *zParent = db_column_text(&q,5);
          700  +      int isExec = db_column_int(&q,6);
          701  +      int isAux = db_column_int(&q,7);
   701    702         @ <tr>
   702    703         @ <td><a href='%R/finfo?name=%t(zName)'>%h(zName)</a></td>
   703    704         if( zParent ){
   704    705           @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td>
   705    706         }else{
   706    707           @ <td><i>(New)</i></td>
   707    708         }
................................................................................
   709    710         if( zFid ){
   710    711           @ <td><a href='%R/info/%!S(zFid)'>%S(zFid)</a></td>
   711    712         }else{
   712    713           @ <td><i>(Deleted)</i></td>
   713    714         }
   714    715         if( zPid ){
   715    716           @ <td><a href='%R/info/%!S(zPid)'>%S(zPid)</a>
          717  +      }else if( db_column_int(&q,2)<0 ){
          718  +        @ <td><i>(Added by merge)</i></td>
   716    719         }else{
   717    720           @ <td><i>(New)</i></td>
   718    721         }
   719    722         @ <td align='center'>%s(isExec?"&#x2713;":"")</td>
   720    723         if( zPrior ){
   721    724           @ <td><a href='%R/finfo?name=%t(zPrior)'>%h(zPrior)</a></td>
   722    725         }else{

Changes to src/manifest.c.

  1183   1183     }
  1184   1184     return mperm;
  1185   1185   }
  1186   1186   
  1187   1187   /*
  1188   1188   ** Add a single entry to the mlink table.  Also add the filename to
  1189   1189   ** the filename table if it is not there already.
         1190  +**
         1191  +** An mlink entry is always created if isPrimary is true.  But if
         1192  +** isPrimary is false (meaning that pmid is a merge parent of mid)
         1193  +** then the mlink entry is only created if there is already an mlink
         1194  +** from primary parent for the same file.
  1190   1195   */
  1191   1196   static void add_one_mlink(
  1192   1197     int pmid,                 /* The parent manifest */
  1193   1198     const char *zFromUuid,    /* UUID for content in parent */
  1194   1199     int mid,                  /* The record ID of the manifest */
  1195   1200     const char *zToUuid,      /* UUID for content in child */
  1196   1201     const char *zFilename,    /* Filename */
  1197   1202     const char *zPrior,       /* Previous filename. NULL if unchanged */
  1198   1203     int isPublic,             /* True if mid is not a private manifest */
  1199   1204     int isPrimary,            /* pmid is the primary parent of mid */
  1200   1205     int mperm                 /* 1: exec, 2: symlink */
  1201   1206   ){
  1202   1207     int fnid, pfnid, pid, fid;
  1203         -  static Stmt s1;
         1208  +  int doInsert;
         1209  +  static Stmt s1, s2;
  1204   1210   
  1205   1211     fnid = filename_to_fnid(zFilename);
  1206   1212     if( zPrior==0 ){
  1207   1213       pfnid = 0;
  1208   1214     }else{
  1209   1215       pfnid = filename_to_fnid(zPrior);
  1210   1216     }
................................................................................
  1215   1221     }
  1216   1222     if( zToUuid==0 || zToUuid[0]==0 ){
  1217   1223       fid = 0;
  1218   1224     }else{
  1219   1225       fid = uuid_to_rid(zToUuid, 1);
  1220   1226       if( isPublic ) content_make_public(fid);
  1221   1227     }
  1222         -  db_static_prepare(&s1,
  1223         -    "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
  1224         -    "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
  1225         -  );
  1226         -  db_bind_int(&s1, ":m", mid);
  1227         -  db_bind_int(&s1, ":f", fid);
  1228         -  db_bind_int(&s1, ":pm", pmid);
  1229         -  db_bind_int(&s1, ":p", pid);
  1230         -  db_bind_int(&s1, ":n", fnid);
  1231         -  db_bind_int(&s1, ":pfn", pfnid);
  1232         -  db_bind_int(&s1, ":mp", mperm);
  1233         -  db_bind_int(&s1, ":isaux", isPrimary==0);
  1234         -  db_exec(&s1);
         1228  +  if( isPrimary ){
         1229  +    doInsert = 1;
         1230  +  }else{
         1231  +    db_static_prepare(&s2,
         1232  +      "SELECT 1 FROM mlink WHERE mid=:m AND fnid=:n AND NOT isaux"
         1233  +    );
         1234  +    db_bind_int(&s2, ":m", mid);
         1235  +    db_bind_int(&s2, ":n", fnid);
         1236  +    doInsert = db_step(&s2)==SQLITE_ROW;
         1237  +    db_reset(&s2);
         1238  +  }
         1239  +  if( doInsert ){
         1240  +    db_static_prepare(&s1,
         1241  +      "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
         1242  +      "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
         1243  +    );
         1244  +    db_bind_int(&s1, ":m", mid);
         1245  +    db_bind_int(&s1, ":f", fid);
         1246  +    db_bind_int(&s1, ":pm", pmid);
         1247  +    db_bind_int(&s1, ":p", pid);
         1248  +    db_bind_int(&s1, ":n", fnid);
         1249  +    db_bind_int(&s1, ":pfn", pfnid);
         1250  +    db_bind_int(&s1, ":mp", mperm);
         1251  +    db_bind_int(&s1, ":isaux", isPrimary==0);
         1252  +    db_exec(&s1);
         1253  +  }
  1235   1254     if( pid && fid ){
  1236   1255       content_deltify(pid, fid, 0);
  1237   1256     }
  1238   1257   }
  1239   1258   
  1240   1259   /*
  1241   1260   ** Do a binary search to find a file in the p->aFile[] array.
................................................................................
  1344   1363   ** A single mlink entry is added for every file that changed content,
  1345   1364   ** name, and/or permissions going from pid to cid.
  1346   1365   **
  1347   1366   ** Deleted files have mlink.fid=0.
  1348   1367   ** Added files have mlink.pid=0.
  1349   1368   ** File added by merge have mlink.pid=-1
  1350   1369   ** Edited files have both mlink.pid!=0 and mlink.fid!=0
         1370  +**
         1371  +** Many mlink entries for merge parents will only be added if another mlink
         1372  +** entry already exists for the same file from the primary parent.  Therefore,
         1373  +** to ensure that all merge-parent mlink entries are properly created:
         1374  +**
         1375  +**    (1) Make this routine a no-op if pParent is a merge parent and the
         1376  +**        primary parent is a phantom.
         1377  +**    (2) Invoke this routine recursively for merge-parents if pParent is the
         1378  +**        primary parent.
  1351   1379   */
  1352   1380   static void add_mlink(
  1353   1381     int pmid, Manifest *pParent,  /* Parent check-in */
  1354   1382     int mid,  Manifest *pChild,   /* The child check-in */
  1355   1383     int isPrim                    /* TRUE if pmid is the primary parent of mid */
  1356   1384   ){
  1357   1385     Blob otherContent;
................................................................................
  1390   1418       if( *ppOther==0 ) return;
  1391   1419     }
  1392   1420     if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
  1393   1421       manifest_destroy(*ppOther);
  1394   1422       return;
  1395   1423     }
  1396   1424     isPublic = !content_is_private(mid);
         1425  +  
         1426  +  /* If pParent is not the primary parent of pChild, and the primary
         1427  +  ** parent of pChild is a phantom, then abort this routine without
         1428  +  ** doing any work.  The mlink entries will be computed when the
         1429  +  ** primary parent dephantomizes.
         1430  +  */
         1431  +  if( !isPrim && otherRid==mid
         1432  +   && !db_exists("SELECT 1 FROM blob WHERE uuid=%Q AND size>0",
         1433  +                 pChild->azParent[0])
         1434  +  ){
         1435  +    manifest_cache_insert(*ppOther);
         1436  +    return;
         1437  +  }
  1397   1438   
  1398   1439     /* Try to make the parent manifest a delta from the child, if that
  1399   1440     ** is an appropriate thing to do.  For a new baseline, make the
  1400   1441     ** previous baseline a delta from the current baseline.
  1401   1442     */
  1402   1443     if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
  1403   1444       content_deltify(pmid, mid, 0);
................................................................................
  1487   1528         if( pChildFile==0 && pParentFile->zUuid!=0 ){
  1488   1529           add_one_mlink(pmid, pParentFile->zUuid, mid, 0, pParentFile->zName, 0,
  1489   1530                         isPublic, isPrim, 0);
  1490   1531         }
  1491   1532       }
  1492   1533     }
  1493   1534     manifest_cache_insert(*ppOther);
         1535  +  
         1536  +  /* If pParent is the primary parent of pChild, also run this analysis
         1537  +  ** for all merge parents of pChild
         1538  +  */
         1539  +  if( isPrim ){
         1540  +    for(i=1; i<pChild->nParent; i++){
         1541  +      pmid = uuid_to_rid(pChild->azParent[i], 0);
         1542  +      if( pmid<=0 ) continue;
         1543  +      add_mlink(pmid, 0, mid, pChild, 0);
         1544  +    }
         1545  +  }
  1494   1546   }
  1495   1547   
  1496   1548   /*
  1497   1549   ** Setup to do multiple manifest_crosslink() calls.
  1498   1550   ** This is only required if processing ticket changes.
  1499   1551   */
  1500   1552   void manifest_crosslink_begin(void){
................................................................................
  1796   1848         }
  1797   1849         for(i=0; i<p->nParent; i++){
  1798   1850           int pid = uuid_to_rid(p->azParent[i], 1);
  1799   1851           db_multi_exec(
  1800   1852              "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
  1801   1853              "VALUES(%d, %d, %d, %.17g, %s)",
  1802   1854              pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
  1803         -        add_mlink(pid, 0, rid, p, i==0);
  1804   1855           if( i==0 ) parentid = pid;
  1805   1856         }
         1857  +      add_mlink(parentid, 0, rid, p, 1);
  1806   1858         if( p->nParent>1 ){
  1807   1859           /* Change MLINK.PID from 0 to -1 for files that are added by merge. */
  1808   1860           db_multi_exec(
  1809   1861              "UPDATE mlink SET pid=-1"
  1810   1862              " WHERE mid=%d"
  1811   1863              "   AND pid=0"
  1812   1864              "   AND fnid IN "