2121import java .io .Closeable ;
2222import java .io .File ;
2323import java .io .IOException ;
24+ import java .io .PrintStream ;
2425import java .net .MalformedURLException ;
2526import java .net .URL ;
2627import java .util .ArrayList ;
@@ -238,6 +239,7 @@ public static boolean isSyncServerAvailable() {
238239
239240 native long nativePanicModeRemoveAllObjects (long store , int entityId );
240241
242+ private final PrintStream errorOutputStream ;
241243 private final File directory ;
242244 private final String canonicalPath ;
243245 /** Reference to the native store. Should probably get through {@link #getNativeStore()} instead. */
@@ -283,6 +285,7 @@ public static boolean isSyncServerAvailable() {
283285 relinker = builder .relinker ;
284286 NativeLibraryLoader .ensureLoaded ();
285287
288+ errorOutputStream = builder .errorOutputStream ;
286289 directory = builder .directory ;
287290 canonicalPath = getCanonicalPath (directory );
288291 verifyNotAlreadyOpen (canonicalPath );
@@ -613,7 +616,7 @@ public Transaction beginTx() {
613616 // Because write TXs are typically not cached, initialCommitCount is not as relevant than for read TXs.
614617 int initialCommitCount = commitCount ;
615618 if (debugTxWrite ) {
616- System . out .println ("Begin TX with commit count " + initialCommitCount );
619+ getOutput () .println ("Begin TX with commit count " + initialCommitCount );
617620 }
618621 long nativeTx = nativeBeginTx (getNativeStore ());
619622 if (nativeTx == 0 ) throw new DbException ("Could not create native transaction" );
@@ -638,7 +641,7 @@ public Transaction beginReadTx() {
638641 // TODO add multithreaded test for this
639642 int initialCommitCount = commitCount ;
640643 if (debugTxRead ) {
641- System . out .println ("Begin read TX with commit count " + initialCommitCount );
644+ getOutput () .println ("Begin read TX with commit count " + initialCommitCount );
642645 }
643646 long nativeTx = nativeBeginReadTx (getNativeStore ());
644647 if (nativeTx == 0 ) throw new DbException ("Could not create native read transaction" );
@@ -698,7 +701,7 @@ public void close() {
698701 // Give open transactions some time to close (BoxStore.unregisterTransaction() calls notify),
699702 // 1000 ms should be long enough for most small operations and short enough to avoid ANRs on Android.
700703 if (hasActiveTransaction ()) {
701- System . out .println ("Briefly waiting for active transactions before closing the Store..." );
704+ getOutput () .println ("Briefly waiting for active transactions before closing the Store..." );
702705 try {
703706 // It is fine to hold a lock on BoxStore.this as well as BoxStore.unregisterTransaction()
704707 // only synchronizes on "transactions".
@@ -708,7 +711,7 @@ public void close() {
708711 // If interrupted, continue with releasing native resources
709712 }
710713 if (hasActiveTransaction ()) {
711- System . err .println ("Transactions are still active:"
714+ getErrorOutput () .println ("Transactions are still active:"
712715 + " ensure that all database operations are finished before closing the Store!" );
713716 }
714717 }
@@ -745,16 +748,16 @@ private void checkThreadTermination() {
745748 try {
746749 if (!threadPool .awaitTermination (1 , TimeUnit .SECONDS )) {
747750 int activeCount = Thread .activeCount ();
748- System . err .println ("Thread pool not terminated in time; printing stack traces..." );
751+ getErrorOutput () .println ("Thread pool not terminated in time; printing stack traces..." );
749752 Thread [] threads = new Thread [activeCount + 2 ];
750753 int count = Thread .enumerate (threads );
751754 for (int i = 0 ; i < count ; i ++) {
752- System . err .println ("Thread: " + threads [i ].getName ());
755+ getErrorOutput () .println ("Thread: " + threads [i ].getName ());
753756 Thread .dumpStack ();
754757 }
755758 }
756759 } catch (InterruptedException e ) {
757- e .printStackTrace ();
760+ e .printStackTrace (getErrorOutput () );
758761 }
759762 }
760763
@@ -894,7 +897,7 @@ void txCommitted(Transaction tx, @Nullable int[] entityTypeIdsAffected) {
894897 synchronized (txCommitCountLock ) {
895898 commitCount ++; // Overflow is OK because we check for equality
896899 if (debugTxWrite ) {
897- System . out .println ("TX committed. New commit count: " + commitCount + ", entity types affected: " +
900+ getOutput () .println ("TX committed. New commit count: " + commitCount + ", entity types affected: " +
898901 (entityTypeIdsAffected != null ? entityTypeIdsAffected .length : 0 ));
899902 }
900903 }
@@ -1013,10 +1016,10 @@ public <T> T callInReadTxWithRetry(Callable<T> callable, int attempts, int initi
10131016 String diagnose = diagnose ();
10141017 String message = attempt + " of " + attempts + " attempts of calling a read TX failed:" ;
10151018 if (logAndHeal ) {
1016- System . err .println (message );
1019+ getErrorOutput () .println (message );
10171020 e .printStackTrace ();
1018- System . err .println (diagnose );
1019- System . err .flush ();
1021+ getErrorOutput () .println (diagnose );
1022+ getErrorOutput () .flush ();
10201023
10211024 System .gc ();
10221025 System .runFinalization ();
@@ -1337,6 +1340,20 @@ public TxCallback<?> internalFailedReadTxAttemptCallback() {
13371340 return failedReadTxAttemptCallback ;
13381341 }
13391342
1343+ /**
1344+ * The output stream to print log messages to. Currently {@link System#out}.
1345+ */
1346+ private PrintStream getOutput () {
1347+ return System .out ;
1348+ }
1349+
1350+ /**
1351+ * The error output stream to print log messages to. This is {@link System#err} by default.
1352+ */
1353+ private PrintStream getErrorOutput () {
1354+ return errorOutputStream ;
1355+ }
1356+
13401357 void setDebugFlags (int debugFlags ) {
13411358 nativeSetDebugFlags (getNativeStore (), debugFlags );
13421359 }
0 commit comments