2020import static java .net .HttpURLConnection .HTTP_NOT_FOUND ;
2121
2222import com .google .api .core .BetaApi ;
23+ import com .google .api .core .InternalApi ;
2324import com .google .api .services .bigquery .model .GetQueryResultsResponse ;
2425import com .google .api .services .bigquery .model .JobConfigurationQuery ;
2526import com .google .api .services .bigquery .model .QueryParameter ;
@@ -496,6 +497,38 @@ void parseRpcDataAsync(
496497 queryTaskExecutor .execute (parseDataTask );
497498 }
498499
500+ /**
501+ * This method is called when the current thread is interrupted, this communicates to ResultSet by
502+ * adding a EoS
503+ *
504+ * @param buffer
505+ */
506+ @ InternalApi
507+ void markEoS (BlockingQueue <AbstractList <FieldValue >> buffer ) { // package-private
508+ try {
509+ buffer .put (new EndOfFieldValueList ()); // All the pages has been processed, put this marker
510+ } catch (InterruptedException e ) {
511+ logger .log (Level .WARNING , "\n " + Thread .currentThread ().getName () + " Interrupted" , e );
512+ }
513+ }
514+
515+ /**
516+ * This method is called when the current thread is interrupted, this communicates to ResultSet by
517+ * adding a isLast Row
518+ *
519+ * @param buffer
520+ */
521+ @ InternalApi
522+ void markLast (BlockingQueue <BigQueryResultImpl .Row > buffer ) { // package-private
523+ try {
524+ buffer .put (
525+ new BigQueryResultImpl .Row (
526+ null , true )); // All the pages has been processed, put this marker
527+ } catch (InterruptedException e ) {
528+ logger .log (Level .WARNING , "\n " + Thread .currentThread ().getName () + " Interrupted" , e );
529+ }
530+ }
531+
499532 @ VisibleForTesting
500533 void populateBufferAsync (
501534 BlockingQueue <Tuple <TableDataList , Boolean >> rpcResponseQueue ,
@@ -516,18 +549,25 @@ void populateBufferAsync(
516549 "\n " + Thread .currentThread ().getName () + " Interrupted" ,
517550 e ); // Thread might get interrupted while calling the Cancel method, which is
518551 // expected, so logging this instead of throwing the exception back
552+ markEoS (
553+ buffer ); // Thread has been interrupted, communicate to ResultSet by adding EoS
519554 }
520555
521556 if (Thread .currentThread ().isInterrupted ()
522557 || fieldValueLists
523558 == null ) { // do not process further pages and shutdown (outerloop)
559+ markEoS (
560+ buffer ); // Thread has been interrupted, communicate to ResultSet by adding EoS
524561 break ;
525562 }
526563
527564 for (FieldValueList fieldValueList : fieldValueLists ) {
528565 try {
529566 if (Thread .currentThread ()
530567 .isInterrupted ()) { // do not process further pages and shutdown (inner loop)
568+ markEoS (
569+ buffer ); // Thread has been interrupted, communicate to ResultSet by adding
570+ // EoS
531571 break ;
532572 }
533573 buffer .put (fieldValueList );
@@ -537,19 +577,15 @@ void populateBufferAsync(
537577 }
538578 }
539579
540- if (Thread .currentThread ()
541- .isInterrupted ()) { // clear the buffer for any outstanding records
542- buffer .clear ();
543- rpcResponseQueue
544- .clear (); // IMP - so that if it's full then it unblocks and the interrupt logic
545- // could trigger
546- }
547-
548580 try {
549- buffer .put (
550- new EndOfFieldValueList ()); // All the pages has been processed, put this marker
551- } catch (InterruptedException e ) {
552- throw new BigQueryException (0 , e .getMessage (), e );
581+ if (Thread .currentThread ()
582+ .isInterrupted ()) { // clear the buffer for any outstanding records
583+ rpcResponseQueue
584+ .clear (); // IMP - so that if it's full then it unblocks and the interrupt logic
585+ // could trigger
586+ buffer .clear ();
587+ }
588+ markEoS (buffer ); // All the pages has been processed, put this marker
553589 } finally {
554590 queryTaskExecutor .shutdownNow (); // Shutdown the thread pool
555591 }
@@ -790,12 +826,8 @@ private void processArrowStreamAsync(
790826 } catch (Exception e ) {
791827 throw BigQueryException .translateAndThrow (e );
792828 } finally {
793- try {
794- buffer .put (new BigQueryResultImpl .Row (null , true )); // marking end of stream
795- queryTaskExecutor .shutdownNow (); // Shutdown the thread pool
796- } catch (InterruptedException e ) {
797- logger .log (Level .WARNING , "\n Error occurred " , e );
798- }
829+ markLast (buffer ); // marking end of stream
830+ queryTaskExecutor .shutdownNow (); // Shutdown the thread pool
799831 }
800832 };
801833
@@ -856,6 +888,7 @@ private void processRows(
856888
857889 if (Thread .currentThread ().isInterrupted ()
858890 || queryTaskExecutor .isShutdown ()) { // do not process and shutdown
891+ markLast (buffer ); // puts an isLast Row in the buffer for ResultSet to process
859892 break ; // exit the loop, root will be cleared in the finally block
860893 }
861894
@@ -869,9 +902,7 @@ private void processRows(
869902 }
870903 buffer .put (new BigQueryResultImpl .Row (curRow ));
871904 }
872- root .clear (); // TODO: make sure to clear the root while implementing the thread
873- // interruption logic (Connection.close method)
874-
905+ root .clear ();
875906 } catch (RuntimeException | InterruptedException e ) {
876907 throw BigQueryException .translateAndThrow (e );
877908 } finally {
0 commit comments