public synchronized boolean trim ( ) throws IOException { boolean modified = false ; for ( Entry < String , RangeSet > e : new Hashtable <> ( usages ) . entrySet ( ) ) { // copy because we mutate Job j = Jenkins . getInstance ( ) . getItemByFullName ( e . getKey ( ) , Job . class ) ; if ( j == null ) { // no such job any more. recycle the record modified = true ; usages . remove ( e . getKey ( ) ) ; continue ; } Run firstBuild = j . getFirstBuild ( ) ; if ( firstBuild == null ) { // no builds. recycle the whole record modified = true ; usages . remove ( e . getKey ( ) ) ; continue ; } RangeSet cur = e . getValue ( ) ; // builds that are around without the keepLog flag on are normally clustered together (in terms of build #) // so our basic strategy is to discard everything up to the first ephemeral build, except those builds // that are marked as kept RangeSet kept = new RangeSet ( ) ; Run r = firstBuild ; while ( r != null && r . isKeepLog ( ) ) { kept . add ( r . getNumber ( ) ) ; r = r . getNextBuild ( ) ; } if ( r == null ) { // all the build records are permanently kept ones, so we'll just have to keep 'kept' out of whatever currently in 'cur' modified |= cur . retainAll ( kept ) ; } else { // otherwise we are ready to discard [0,r.number) except those marked as 'kept' RangeSet discarding = new RangeSet ( new Range ( - 1 , r . getNumber ( ) ) ) ; discarding . removeAll ( kept ) ; modified |= cur . removeAll ( discarding ) ; } if ( cur . isEmpty ( ) ) { usages . remove ( e . getKey ( ) ) ; modified = true ; } } if ( modified ) { if ( logger . isLoggable ( Level . FINE ) ) { logger . log ( Level . FINE , "Saving trimmed {0}" , getFingerprintFile ( md5sum ) ) ; } save ( ) ; } return modified ; }
Trim off references to non - existent builds and jobs thereby making the fingerprint smaller .