public void putAll ( final Collection < Bucket > updates ) { final Set < Key > good = this . cachePutIfUntouched ( updates ) ; if ( good . size ( ) == updates . size ( ) ) return ; // Figure out which ones were bad final List < Key > bad = updates . stream ( ) . map ( Bucket :: getKey ) . filter ( key -> ! good . contains ( key ) ) . collect ( Collectors . toList ( ) ) ; if ( ! bad . isEmpty ( ) ) { // So we had some collisions. We need to reset these back to null, but do it in a safe way - if we // blindly set null something already null, it will break any putIfUntouched() which saw the first null. // This could result in write contention starving out a real write. The solution is to only reset things // that are not already null. final Map < Key , Object > cached = this . cacheGetAll ( bad ) ; // Remove the stuff we don't care about cached . values ( ) . removeIf ( Objects :: isNull ) ; this . empty ( cached . keySet ( ) ) ; } }
Update a set of buckets with new values . If collisions occur resets the memcache value to null .