1
+ using System . Collections . Specialized ;
2
+ using System . IO ;
3
+ using System . Linq ;
4
+ using System . Web ;
5
+ using Lucene . Net . Analysis ;
6
+ using Lucene . Net . Index ;
7
+ using Lucene . Net . Store ;
8
+ using Umbraco . Core ;
9
+ using Umbraco . Core . IO ;
10
+ using Umbraco . Core . Logging ;
11
+ using Directory = System . IO . Directory ;
12
+
13
+ namespace UmbracoExamine . LocalStorage
14
+ {
15
+ internal class LocalTempStorageIndexer
16
+ {
17
+ private string _tempPath ;
18
+ public Lucene . Net . Store . Directory LuceneDirectory { get ; private set ; }
19
+ private static readonly object Locker = new object ( ) ;
20
+ public SnapshotDeletionPolicy Snapshotter { get ; private set ; }
21
+ private bool _syncStorage = false ;
22
+
23
+ public LocalTempStorageIndexer ( )
24
+ {
25
+ IndexDeletionPolicy policy = new KeepOnlyLastCommitDeletionPolicy ( ) ;
26
+ Snapshotter = new SnapshotDeletionPolicy ( policy ) ;
27
+ }
28
+
29
+ public void Initialize ( NameValueCollection config , string configuredPath , Lucene . Net . Store . Directory baseLuceneDirectory , Analyzer analyzer )
30
+ {
31
+ var codegenPath = HttpRuntime . CodegenDir ;
32
+
33
+ _tempPath = Path . Combine ( codegenPath , configuredPath . TrimStart ( '~' , '/' ) . Replace ( "/" , "\\ " ) ) ;
34
+
35
+ if ( config != null )
36
+ {
37
+ if ( config [ "syncTempStorage" ] != null )
38
+ {
39
+ var attempt = config [ "syncTempStorage" ] . TryConvertTo < bool > ( ) ;
40
+ if ( attempt )
41
+ {
42
+ _syncStorage = attempt . Result ;
43
+ }
44
+ }
45
+ }
46
+
47
+ InitializeLocalIndexAndDirectory ( baseLuceneDirectory , analyzer , configuredPath ) ;
48
+ }
49
+
50
+ private void InitializeLocalIndexAndDirectory ( Lucene . Net . Store . Directory baseLuceneDirectory , Analyzer analyzer , string configuredPath )
51
+ {
52
+ lock ( Locker )
53
+ {
54
+ if ( Directory . Exists ( _tempPath ) == false )
55
+ {
56
+ Directory . CreateDirectory ( _tempPath ) ;
57
+ }
58
+
59
+ //if we are syncing storage to the main file system to temp files, then sync from the main FS to our temp FS
60
+ if ( _syncStorage )
61
+ {
62
+ //copy index
63
+
64
+ using ( new IndexWriter (
65
+ //read from the underlying/default directory, not the temp codegen dir
66
+ baseLuceneDirectory ,
67
+ analyzer ,
68
+ Snapshotter ,
69
+ IndexWriter . MaxFieldLength . UNLIMITED ) )
70
+ {
71
+ try
72
+ {
73
+ var basePath = IOHelper . MapPath ( configuredPath ) ;
74
+
75
+ var commit = Snapshotter . Snapshot ( ) ;
76
+ var allSnapshotFiles = commit . GetFileNames ( ) . Concat ( new [ ] { commit . GetSegmentsFileName ( ) } ) . ToArray ( ) ;
77
+
78
+ var tempDir = new DirectoryInfo ( _tempPath ) ;
79
+
80
+ //Get all files in the temp storage that don't exist in the snapshot collection, we want to remove these
81
+ var toRemove = tempDir . GetFiles ( )
82
+ . Select ( x => x . Name )
83
+ . Except ( allSnapshotFiles ) ;
84
+
85
+ using ( var tempDirectory = new SimpleFSDirectory ( tempDir ) )
86
+ {
87
+ if ( IndexWriter . IsLocked ( tempDirectory ) == false )
88
+ {
89
+ foreach ( var file in toRemove )
90
+ {
91
+ try
92
+ {
93
+ File . Delete ( Path . Combine ( _tempPath , file ) ) ;
94
+ }
95
+ catch ( IOException ex )
96
+ {
97
+ LogHelper . Error < LocalTempStorageIndexer > ( "Could not delete index file, could not sync from main storage" , ex ) ;
98
+
99
+ //quit here and do not assign the lucene directory, this means that the app will now just be working from normal storage
100
+ return ;
101
+ }
102
+ }
103
+ }
104
+ else
105
+ {
106
+ LogHelper . Warn < LocalTempStorageIndexer > ( "Cannot sync index files from main storage, the index is currently locked" ) ;
107
+
108
+ //quit here and do not assign the lucene directory, this means that the app will now just be working from normal storage
109
+ return ;
110
+ }
111
+ }
112
+
113
+ foreach ( var fileName in allSnapshotFiles . Where ( f => f . IsNullOrWhiteSpace ( ) == false ) )
114
+ {
115
+ try
116
+ {
117
+ File . Copy (
118
+ Path . Combine ( basePath , "Index" , fileName ) ,
119
+ Path . Combine ( _tempPath , Path . GetFileName ( fileName ) ) , true ) ;
120
+ }
121
+ catch ( IOException ex )
122
+ {
123
+ LogHelper . Error < LocalTempStorageIndexer > ( "Could not copy index file, could not sync from main storage" , ex ) ;
124
+
125
+ //quit here and do not assign the lucene directory, this means that the app will now just be working from normal storage
126
+ return ;
127
+ }
128
+ }
129
+
130
+ }
131
+ finally
132
+ {
133
+ Snapshotter . Release ( ) ;
134
+ }
135
+ }
136
+
137
+ //create the custom lucene directory which will keep the main and temp FS's in sync
138
+
139
+ LuceneDirectory = new LocalTempStorageDirectory (
140
+ new DirectoryInfo ( _tempPath ) ,
141
+ baseLuceneDirectory ) ;
142
+ }
143
+ else
144
+ {
145
+ //just return a normal lucene directory that uses the codegen folder
146
+
147
+ LuceneDirectory = FSDirectory . Open ( new DirectoryInfo ( _tempPath ) ) ;
148
+ }
149
+
150
+ }
151
+ }
152
+ }
153
+ }
0 commit comments