Changes On Branch annotate_noleak
Not logged in

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

Changes In Branch annotate_noleak Excluding Merge-Ins

This is equivalent to a diff from 0cf5416002 to 4860d9f234

2011-10-14
16:11
Merging the annotate_noleak changes, about removing an important memory leak in the annotate operation.    It also fixes some blob behaviour in blob.c and content.c.    Update: Removed from trunk. Replaced by the must simpler fix at [9929bab702f99839ee] check-in: 409f370a6d user: viriketo tags: declined
2011-09-13
17:18
The Label list was not properly freed in some cases; looking at the annotate of 'win/Makefile.msc' was triggering the case. Closed-Leaf check-in: 4860d9f234 user: viriketo tags: annotate_noleak
16:43
Getting in the changes reducing the leak on annotate. In the fossil mailing list, I received only opinions in favour of getting mallocs and frees properly paired, so I think noone will refuse the change. check-in: 7870a89b10 user: viriketo tags: annotate_noleak
2011-09-06
13:23
Close A and LI tags when displaying new and deleted files in timeline. check-in: 8d703ff956 user: dmitry tags: trunk
07:33
Two fixes about localtime: • The ci_edit page tells the user that it asks UTC time • The object_description gives links to localtime (if it's set in the config). Otherwise the links were not pointing at the concerning checkin. Leaf check-in: 1765c18d94 user: viriketo tags: localtime_fixes
2011-09-04
20:43
Updating from trunk to get the latest code. check-in: 73b6ff4966 user: viriketo tags: annotate_noleak
01:28
Update the built-in SQLite to the latest 3.7.8-alpha version that contains the improved merge-sort logic. check-in: 0cf5416002 user: drh tags: trunk
2011-09-02
16:19
Do a better job of merging branches that contain lots of file renames. check-in: 0b93b0f958 user: drh tags: trunk

Changes to src/blob.c.

   892    892   **
   893    893   ** pOut must be either uninitialized or the same as pIn.
   894    894   */
   895    895   int blob_uncompress(Blob *pIn, Blob *pOut){
   896    896     unsigned int nOut;
   897    897     unsigned char *inBuf;
   898    898     unsigned int nIn = blob_size(pIn);
   899         -  Blob temp;
          899  +  Blob temp = empty_blob;
   900    900     int rc;
   901    901     unsigned long int nOut2;
   902    902     if( nIn<=4 ){
   903    903       return 0;
   904    904     }
   905    905     inBuf = (unsigned char*)blob_buffer(pIn);
   906    906     nOut = (inBuf[0]<<24) + (inBuf[1]<<16) + (inBuf[2]<<8) + inBuf[3];

Changes to src/content.c.

    93     93                                contentCache.nAlloc*sizeof(contentCache.a[0]));
    94     94     }
    95     95     p = &contentCache.a[contentCache.n++];
    96     96     p->rid = rid;
    97     97     p->age = contentCache.nextAge++;
    98     98     contentCache.szTotal += blob_size(pBlob);
    99     99     p->content = *pBlob;
   100         -  blob_zero(pBlob);
          100  +  *pBlob = empty_blob;
   101    101     bag_insert(&contentCache.inCache, rid);
   102    102   }
   103    103   
   104    104   /*
   105    105   ** Clear the content cache.
   106    106   */
   107    107   void content_clear_cache(void){
................................................................................
   257    257     if( nextRid==0 ){
   258    258       rc = content_of_blob(rid, pBlob);
   259    259     }else{
   260    260       int n = 1;
   261    261       int nAlloc = 10;
   262    262       int *a = 0;
   263    263       int mx;
   264         -    Blob delta, next;
          264  +    Blob delta = empty_blob, next = empty_blob;
   265    265   
   266    266       a = fossil_malloc( sizeof(a[0])*nAlloc );
   267    267       a[0] = rid;
   268    268       a[1] = nextRid;
   269    269       n = 1;
   270    270       while( !bag_find(&contentCache.inCache, nextRid)
   271    271           && (nextRid = findSrcid(nextRid))>0 ){

Changes to src/db.c.

   209    209   ** Prepare a Stmt.  Assume that the Stmt is previously uninitialized.
   210    210   ** If the input string contains multiple SQL statements, only the first
   211    211   ** one is processed.  All statements beyond the first are silently ignored.
   212    212   */
   213    213   int db_vprepare(Stmt *pStmt, int errOk, const char *zFormat, va_list ap){
   214    214     int rc;
   215    215     char *zSql;
   216         -  blob_zero(&pStmt->sql);
          216  +  pStmt->sql = empty_blob;
   217    217     blob_vappendf(&pStmt->sql, zFormat, ap);
   218    218     va_end(ap);
   219    219     zSql = blob_str(&pStmt->sql);
   220    220     nPrepare++;
   221    221     rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt->pStmt, 0);
   222    222     if( rc!=0 && !errOk ){
   223    223       db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);

Changes to src/deltacmd.c.

    75     75   **
    76     76   ** It works ok for pTarget and pOriginal to be the same blob.
    77     77   **
    78     78   ** Return the length of the target.  Return -1 if there is an error.
    79     79   */
    80     80   int blob_delta_apply(Blob *pOriginal, Blob *pDelta, Blob *pTarget){
    81     81     int len, n;
    82         -  Blob out;
           82  +  Blob out = empty_blob;
    83     83   
    84     84     n = delta_output_size(blob_buffer(pDelta), blob_size(pDelta));
    85     85     blob_zero(&out);
    86     86     if( n<0 ) return -1;
    87     87     blob_resize(&out, n);
    88     88     len = delta_apply(
    89     89        blob_buffer(pOriginal), blob_size(pOriginal),

Changes to src/diff.c.

   617    617   }
   618    618   
   619    619   /**************************************************************************
   620    620   ** The basic difference engine is above.  What follows is the annotation
   621    621   ** engine.  Both are in the same file since they share many components.
   622    622   */
   623    623   
          624  +/*
          625  +** Linked list of strings, labels used in the annotator code.
          626  +** The elements of the list and the pointed string (str)
          627  +** will be freed once they become totally unreferenced
          628  +** (nref == 0).
          629  +*/
          630  +struct Label
          631  +{
          632  +    struct Label *prev;   /* previous element */
          633  +    struct Label *next;   /* next element */
          634  +    char *str;            /* The label string */
          635  +    int nref;             /* Number of references to the string */
          636  +};
          637  +
   624    638   /*
   625    639   ** The status of an annotation operation is recorded by an instance
   626    640   ** of the following structure.
   627    641   */
   628    642   typedef struct Annotator Annotator;
   629    643   struct Annotator {
   630    644     DContext c;       /* The diff-engine context */
   631    645     struct AnnLine {  /* Lines of the original files... */
   632    646       const char *z;       /* The text of the line */
   633    647       short int n;         /* Number of bytes (omitting trailing space and \n) */
   634    648       short int iLevel;    /* Level at which tag was set */
   635         -    const char *zSrc;    /* Tag showing origin of this line */
          649  +    struct Label *zSrc;    /* Tag showing origin of this line */
   636    650     } *aOrig;
   637    651     int nOrig;        /* Number of elements in aOrig[] */
   638    652     int nNoSrc;       /* Number of entries where aOrig[].zSrc==NULL */
   639    653     int iLevel;       /* Current level */
   640    654     int nVers;        /* Number of versions analyzed */
   641         -  char **azVers;    /* Names of versions analyzed */
          655  +  struct Label **azVers;    /* Names of versions analyzed */
          656  +  Blob toAnnotate;
          657  +  struct Label *firstLabel;
   642    658   };
   643    659   
   644    660   /*
   645    661   ** Initialize the annotation process by specifying the file that is
   646    662   ** to be annotated.  The annotator takes control of the input Blob and
   647    663   ** will release it when it is finished with it.
   648    664   */
   649         -static int annotation_start(Annotator *p, Blob *pInput){
          665  +static int annotation_start(Annotator *p){
   650    666     int i;
   651    667   
   652         -  memset(p, 0, sizeof(*p));
   653         -  p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,1);
          668  +  p->c.aTo = break_into_lines(blob_str(&p->toAnnotate),
          669  +          blob_size(&p->toAnnotate),&p->c.nTo,1);
   654    670     if( p->c.aTo==0 ){
   655    671       return 1;
   656    672     }
   657    673     p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo );
   658    674     for(i=0; i<p->c.nTo; i++){
   659    675       p->aOrig[i].z = p->c.aTo[i].z;
   660    676       p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK;
................................................................................
   667    683   /*
   668    684   ** The input pParent is the next most recent ancestor of the file
   669    685   ** being annotated.  Do another step of the annotation.  Return true
   670    686   ** if additional annotation is required.  zPName is the tag to insert
   671    687   ** on each line of the file being annotated that was contributed by
   672    688   ** pParent.  Memory to hold zPName is leaked.
   673    689   */
   674         -static int annotation_step(Annotator *p, Blob *pParent, char *zPName){
          690  +static int annotation_step(Annotator *p, Blob *pParent, struct Label *zPName){
   675    691     int i, j;
   676    692     int lnTo;
   677    693     int iPrevLevel;
   678    694     int iThisLevel;
   679    695   
   680    696     /* Prepare the parent file to be diffed */
   681    697     p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent),
   682    698                                   &p->c.nFrom, 1);
   683    699     if( p->c.aFrom==0 ){
          700  +    free(p->c.aFrom);
   684    701       return 1;
   685    702     }
   686    703   
   687    704     /* Compute the differences going from pParent to the file being
   688    705     ** annotated. */
   689    706     diff_all(&p->c);
   690    707   
................................................................................
   694    711     iPrevLevel = p->iLevel;
   695    712     p->iLevel++;
   696    713     iThisLevel = p->iLevel;
   697    714     for(i=lnTo=0; i<p->c.nEdit; i+=3){
   698    715       struct AnnLine *x = &p->aOrig[lnTo];
   699    716       for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){
   700    717         if( x->zSrc==0 || x->iLevel==iPrevLevel ){
          718  +         if (x->zSrc!=0)
          719  +         {
          720  +           if(--x->zSrc->nref == 0)
          721  +           {
          722  +             free(x->zSrc->str);
          723  +             if (x->zSrc->prev)
          724  +               x->zSrc->prev->next = x->zSrc->next;
          725  +             if (x->zSrc->next)
          726  +               x->zSrc->next->prev = x->zSrc->prev;
          727  +             free(x->zSrc);
          728  +           }
          729  +         }
   701    730            x->zSrc = zPName;
          731  +         ++zPName->nref;
   702    732            x->iLevel = iThisLevel;
   703    733         }
   704    734       }
   705    735       lnTo += p->c.aEdit[i+2];
   706    736     }
   707    737   
   708    738     /* Clear out the diff results */
................................................................................
   709    739     free(p->c.aEdit);
   710    740     p->c.aEdit = 0;
   711    741     p->c.nEdit = 0;
   712    742     p->c.nEditAlloc = 0;
   713    743   
   714    744     /* Clear out the from file */
   715    745     free(p->c.aFrom);    
   716         -  blob_zero(pParent);
          746  +  blob_reset(pParent);
   717    747   
   718    748     /* Return no errors */
   719    749     return 0;
   720    750   }
   721    751   
   722    752   
   723    753   /*
   724    754   ** COMMAND: test-annotate-step
   725    755   */
   726    756   void test_annotate_step_cmd(void){
   727         -  Blob orig, b;
          757  +  Blob b = empty_blob;
   728    758     Annotator x;
   729    759     int i;
   730    760   
   731    761     if( g.argc<4 ) usage("RID1 RID2 ...");
   732    762     db_must_be_within_tree();
   733         -  blob_zero(&b);
   734         -  content_get(name_to_rid(g.argv[2]), &orig);
   735         -  if( annotation_start(&x, &orig) ){
          763  +  memset(&x, 0, sizeof(x));
          764  +  x.toAnnotate = empty_blob;
          765  +  content_get(name_to_rid(g.argv[2]), &x.toAnnotate);
          766  +  if( annotation_start(&x) ){
   736    767       fossil_fatal("binary file");
   737    768     }
   738    769     for(i=3; i<g.argc; i++){
          770  +    struct Label *l;
   739    771       blob_zero(&b);
   740    772       content_get(name_to_rid(g.argv[i]), &b);
   741         -    if( annotation_step(&x, &b, g.argv[i-1]) ){
          773  +    l = fossil_malloc(sizeof(*l));
          774  +    l->str = g.argv[i-1];
          775  +    l->nref = 0;
          776  +    l->next = x.firstLabel;
          777  +    if (x.firstLabel)
          778  +      x.firstLabel->prev = l;
          779  +    x.firstLabel = l;
          780  +    if( annotation_step(&x, &b, l) ){
   742    781         fossil_fatal("binary file");
   743    782       }
   744    783     }
   745    784     for(i=0; i<x.nOrig; i++){
   746         -    const char *zSrc = x.aOrig[i].zSrc;
          785  +    const char *zSrc = x.aOrig[i].zSrc->str;
   747    786       if( zSrc==0 ) zSrc = g.argv[g.argc-1];
   748    787       fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
          788  +  }
          789  +  while(x.firstLabel) {
          790  +    struct Label *l;
          791  +    l = x.firstLabel->next;
          792  +    assert(x.firstLabel->nref > 0);
          793  +    free(x.firstLabel->str);
          794  +    free(x.firstLabel);
          795  +    x.firstLabel = l;
   749    796     }
   750    797   }
   751    798   
   752    799   /* Annotation flags */
   753    800   #define ANN_FILE_VERS  0x001  /* Show file version rather than commit version */
   754    801   
   755    802   /*
................................................................................
   761    808     Annotator *p,        /* The annotator */
   762    809     int fnid,            /* The name of the file to be annotated */
   763    810     int mid,             /* Use the version of the file in this check-in */
   764    811     int webLabel,        /* Use web-style annotations if true */
   765    812     int iLimit,          /* Limit the number of levels if greater than zero */
   766    813     int annFlags         /* Flags to alter the annotation */
   767    814   ){
   768         -  Blob toAnnotate;     /* Text of the final (mid) version of the file */
   769         -  Blob step;           /* Text of previous revision */
          815  +  Blob step = empty_blob;           /* Text of previous revision */
   770    816     int rid;             /* Artifact ID of the file being annotated */
   771         -  char *zLabel;        /* Label to apply to a line */
   772    817     Stmt q;              /* Query returning all ancestor versions */
   773    818   
   774    819     /* Initialize the annotation */
   775    820     rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
   776    821     if( rid==0 ){
   777    822       fossil_panic("file #%d is unchanged in manifest #%d", fnid, mid);
   778    823     }
   779         -  if( !content_get(rid, &toAnnotate) ){
          824  +  memset(p, 0, sizeof(*p));
          825  +  p->toAnnotate = empty_blob;
          826  +  if( !content_get(rid, &p->toAnnotate) ){
   780    827       fossil_panic("unable to retrieve content of artifact #%d", rid);
   781    828     }
   782    829     db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
   783    830     if( iLimit<=0 ) iLimit = 1000000000;
   784    831     compute_direct_ancestors(mid, iLimit);
   785         -  annotation_start(p, &toAnnotate);
          832  +  annotation_start(p);
   786    833   
   787    834     db_prepare(&q, 
   788    835       "SELECT mlink.fid,"
   789    836       "       (SELECT uuid FROM blob WHERE rid=mlink.%s),"
   790    837       "       date(event.mtime), "
   791    838       "       coalesce(event.euser,event.user) "
   792    839       "  FROM ancestor, mlink, event"
................................................................................
   800    847       iLimit>0 ? iLimit : 10000000
   801    848     );
   802    849     while( db_step(&q)==SQLITE_ROW ){
   803    850       int pid = db_column_int(&q, 0);
   804    851       const char *zUuid = db_column_text(&q, 1);
   805    852       const char *zDate = db_column_text(&q, 2);
   806    853       const char *zUser = db_column_text(&q, 3);
          854  +    struct Label *l = fossil_malloc(sizeof(*l));
          855  +    l->nref = 0;
          856  +    l->next = p->firstLabel;
          857  +    l->prev = 0;
          858  +    if (p->firstLabel)
          859  +      p->firstLabel->prev = l;
   807    860       if( webLabel ){
   808         -      zLabel = mprintf(
          861  +      l->str = mprintf(
   809    862             "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s", 
   810    863             g.zTop, zUuid, zUuid, zDate, zUser
   811    864         );
   812    865       }else{
   813         -      zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
          866  +      l->str = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
   814    867       }
          868  +    p->firstLabel = l;
   815    869       p->nVers++;
   816    870       p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
   817         -    p->azVers[p->nVers-1] = zLabel;
          871  +    p->azVers[p->nVers-1] = l;
   818    872       content_get(pid, &step);
   819         -    annotation_step(p, &step, zLabel);
          873  +    annotation_step(p, &step, l);
          874  +    if (l->nref == 0)
          875  +    {
          876  +      free(l->str);
          877  +      p->firstLabel = l->next;
          878  +      if (l->next)
          879  +        l->next->prev = 0;
          880  +      free(l);
          881  +    }
   820    882       blob_reset(&step);
   821    883     }
   822    884     db_finalize(&q);
          885  +  free(p->c.aTo);
   823    886   }
   824    887   
   825    888   /*
   826    889   ** WEBPAGE: annotate
   827    890   **
   828    891   ** Query parameters:
   829    892   **
................................................................................
   851    914     if( P("filevers") ) annFlags |= ANN_FILE_VERS;
   852    915     annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags);
   853    916     if( P("log") ){
   854    917       int i;
   855    918       @ <h2>Versions analyzed:</h2>
   856    919       @ <ol>
   857    920       for(i=0; i<ann.nVers; i++){
   858         -      @ <li><tt>%s(ann.azVers[i])</tt></li>
          921  +      @ <li><tt>%s(ann.azVers[i]->str)</tt></li>
   859    922       }
   860    923       @ </ol>
   861    924       @ <hr>
   862    925       @ <h2>Annotation:</h2>
   863    926     }
   864    927     @ <pre>
   865    928     for(i=0; i<ann.nOrig; i++){
   866    929       ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
   867         -    @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
          930  +    @ %s(ann.aOrig[i].zSrc->str): %h(ann.aOrig[i].z)
   868    931     }
   869    932     @ </pre>
   870    933     style_footer();
          934  +
          935  +  free(ann.azVers);
          936  +  free(ann.aOrig);
          937  +  blob_reset(&ann.toAnnotate);
          938  +  while(ann.firstLabel) {
          939  +    struct Label *l;
          940  +    l = ann.firstLabel->next;
          941  +    assert(ann.firstLabel->nref > 0);
          942  +    free(ann.firstLabel->str);
          943  +    free(ann.firstLabel);
          944  +    ann.firstLabel = l;
          945  +  }
   871    946   }
   872    947   
   873    948   /*
   874    949   ** COMMAND: annotate
   875    950   **
   876    951   ** %fossil annotate FILENAME
   877    952   **
................................................................................
   883    958   **   --log           List all versions analyzed
   884    959   **   --filevers      Show file version numbers rather than check-in versions
   885    960   */
   886    961   void annotate_cmd(void){
   887    962     int fnid;         /* Filename ID */
   888    963     int fid;          /* File instance ID */
   889    964     int mid;          /* Manifest where file was checked in */
   890         -  Blob treename;    /* FILENAME translated to canonical form */
          965  +  Blob treename = empty_blob;    /* FILENAME translated to canonical form */
   891    966     char *zFilename;  /* Cannonical filename */
   892    967     Annotator ann;    /* The annotation of the file */
   893    968     int i;            /* Loop counter */
   894    969     const char *zLimit; /* The value to the --limit option */
   895    970     int iLimit;       /* How far back in time to look */
   896    971     int showLog;      /* True to show the log */
   897    972     int fileVers;     /* Show file version instead of check-in versions */
................................................................................
   912    987     if( fnid==0 ){
   913    988       fossil_fatal("no such file: %s", zFilename);
   914    989     }
   915    990     fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename);
   916    991     if( fid==0 ){
   917    992       fossil_fatal("not part of current checkout: %s", zFilename);
   918    993     }
          994  +  blob_reset(&treename);
   919    995     mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid);
   920    996     if( mid==0 ){
   921    997       fossil_panic("unable to find manifest");
   922    998     }
   923    999     if( fileVers ) annFlags |= ANN_FILE_VERS;
   924   1000     annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
   925   1001     if( showLog ){
   926   1002       for(i=0; i<ann.nVers; i++){
   927         -      printf("version %3d: %s\n", i+1, ann.azVers[i]);
         1003  +      printf("version %3d: %s\n", i+1, ann.azVers[i]->str);
   928   1004       }
   929   1005       printf("---------------------------------------------------\n");
   930   1006     }
   931   1007     for(i=0; i<ann.nOrig; i++){
   932   1008       fossil_print("%s: %.*s\n", 
   933         -                 ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
         1009  +                 ann.aOrig[i].zSrc->str, ann.aOrig[i].n, ann.aOrig[i].z);
         1010  +  }
         1011  +  free(ann.azVers);
         1012  +  free(ann.aOrig);
         1013  +  blob_reset(&ann.toAnnotate);
         1014  +  while(ann.firstLabel) {
         1015  +    struct Label *l;
         1016  +    l = ann.firstLabel->next;
         1017  +    assert(ann.firstLabel->nref > 0);
         1018  +    free(ann.firstLabel->str);
         1019  +    free(ann.firstLabel);
         1020  +    ann.firstLabel = l;
   934   1021     }
   935   1022   }

Changes to src/file.c.

   699    699   ** message and quit if the errFatal flag is true.  If errFatal is
   700    700   ** false, then simply return 0.
   701    701   **
   702    702   ** The root of the tree is defined by the g.zLocalRoot variable.
   703    703   */
   704    704   int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){
   705    705     int n;
   706         -  Blob full;
          706  +  Blob full = empty_blob;
   707    707     int nFull;
   708    708     char *zFull;
   709    709   
   710    710     blob_zero(pOut);
   711    711     db_must_be_within_tree();
   712    712     file_canonical_name(zOrigName, &full);
   713    713     n = strlen(g.zLocalRoot);