2525import com .google .cloud .logging .Logging .WriteOption ;
2626import com .google .common .collect .ImmutableList ;
2727import com .google .common .collect .ImmutableMap ;
28- import com .google .common .collect .MapMaker ;
2928import com .google .common .util .concurrent .Uninterruptibles ;
3029import java .util .ArrayList ;
3130import java .util .Collections ;
31+ import java .util .IdentityHashMap ;
3232import java .util .List ;
33- import java .util .concurrent .ConcurrentMap ;
33+ import java .util .Set ;
34+ import java .util .concurrent .locks .Lock ;
35+ import java .util .concurrent .locks .ReentrantLock ;
3436import java .util .logging .ErrorManager ;
3537import java .util .logging .Filter ;
3638import java .util .logging .Formatter ;
@@ -123,12 +125,9 @@ public class LoggingHandler extends Handler {
123125 // https://github.com/GoogleCloudPlatform/google-cloud-java/issues/1740 .
124126 private final Level baseLevel ;
125127
126- // A map whose keys are pending write operations. The values of the map are meaningless, but the type is Boolean
127- // and not Void since the map implementation does not allow null values.
128- // Since the map has weak keys and we do not hold on to completed futures,
129- // completed futures are automatically GCed and removed from the map.
130- private final ConcurrentMap <ApiFuture <Void >, Boolean > pendingWrites =
131- new MapMaker ().weakKeys ().makeMap ();
128+ private final Lock writeLock = new ReentrantLock ();
129+ private final Set <ApiFuture <Void >> pendingWrites =
130+ Collections .newSetFromMap (new IdentityHashMap <ApiFuture <Void >, Boolean >());
132131
133132 /**
134133 * Creates an handler that publishes messages to Stackdriver Logging.
@@ -473,22 +472,36 @@ void write(LogEntry entry, WriteOption... options) {
473472
474473 case ASYNC :
475474 default :
476- ApiFuture <Void > writeFuture = getLogging ().writeAsync (entryList , options );
477- pendingWrites .put (writeFuture , Boolean .TRUE );
475+ final ApiFuture <Void > writeFuture = getLogging ().writeAsync (entryList , options );
476+ writeLock .lock ();
477+ try {
478+ pendingWrites .add (writeFuture );
479+ } finally {
480+ writeLock .unlock ();
481+ }
478482 ApiFutures .addCallback (
479483 writeFuture ,
480484 new ApiFutureCallback <Void >() {
481485 @ Override
482486 public void onSuccess (Void v ) {
483- // Nothing to do.
487+ writeLock .lock ();
488+ try {
489+ pendingWrites .remove (writeFuture );
490+ } finally {
491+ writeLock .unlock ();
492+ }
484493 }
485494
486495 @ Override
487496 public void onFailure (Throwable t ) {
488- if (t instanceof Exception ) {
489- reportError (null , (Exception ) t , ErrorManager .FLUSH_FAILURE );
490- } else {
491- reportError (null , new Exception (t ), ErrorManager .FLUSH_FAILURE );
497+ try {
498+ if (t instanceof Exception ) {
499+ reportError (null , (Exception ) t , ErrorManager .FLUSH_FAILURE );
500+ } else {
501+ reportError (null , new Exception (t ), ErrorManager .FLUSH_FAILURE );
502+ }
503+ } finally {
504+ onSuccess (null );
492505 }
493506 }
494507 });
@@ -500,22 +513,19 @@ public void onFailure(Throwable t) {
500513 public void flush () {
501514 // BUG(1795): flush is broken, need support from batching implementation.
502515
503- // Make a copy of currently-pending writes.
504- // As new writes are made, they might be reflected in the keySet iterator.
505- // If we naively iterate through keySet, waiting for each future,
506- // we might never finish.
507- ArrayList <ApiFuture <Void >> writes = new ArrayList <>(pendingWrites .size ());
508- for (ApiFuture <Void > write : pendingWrites .keySet ()) {
509- writes .add (write );
516+ ArrayList <ApiFuture <Void >> writes = new ArrayList <>();
517+ writeLock .lock ();
518+ try {
519+ writes .addAll (pendingWrites );
520+ } finally {
521+ writeLock .unlock ();
510522 }
511- for (int i = 0 ; i < writes .size (); i ++) {
512- ApiFuture <Void > write = writes .get (i );
523+ for (ApiFuture <Void > write : writes ) {
513524 try {
514525 Uninterruptibles .getUninterruptibly (write );
515526 } catch (Exception e ) {
516527 // Ignore exceptions, they are propagated to the error manager.
517528 }
518- writes .set (i , null );
519529 }
520530 }
521531
0 commit comments