@@ -629,13 +629,29 @@ private enum ScoreTypeHeader
629
629
// ReSharper restore InconsistentNaming
630
630
// ReSharper restore UnusedMember.Local
631
631
632
- private MemoryStream CreateCache ( ILoadMonitor loader , IProgressStatus status , int percent )
632
+ /// <summary>
633
+ /// Read entries from the database and create a .slc file.
634
+ /// Returns true if successful, otherwise false.
635
+ /// <paramref name="memoryStream"/> will be set to
636
+ /// </summary>
637
+ private bool CreateCache ( ILoadMonitor loader , IProgressStatus status , int percent , out MemoryStream memoryStream )
633
638
{
634
- MemoryStream outStream ;
639
+ memoryStream = null ;
635
640
var sm = loader . StreamManager ;
636
641
EnsureConnections ( sm ) ;
637
- using ( SQLiteCommand select = new SQLiteCommand ( _sqliteConnection . Connection ) )
642
+ using FileSaver fs = new FileSaver ( CachePath , sm ) ;
643
+ Stream cacheFileStream = null ;
644
+ try
645
+ {
646
+ cacheFileStream = sm . CreateStream ( fs . SafeName , FileMode . Create , true ) ;
647
+ }
648
+ catch ( Exception )
638
649
{
650
+ // The cache will be entirely kept in memory if the file stream could not be created
651
+ }
652
+ using ( cacheFileStream )
653
+ {
654
+ using SQLiteCommand select = new SQLiteCommand ( _sqliteConnection . Connection ) ;
639
655
int rows ;
640
656
string lsid ;
641
657
int dataRev , schemaVer ;
@@ -741,14 +757,14 @@ private MemoryStream CreateCache(ILoadMonitor loader, IProgressStatus status, in
741
757
int rowsRead = 0 ;
742
758
while ( reader . Read ( ) )
743
759
{
744
- int percentComplete = rowsRead ++ * percent / rows ;
760
+ int percentComplete = rowsRead ++ * percent / rows ;
745
761
if ( status . PercentComplete != percentComplete )
746
762
{
747
763
// Check for cancellation after each integer change in percent loaded.
748
764
if ( loader . IsCanceled )
749
765
{
750
766
loader . UpdateProgress ( status . Cancel ( ) ) ;
751
- return null ;
767
+ return false ;
752
768
}
753
769
754
770
// If not cancelled, update progress.
@@ -877,10 +893,24 @@ private MemoryStream CreateCache(ILoadMonitor loader, IProgressStatus status, in
877
893
}
878
894
879
895
}
880
-
881
- outStream = new MemoryStream ( ) ;
896
+
897
+ // Start out writing to a memory stream
898
+ Stream outStream = memoryStream = new MemoryStream ( ) ;
899
+ // Write the memory stream out to disk when it gets bigger maxMemoryStreamSize
900
+ const long maxMemoryStreamSize = 10_000_000 ;
901
+
882
902
foreach ( var info in libraryEntries )
883
903
{
904
+ if ( cacheFileStream != null && memoryStream ? . Length > maxMemoryStreamSize )
905
+ {
906
+ // Write out the memory stream if it is too big and switch to using the file stream
907
+ memoryStream . Seek ( 0 , SeekOrigin . Begin ) ;
908
+ memoryStream . CopyTo ( cacheFileStream ) ;
909
+ outStream = cacheFileStream ;
910
+ // The memory stream is now incomplete and should not be used by the caller
911
+ memoryStream = null ;
912
+ }
913
+
884
914
// Write the spectrum header - order must match enum SpectrumCacheHeader
885
915
info . Key . Write ( outStream ) ;
886
916
outStream . Write ( BitConverter . GetBytes ( info . Copies ) , 0 , sizeof ( int ) ) ;
@@ -962,26 +992,31 @@ private MemoryStream CreateCache(ILoadMonitor loader, IProgressStatus status, in
962
992
outStream . Write ( BitConverter . GetBytes ( libraryEntries . Count ) , 0 , sizeof ( int ) ) ;
963
993
outStream . Write ( BitConverter . GetBytes ( sourcePosition ) , 0 , sizeof ( long ) ) ;
964
994
outStream . Write ( BitConverter . GetBytes ( scoreTypesPosition ) , 0 , sizeof ( long ) ) ;
965
- try
995
+ if ( cacheFileStream != null )
966
996
{
967
- using ( FileSaver fs = new FileSaver ( CachePath , sm ) )
968
- using ( Stream cacheFileStream = sm . CreateStream ( fs . SafeName , FileMode . Create , true ) )
997
+ if ( memoryStream != null )
998
+ {
999
+ memoryStream . Seek ( 0 , SeekOrigin . Begin ) ;
1000
+ memoryStream . CopyTo ( cacheFileStream ) ;
1001
+ }
1002
+ sm . Finish ( cacheFileStream ) ;
1003
+ try
969
1004
{
970
- outStream . Seek ( 0 , SeekOrigin . Begin ) ;
971
- outStream . CopyTo ( cacheFileStream ) ;
972
- sm . Finish ( cacheFileStream ) ;
973
1005
fs . Commit ( ) ;
974
1006
sm . SetCache ( FilePath , CachePath ) ;
975
1007
}
976
- }
977
- catch
978
- {
979
- // ignore
1008
+ catch
1009
+ {
1010
+ // failure to commit the FileSaver can be ignored if we still have the memoryStream
1011
+ if ( memoryStream == null )
1012
+ {
1013
+ throw ;
1014
+ }
1015
+ }
980
1016
}
981
1017
}
982
-
983
1018
loader . UpdateProgress ( status . Complete ( ) ) ;
984
- return outStream ;
1019
+ return true ;
985
1020
}
986
1021
987
1022
private Dictionary < int , string > ProteinsBySpectraID ( )
@@ -1057,12 +1092,10 @@ private bool Load(ILoadMonitor loader, IProgressStatus status, bool cached)
1057
1092
status = status . ChangePercentComplete ( 0 ) ;
1058
1093
loader . UpdateProgress ( status ) ;
1059
1094
1060
- cacheBytes = CreateCache ( loader , status , 100 - loadPercent ) ;
1061
- if ( cacheBytes == null )
1095
+ if ( ! CreateCache ( loader , status , 100 - loadPercent , out cacheBytes ) )
1062
1096
{
1063
1097
return false ;
1064
1098
}
1065
-
1066
1099
}
1067
1100
1068
1101
status = status . ChangeMessage ( string . Format ( LibResources . BiblioSpecLiteLibraryLoadLoading__0__library ,
0 commit comments