@@ -508,8 +508,8 @@ class AmazonS3ScalaClient(
508
508
* interface, and [[FutureTransfer.listenFor ]] adapts this interface to
509
509
* Scala futures.
510
510
*
511
- * @see [[http://docs.aws.amazon. com/AWSJavaSDK/latest/javadoc/com/ amazonaws/ services/s3/ transfer/TransferManager.html TransferManager ]]
512
- * @see [[http://docs.aws.amazon. com/AWSJavaSDK/latest/javadoc/com/ amazonaws/ services/s3/ transfer/Transfer.html Transfer ]]
511
+ * @see [[com. amazonaws. services.s3. transfer.TransferManager TransferManager ]]
512
+ * @see [[com. amazonaws. services.s3. transfer.Transfer Transfer ]]
513
513
*/
514
514
object FutureTransfer {
515
515
@@ -518,7 +518,7 @@ object FutureTransfer {
518
518
/**
519
519
* Attach a listener to an S3 Transfer and return it as a Future.
520
520
*
521
- * This helper method attaches a progress listener to the given
521
+ * This helper method attaches a progress and state change listeners to the given
522
522
* Transfer object. The returned future is completed with the
523
523
* same transfer when the transfer is ‘done’ (canceled, completed,
524
524
* or failed). The future will always been completed successfully
@@ -536,14 +536,33 @@ object FutureTransfer {
536
536
* @param transfer
537
537
* an S3 Transfer to listen for progress.
538
538
* @return the transfer in a future.
539
- * @see [[http://docs.aws.amazon. com/AWSJavaSDK/latest/javadoc/com/ amazonaws/ services/s3/ transfer/Transfer.html Transfer ]]
540
- * @see [[http://docs.aws.amazon. com/AWSJavaSDK/latest/javadoc/com/ amazonaws/ event/ProgressListener.html ProgressListener ]]
539
+ * @see [[com. amazonaws. services.s3. transfer.Transfer Transfer ]]
540
+ * @see [[com. amazonaws. event.ProgressListener ProgressListener ]]
541
541
*/
542
542
def listenFor [T <: Transfer ](transfer : T ): Future [transfer.type ] = {
543
+ import com .amazonaws .services .s3 .transfer .internal .{ AbstractTransfer , TransferStateChangeListener }
543
544
val transferDescription = transfer.getDescription
544
545
def debugLog (eventType : String ): Unit = {
545
546
logger.debug(s " $eventType : $transferDescription" )
546
547
}
548
+ def logTransferState (state : Transfer .TransferState ): Unit = {
549
+ if (logger.isDebugEnabled) {
550
+ state match {
551
+ case Transfer .TransferState .Waiting =>
552
+ debugLog(" Waiting" )
553
+ case Transfer .TransferState .InProgress =>
554
+ debugLog(" InProgress" )
555
+ case Transfer .TransferState .Completed =>
556
+ debugLog(" Completed" )
557
+ case Transfer .TransferState .Canceled =>
558
+ debugLog(" Canceled" )
559
+ case Transfer .TransferState .Failed =>
560
+ debugLog(" Failed" )
561
+ case _ =>
562
+ logger.warn(s " unrecognized transfer state for transfer $transferDescription" )
563
+ }
564
+ }
565
+ }
547
566
def logProgressEvent (progressEvent : ProgressEvent ): Unit = {
548
567
if (logger.isDebugEnabled) {
549
568
progressEvent.getEventType match {
@@ -601,6 +620,35 @@ object FutureTransfer {
601
620
602
621
val p = Promise [transfer.type ]
603
622
623
+ if (transfer.isInstanceOf [AbstractTransfer ]) {
624
+ /* Attach a state change listener to the transfer.
625
+ * At this point, the transfer is already in progress
626
+ * and may even have already completed. We will have
627
+ * missed any state change events that have already been
628
+ * fired, including the completion event!
629
+ */
630
+ transfer.asInstanceOf [AbstractTransfer ].addStateChangeListener(new TransferStateChangeListener {
631
+ /* Note that the transferStateChanged will be called in the Java SDK’s
632
+ * special thread for callbacks, so any blocking calls here have
633
+ * the potential to induce deadlock.
634
+ */
635
+ override def transferStateChanged (t : Transfer , state : Transfer .TransferState ): Unit = {
636
+ logTransferState(state)
637
+
638
+ if (state == Transfer .TransferState .Completed ||
639
+ state == Transfer .TransferState .Canceled ||
640
+ state == Transfer .TransferState .Failed ) {
641
+ val success = p trySuccess transfer
642
+ if (logger.isDebugEnabled) {
643
+ if (success) {
644
+ logger.debug(s " promise successfully completed from transfer state change listener for $transferDescription" )
645
+ }
646
+ }
647
+ }
648
+ }
649
+ })
650
+ }
651
+
604
652
/* Attach a progress listener to the transfer.
605
653
* At this point, the transfer is already in progress
606
654
* and may even have already completed. We will have
@@ -624,8 +672,6 @@ object FutureTransfer {
624
672
if (logger.isDebugEnabled) {
625
673
if (success) {
626
674
logger.debug(s " promise successfully completed from progress listener for $transferDescription" )
627
- } else {
628
- logger.debug(s " promise was found to be already completed from progress listener for $transferDescription" )
629
675
}
630
676
}
631
677
}
@@ -639,9 +685,7 @@ object FutureTransfer {
639
685
val success = p trySuccess transfer
640
686
if (logger.isDebugEnabled) {
641
687
if (success) {
642
- logger.debug(s " promise successfully completed outside of progress listener for $transferDescription" )
643
- } else {
644
- logger.debug(s " promise was found to be already completed outside of progress listener for $transferDescription" )
688
+ logger.debug(s " promise successfully completed from outside of callbacks for $transferDescription" )
645
689
}
646
690
}
647
691
}
0 commit comments