~ubuntu-branches/ubuntu/jaunty/beagle/jaunty-security

« back to all changes in this revision

Viewing changes to beagled/Lucene.Net/Index/SegmentInfos.cs

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Ebner
  • Date: 2008-05-04 00:31:32 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20080504003132-2tkm5o8moo5952ri
Tags: 0.3.7-2ubuntu1
 * Merge from Debian unstable. (LP: #225746) Remaining Ubuntu changes:
  - debian/control:
    + Rename ice{weasel,dove}-beagle to {mozilla,thunderbird}-beagle and
      and update the dependencies accordingly.
    + Change Maintainer to Ubuntu Mono Team.
  - debian/rules:
    + Install the mozilla-beagle and thunderbird-beagle extensions.
  - ice{dove,weasel}.dirs:
    + Renamed to {mozilla,thunderbird}-beagle.dirs.
    + Fixed paths to point to usr/lib/{firefox,thunderbird}

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright 2004 The Apache Software Foundation
3
 
 * 
4
 
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 
 * you may not use this file except in compliance with the License.
6
 
 * You may obtain a copy of the License at
 
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
 
3
 * contributor license agreements.  See the NOTICE file distributed with
 
4
 * this work for additional information regarding copyright ownership.
 
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
6
 * (the "License"); you may not use this file except in compliance with
 
7
 * the License.  You may obtain a copy of the License at
7
8
 * 
8
9
 * http://www.apache.org/licenses/LICENSE-2.0
9
10
 * 
18
19
using Directory = Lucene.Net.Store.Directory;
19
20
using IndexInput = Lucene.Net.Store.IndexInput;
20
21
using IndexOutput = Lucene.Net.Store.IndexOutput;
21
 
using Constants = Lucene.Net.Util.Constants;
22
22
 
23
23
namespace Lucene.Net.Index
24
24
{
26
26
        [Serializable]
27
27
        public sealed class SegmentInfos : System.Collections.ArrayList
28
28
        {
 
29
                private class AnonymousClassFindSegmentsFile:FindSegmentsFile
 
30
                {
 
31
                        private void  InitBlock(SegmentInfos enclosingInstance)
 
32
                        {
 
33
                                this.enclosingInstance = enclosingInstance;
 
34
                        }
 
35
                        private SegmentInfos enclosingInstance;
 
36
                        public SegmentInfos Enclosing_Instance
 
37
                        {
 
38
                                get
 
39
                                {
 
40
                                        return enclosingInstance;
 
41
                                }
 
42
                                
 
43
                        }
 
44
                        internal AnonymousClassFindSegmentsFile(SegmentInfos enclosingInstance, Lucene.Net.Store.Directory Param1):base(Param1)
 
45
                        {
 
46
                                InitBlock(enclosingInstance);
 
47
                        }
 
48
                        
 
49
                        public override System.Object DoBody(System.String segmentFileName)
 
50
                        {
 
51
                                Enclosing_Instance.Read(directory, segmentFileName);
 
52
                                return null;
 
53
                        }
 
54
                }
 
55
                private class AnonymousClassFindSegmentsFile1:FindSegmentsFile
 
56
                {
 
57
                        internal AnonymousClassFindSegmentsFile1(Lucene.Net.Store.Directory Param1):base(Param1)
 
58
                        {
 
59
                        }
 
60
                        public override System.Object DoBody(System.String segmentFileName)
 
61
                        {
 
62
                                
 
63
                                IndexInput input = directory.OpenInput(segmentFileName);
 
64
                                
 
65
                                int format = 0;
 
66
                                long version = 0;
 
67
                                try
 
68
                                {
 
69
                                        format = input.ReadInt();
 
70
                                        if (format < 0)
 
71
                                        {
 
72
                                                if (format < Lucene.Net.Index.SegmentInfos.FORMAT_SINGLE_NORM_FILE)
 
73
                                                        throw new System.IO.IOException("Unknown format version: " + format);
 
74
                                                version = input.ReadLong(); // read version
 
75
                                        }
 
76
                                }
 
77
                                finally
 
78
                                {
 
79
                                        input.Close();
 
80
                                }
 
81
                                
 
82
                                if (format < 0)
 
83
                                        return (long) version;
 
84
                                
 
85
                                // We cannot be sure about the format of the file.
 
86
                                // Therefore we have to read the whole file and cannot simply seek to the version entry.
 
87
                                SegmentInfos sis = new SegmentInfos();
 
88
                                sis.Read(directory, segmentFileName);
 
89
                                return (long) sis.GetVersion();
 
90
                        }
 
91
                }
29
92
                
30
93
                /// <summary>The file format version, a negative number. </summary>
31
94
                /* Works since counter, the old 1st entry, is always >= 0 */
32
95
                public const int FORMAT = - 1;
33
96
                
 
97
                /// <summary>This format adds details used for lockless commits.  It differs
 
98
                /// slightly from the previous format in that file names
 
99
                /// are never re-used (write once).  Instead, each file is
 
100
                /// written to the next generation.  For example,
 
101
                /// segments_1, segments_2, etc.  This allows us to not use
 
102
                /// a commit lock.  See <a
 
103
                /// href="http://lucene.apache.org/java/docs/fileformats.html">file
 
104
                /// formats</a> for details.
 
105
                /// </summary>
 
106
                public const int FORMAT_LOCKLESS = - 2;
 
107
                
 
108
                /// <summary>This is the current file format written.  It adds a
 
109
                /// "hasSingleNormFile" flag into each segment info.
 
110
                /// See <a href="http://issues.apache.org/jira/browse/LUCENE-756">LUCENE-756</a>
 
111
                /// for details.
 
112
                /// </summary>
 
113
                public const int FORMAT_SINGLE_NORM_FILE = - 3;
 
114
                
34
115
                public int counter = 0; // used to name new segments
35
116
                /// <summary> counts how often the index has been changed by adding or deleting docs.
36
117
                /// starting with the current time in milliseconds forces to create unique version numbers.
37
118
                /// </summary>
38
 
                private long version = System.DateTime.Now.Ticks;
 
119
                private long version = System.DateTime.Now.Millisecond;
 
120
                
 
121
                private long generation = 0; // generation of the "segments_N" for the next commit
 
122
                private long lastGeneration = 0; // generation of the "segments_N" file we last successfully read
 
123
                // or wrote; this is normally the same as generation except if
 
124
                // there was an IOException that had interrupted a commit
 
125
                
 
126
                /// <summary> If non-null, information about loading segments_N files</summary>
 
127
                /// <seealso cref="#setInfoStream.">
 
128
                /// </seealso>
 
129
                private static System.IO.TextWriter infoStream;
39
130
                
40
131
                public SegmentInfo Info(int i)
41
132
                {
42
133
                        return (SegmentInfo) this[i];
43
134
                }
44
135
                
45
 
                public void  Read(Directory directory)
46
 
                {
47
 
                        
48
 
                        IndexInput input = directory.OpenInput(IndexFileNames.SEGMENTS);
 
136
                /// <summary> Get the generation (N) of the current segments_N file
 
137
                /// from a list of files.
 
138
                /// 
 
139
                /// </summary>
 
140
                /// <param name="files">-- array of file names to check
 
141
                /// </param>
 
142
                public static long GetCurrentSegmentGeneration(System.String[] files)
 
143
                {
 
144
                        if (files == null)
 
145
                        {
 
146
                                return - 1;
 
147
                        }
 
148
                        long max = - 1;
 
149
                        int prefixLen = IndexFileNames.SEGMENTS.Length + 1;
 
150
                        for (int i = 0; i < files.Length; i++)
 
151
                        {
 
152
                                System.String file = System.IO.Path.GetFileName(files[i]);
 
153
                                if (file.StartsWith(IndexFileNames.SEGMENTS) && !file.Equals(IndexFileNames.SEGMENTS_GEN))
 
154
                                {
 
155
                                        if (file.Equals(IndexFileNames.SEGMENTS))
 
156
                                        {
 
157
                                                // Pre lock-less commits:
 
158
                                                if (max == - 1)
 
159
                                                {
 
160
                                                        max = 0;
 
161
                                                }
 
162
                                        }
 
163
                                        else
 
164
                                        {
 
165
#if !PRE_LUCENE_NET_2_0_0_COMPATIBLE
 
166
                        long v = Lucene.Net.Documents.NumberTools.ToLong(file.Substring(prefixLen));
 
167
#else
 
168
                                                long v = System.Convert.ToInt64(file.Substring(prefixLen), 16);
 
169
#endif
 
170
                                                if (v > max)
 
171
                                                {
 
172
                                                        max = v;
 
173
                                                }
 
174
                                        }
 
175
                                }
 
176
                        }
 
177
                        return max;
 
178
                }
 
179
                
 
180
                /// <summary> Get the generation (N) of the current segments_N file
 
181
                /// in the directory.
 
182
                /// 
 
183
                /// </summary>
 
184
                /// <param name="directory">-- directory to search for the latest segments_N file
 
185
                /// </param>
 
186
                public static long GetCurrentSegmentGeneration(Directory directory)
 
187
                {
 
188
                        System.String[] files = directory.List();
 
189
                        if (files == null)
 
190
                        {
 
191
                                throw new System.IO.IOException("Cannot read directory " + directory);
 
192
                        }
 
193
                        return GetCurrentSegmentGeneration(files);
 
194
                }
 
195
                
 
196
                /// <summary> Get the filename of the current segments_N file
 
197
                /// from a list of files.
 
198
                /// 
 
199
                /// </summary>
 
200
                /// <param name="files">-- array of file names to check
 
201
                /// </param>
 
202
                
 
203
                public static System.String GetCurrentSegmentFileName(System.String[] files)
 
204
                {
 
205
                        return IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", GetCurrentSegmentGeneration(files));
 
206
                }
 
207
                
 
208
                /// <summary> Get the filename of the current segments_N file
 
209
                /// in the directory.
 
210
                /// 
 
211
                /// </summary>
 
212
                /// <param name="directory">-- directory to search for the latest segments_N file
 
213
                /// </param>
 
214
                public static System.String GetCurrentSegmentFileName(Directory directory)
 
215
                {
 
216
                        return IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", GetCurrentSegmentGeneration(directory));
 
217
                }
 
218
                
 
219
                /// <summary> Get the segments_N filename in use by this segment infos.</summary>
 
220
                public System.String GetCurrentSegmentFileName()
 
221
                {
 
222
                        return IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", lastGeneration);
 
223
                }
 
224
                
 
225
                /// <summary> Get the next segments_N filename that will be written.</summary>
 
226
                public System.String GetNextSegmentFileName()
 
227
                {
 
228
                        long nextGeneration;
 
229
                        
 
230
                        if (generation == - 1)
 
231
                        {
 
232
                                nextGeneration = 1;
 
233
                        }
 
234
                        else
 
235
                        {
 
236
                                nextGeneration = generation + 1;
 
237
                        }
 
238
                        return IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", nextGeneration);
 
239
                }
 
240
                
 
241
                /// <summary> Read a particular segmentFileName.  Note that this may
 
242
                /// throw an IOException if a commit is in process.
 
243
                /// 
 
244
                /// </summary>
 
245
                /// <param name="directory">-- directory containing the segments file
 
246
                /// </param>
 
247
                /// <param name="segmentFileName">-- segment file to load
 
248
                /// </param>
 
249
                public void  Read(Directory directory, System.String segmentFileName)
 
250
                {
 
251
                        bool success = false;
 
252
                        
 
253
                        IndexInput input = directory.OpenInput(segmentFileName);
 
254
                        
 
255
                        if (segmentFileName.Equals(IndexFileNames.SEGMENTS))
 
256
                        {
 
257
                                generation = 0;
 
258
                        }
 
259
                        else
 
260
                        {
 
261
#if !PRE_LUCENE_NET_2_0_0_COMPATIBLE
 
262
                generation = Lucene.Net.Documents.NumberTools.ToLong(segmentFileName.Substring(1 + IndexFileNames.SEGMENTS.Length));
 
263
#else
 
264
                                generation = System.Convert.ToInt64(segmentFileName.Substring(1 + IndexFileNames.SEGMENTS.Length), 16);
 
265
#endif
 
266
                        }
 
267
                        lastGeneration = generation;
 
268
                        
49
269
                        try
50
270
                        {
51
271
                                int format = input.ReadInt();
53
273
                                {
54
274
                                        // file contains explicit format info
55
275
                                        // check that it is a format we can understand
56
 
                                        if (format < FORMAT)
 
276
                                        if (format < FORMAT_SINGLE_NORM_FILE)
57
277
                                                throw new System.IO.IOException("Unknown format version: " + format);
58
278
                                        version = input.ReadLong(); // read version
59
279
                                        counter = input.ReadInt(); // read counter
67
287
                                for (int i = input.ReadInt(); i > 0; i--)
68
288
                                {
69
289
                                        // read segmentInfos
70
 
                                        SegmentInfo si = new SegmentInfo(input.ReadString(), input.ReadInt(), directory);
71
 
                                        Add(si);
 
290
                                        Add(new SegmentInfo(directory, format, input));
72
291
                                }
73
292
                                
74
293
                                if (format >= 0)
75
294
                                {
76
295
                                        // in old format the version number may be at the end of the file
77
296
                                        if (input.GetFilePointer() >= input.Length())
78
 
                                                version = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
 
297
                                                version = System.DateTime.Now.Millisecond;
79
298
                                        // old file format without version number
80
299
                                        else
81
300
                                                version = input.ReadLong(); // read version
82
301
                                }
 
302
                                success = true;
83
303
                        }
84
304
                        finally
85
305
                        {
86
306
                                input.Close();
 
307
                                if (!success)
 
308
                                {
 
309
                                        // Clear any segment infos we had loaded so we
 
310
                                        // have a clean slate on retry:
 
311
                                        Clear();
 
312
                                }
87
313
                        }
88
314
                }
 
315
                /// <summary> This version of read uses the retry logic (for lock-less
 
316
                /// commits) to find the right segments file to load.
 
317
                /// </summary>
 
318
                public void  Read(Directory directory)
 
319
                {
 
320
                        
 
321
                        generation = lastGeneration = - 1;
 
322
                        
 
323
                        new AnonymousClassFindSegmentsFile(this, directory).run();
 
324
                }
89
325
                
90
326
                public void  Write(Directory directory)
91
327
                {
92
 
                        IndexOutput output = directory.CreateOutput("segments.new");
 
328
                        
 
329
                        System.String segmentFileName = GetNextSegmentFileName();
 
330
                        
 
331
                        // Always advance the generation on write:
 
332
                        if (generation == - 1)
 
333
                        {
 
334
                                generation = 1;
 
335
                        }
 
336
                        else
 
337
                        {
 
338
                                generation++;
 
339
                        }
 
340
                        
 
341
                        IndexOutput output = directory.CreateOutput(segmentFileName);
 
342
                        
93
343
                        try
94
344
                        {
95
 
                                output.WriteInt(FORMAT); // write FORMAT
96
 
                                output.WriteLong(++version); // every write changes the index
 
345
                                output.WriteInt(FORMAT_SINGLE_NORM_FILE); // write FORMAT
 
346
                                output.WriteLong(++version); // every write changes
 
347
                                // the index
97
348
                                output.WriteInt(counter); // write counter
98
349
                                output.WriteInt(Count); // write infos
99
350
                                for (int i = 0; i < Count; i++)
100
351
                                {
101
 
                                        SegmentInfo si = Info(i);
102
 
                                        output.WriteString(si.name);
103
 
                                        output.WriteInt(si.docCount);
 
352
                                        Info(i).Write(output);
104
353
                                }
105
354
                        }
106
355
                        finally
108
357
                                output.Close();
109
358
                        }
110
359
                        
111
 
                        // install new segment info
112
 
                        directory.RenameFile("segments.new", IndexFileNames.SEGMENTS);
 
360
                        try
 
361
                        {
 
362
                                output = directory.CreateOutput(IndexFileNames.SEGMENTS_GEN);
 
363
                                try
 
364
                                {
 
365
                                        output.WriteInt(FORMAT_LOCKLESS);
 
366
                                        output.WriteLong(generation);
 
367
                                        output.WriteLong(generation);
 
368
                                }
 
369
                                finally
 
370
                                {
 
371
                                        output.Close();
 
372
                                }
 
373
                        }
 
374
                        catch (System.IO.IOException e)
 
375
                        {
 
376
                                // It's OK if we fail to write this file since it's
 
377
                                // used only as one of the retry fallbacks.
 
378
                        }
 
379
                        
 
380
                        lastGeneration = generation;
 
381
                }
 
382
                
 
383
                /// <summary> Returns a copy of this instance, also copying each
 
384
                /// SegmentInfo.
 
385
                /// </summary>
 
386
                
 
387
                public override System.Object Clone()
 
388
                {
 
389
                        SegmentInfos sis = new SegmentInfos();
 
390
 
 
391
                        // Copy Fields. const and static fields are ignored
 
392
                        sis.counter = this.counter;
 
393
                        sis.version = this.version;
 
394
                        sis.generation = this.generation;
 
395
                        sis.lastGeneration = this.lastGeneration;
 
396
 
 
397
                        for (int i = 0; i < this.Count; i++)
 
398
                        {
 
399
                                sis.Add(((SegmentInfo)this[i]).Clone());
 
400
                        }
 
401
                        return sis;
113
402
                }
114
403
                
115
404
                /// <summary> version number when this SegmentInfos was generated.</summary>
122
411
                public static long ReadCurrentVersion(Directory directory)
123
412
                {
124
413
                        
125
 
                        IndexInput input = directory.OpenInput(IndexFileNames.SEGMENTS);
126
 
                        int format = 0;
127
 
                        long version = 0;
128
 
                        try
129
 
                        {
130
 
                                format = input.ReadInt();
131
 
                                if (format < 0)
 
414
                        return (long) ((System.Int64) new AnonymousClassFindSegmentsFile1(directory).run());
 
415
                }
 
416
                
 
417
                /// <summary>If non-null, information about retries when loading
 
418
                /// the segments file will be printed to this.
 
419
                /// </summary>
 
420
                public static void  SetInfoStream(System.IO.TextWriter infoStream)
 
421
                {
 
422
                        SegmentInfos.infoStream = infoStream;
 
423
                }
 
424
                
 
425
                /* Advanced configuration of retry logic in loading
 
426
                segments_N file */
 
427
                private static int defaultGenFileRetryCount = 10;
 
428
                private static int defaultGenFileRetryPauseMsec = 50;
 
429
                private static int defaultGenLookaheadCount = 10;
 
430
                
 
431
                /// <summary> Advanced: set how many times to try loading the
 
432
                /// segments.gen file contents to determine current segment
 
433
                /// generation.  This file is only referenced when the
 
434
                /// primary method (listing the directory) fails.
 
435
                /// </summary>
 
436
                public static void  SetDefaultGenFileRetryCount(int count)
 
437
                {
 
438
                        defaultGenFileRetryCount = count;
 
439
                }
 
440
                
 
441
                /// <seealso cref="#setDefaultGenFileRetryCount">
 
442
                /// </seealso>
 
443
                public static int GetDefaultGenFileRetryCount()
 
444
                {
 
445
                        return defaultGenFileRetryCount;
 
446
                }
 
447
                
 
448
                /// <summary> Advanced: set how many milliseconds to pause in between
 
449
                /// attempts to load the segments.gen file.
 
450
                /// </summary>
 
451
                public static void  SetDefaultGenFileRetryPauseMsec(int msec)
 
452
                {
 
453
                        defaultGenFileRetryPauseMsec = msec;
 
454
                }
 
455
                
 
456
                /// <seealso cref="#setDefaultGenFileRetryPauseMsec">
 
457
                /// </seealso>
 
458
                public static int GetDefaultGenFileRetryPauseMsec()
 
459
                {
 
460
                        return defaultGenFileRetryPauseMsec;
 
461
                }
 
462
                
 
463
                /// <summary> Advanced: set how many times to try incrementing the
 
464
                /// gen when loading the segments file.  This only runs if
 
465
                /// the primary (listing directory) and secondary (opening
 
466
                /// segments.gen file) methods fail to find the segments
 
467
                /// file.
 
468
                /// </summary>
 
469
                public static void  SetDefaultGenLookaheadCount(int count)
 
470
                {
 
471
                        defaultGenLookaheadCount = count;
 
472
                }
 
473
                /// <seealso cref="#setDefaultGenLookaheadCount">
 
474
                /// </seealso>
 
475
                public static int GetDefaultGenLookahedCount()
 
476
                {
 
477
                        return defaultGenLookaheadCount;
 
478
                }
 
479
                
 
480
                /// <seealso cref="#setInfoStream">
 
481
                /// </seealso>
 
482
                public static System.IO.TextWriter GetInfoStream()
 
483
                {
 
484
                        return infoStream;
 
485
                }
 
486
                
 
487
                private static void  Message(System.String message)
 
488
                {
 
489
                        if (infoStream != null)
 
490
                        {
 
491
                                infoStream.WriteLine(SupportClass.ThreadClass.Current().Name + ": " + message);
 
492
                        }
 
493
                }
 
494
                
 
495
                /// <summary> Utility class for executing code that needs to do
 
496
                /// something with the current segments file.  This is
 
497
                /// necessary with lock-less commits because from the time
 
498
                /// you locate the current segments file name, until you
 
499
                /// actually open it, read its contents, or check modified
 
500
                /// time, etc., it could have been deleted due to a writer
 
501
                /// commit finishing.
 
502
                /// </summary>
 
503
                public abstract class FindSegmentsFile
 
504
                {
 
505
                        
 
506
                        internal System.IO.FileInfo fileDirectory;
 
507
                        internal Directory directory;
 
508
                        
 
509
                        public FindSegmentsFile(System.IO.FileInfo directory)
 
510
                        {
 
511
                                this.fileDirectory = directory;
 
512
                        }
 
513
                        
 
514
                        public FindSegmentsFile(Directory directory)
 
515
                        {
 
516
                                this.directory = directory;
 
517
                        }
 
518
                        
 
519
                        public System.Object run()
 
520
                        {
 
521
                                System.String segmentFileName = null;
 
522
                                long lastGen = - 1;
 
523
                                long gen = 0;
 
524
                                int genLookaheadCount = 0;
 
525
                                System.IO.IOException exc = null;
 
526
                                bool retry = false;
 
527
                                
 
528
                                int method = 0;
 
529
                                
 
530
                                // Loop until we succeed in calling doBody() without
 
531
                                // hitting an IOException.  An IOException most likely
 
532
                                // means a commit was in process and has finished, in
 
533
                                // the time it took us to load the now-old infos files
 
534
                                // (and segments files).  It's also possible it's a
 
535
                                // true error (corrupt index).  To distinguish these,
 
536
                                // on each retry we must see "forward progress" on
 
537
                                // which generation we are trying to load.  If we
 
538
                                // don't, then the original error is real and we throw
 
539
                                // it.
 
540
                                
 
541
                                // We have three methods for determining the current
 
542
                                // generation.  We try each in sequence.
 
543
                                
 
544
                                while (true)
132
545
                                {
133
 
                                        if (format < FORMAT)
134
 
                                                throw new System.IO.IOException("Unknown format version: " + format);
135
 
                                        version = input.ReadLong(); // read version
 
546
                                        
 
547
                                        // Method 1: list the directory and use the highest
 
548
                                        // segments_N file.  This method works well as long
 
549
                                        // as there is no stale caching on the directory
 
550
                                        // contents:
 
551
                                        System.String[] files = null;
 
552
                                        
 
553
                                        if (0 == method)
 
554
                                        {
 
555
                                                if (directory != null)
 
556
                                                {
 
557
                                                        files = directory.List();
 
558
                                                }
 
559
                                                else
 
560
                                                {
 
561
                                                        files = System.IO.Directory.GetFileSystemEntries(fileDirectory.FullName);
 
562
                            for (int i = 0; i < files.Length; i++)
 
563
                            {
 
564
                                files[i] = System.IO.Path.GetFileName (files[i]);
 
565
                            }
 
566
                        }
 
567
                                                
 
568
                                                gen = Lucene.Net.Index.SegmentInfos.GetCurrentSegmentGeneration(files);
 
569
                                                
 
570
                                                if (gen == - 1)
 
571
                                                {
 
572
                                                        System.String s = "";
 
573
                                                        for (int i = 0; i < files.Length; i++)
 
574
                                                        {
 
575
                                                                s += (" " + files[i]);
 
576
                                                        }
 
577
                                                        throw new System.IO.FileNotFoundException("no segments* file found: files:" + s);
 
578
                                                }
 
579
                                        }
 
580
                                        
 
581
                                        // Method 2 (fallback if Method 1 isn't reliable):
 
582
                                        // if the directory listing seems to be stale, then
 
583
                                        // try loading the "segments.gen" file.
 
584
                                        if (1 == method || (0 == method && lastGen == gen && retry))
 
585
                                        {
 
586
                                                
 
587
                                                method = 1;
 
588
                                                
 
589
                                                for (int i = 0; i < Lucene.Net.Index.SegmentInfos.defaultGenFileRetryCount; i++)
 
590
                                                {
 
591
                                                        IndexInput genInput = null;
 
592
                                                        try
 
593
                                                        {
 
594
                                                                genInput = directory.OpenInput(IndexFileNames.SEGMENTS_GEN);
 
595
                                                        }
 
596
                                                        catch (System.IO.IOException e)
 
597
                                                        {
 
598
                                                                Lucene.Net.Index.SegmentInfos.Message("segments.gen open: IOException " + e);
 
599
                                                        }
 
600
                                                        if (genInput != null)
 
601
                                                        {
 
602
                                                                
 
603
                                                                try
 
604
                                                                {
 
605
                                                                        int version = genInput.ReadInt();
 
606
                                                                        if (version == Lucene.Net.Index.SegmentInfos.FORMAT_LOCKLESS)
 
607
                                                                        {
 
608
                                                                                long gen0 = genInput.ReadLong();
 
609
                                                                                long gen1 = genInput.ReadLong();
 
610
                                                                                Lucene.Net.Index.SegmentInfos.Message("fallback check: " + gen0 + "; " + gen1);
 
611
                                                                                if (gen0 == gen1)
 
612
                                                                                {
 
613
                                                                                        // The file is consistent.
 
614
                                                                                        if (gen0 > gen)
 
615
                                                                                        {
 
616
                                                                                                Lucene.Net.Index.SegmentInfos.Message("fallback to '" + IndexFileNames.SEGMENTS_GEN + "' check: now try generation " + gen0 + " > " + gen);
 
617
                                                                                                gen = gen0;
 
618
                                                                                        }
 
619
                                                                                        break;
 
620
                                                                                }
 
621
                                                                        }
 
622
                                                                }
 
623
                                                                catch (System.IO.IOException err2)
 
624
                                                                {
 
625
                                                                        // will retry
 
626
                                                                }
 
627
                                                                finally
 
628
                                                                {
 
629
                                                                        genInput.Close();
 
630
                                                                }
 
631
                                                        }
 
632
                                                        try
 
633
                                                        {
 
634
                                                                System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * Lucene.Net.Index.SegmentInfos.defaultGenFileRetryPauseMsec));
 
635
                                                        }
 
636
                                                        catch (System.Threading.ThreadInterruptedException e)
 
637
                                                        {
 
638
                                                                // will retry
 
639
                                                        }
 
640
                                                }
 
641
                                        }
 
642
                                        
 
643
                                        // Method 3 (fallback if Methods 2 & 3 are not
 
644
                                        // reliable): since both directory cache and file
 
645
                                        // contents cache seem to be stale, just advance the
 
646
                                        // generation.
 
647
                                        if (2 == method || (1 == method && lastGen == gen && retry))
 
648
                                        {
 
649
                                                
 
650
                                                method = 2;
 
651
                                                
 
652
                                                if (genLookaheadCount < Lucene.Net.Index.SegmentInfos.defaultGenLookaheadCount)
 
653
                                                {
 
654
                                                        gen++;
 
655
                                                        genLookaheadCount++;
 
656
                                                        Lucene.Net.Index.SegmentInfos.Message("look ahead increment gen to " + gen);
 
657
                                                }
 
658
                                        }
 
659
                                        
 
660
                                        if (lastGen == gen)
 
661
                                        {
 
662
                                                
 
663
                                                // This means we're about to try the same
 
664
                                                // segments_N last tried.  This is allowed,
 
665
                                                // exactly once, because writer could have been in
 
666
                                                // the process of writing segments_N last time.
 
667
                                                
 
668
                                                if (retry)
 
669
                                                {
 
670
                                                        // OK, we've tried the same segments_N file
 
671
                                                        // twice in a row, so this must be a real
 
672
                                                        // error.  We throw the original exception we
 
673
                                                        // got.
 
674
                                                        throw exc;
 
675
                                                }
 
676
                                                else
 
677
                                                {
 
678
                                                        retry = true;
 
679
                                                }
 
680
                                        }
 
681
                                        else
 
682
                                        {
 
683
                                                // Segment file has advanced since our last loop, so
 
684
                                                // reset retry:
 
685
                                                retry = false;
 
686
                                        }
 
687
                                        
 
688
                                        lastGen = gen;
 
689
                                        
 
690
                                        segmentFileName = IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen);
 
691
                                        
 
692
                                        try
 
693
                                        {
 
694
                                                System.Object v = DoBody(segmentFileName);
 
695
                                                if (exc != null)
 
696
                                                {
 
697
                                                        Lucene.Net.Index.SegmentInfos.Message("success on " + segmentFileName);
 
698
                                                }
 
699
                                                return v;
 
700
                                        }
 
701
                                        catch (System.IO.IOException err)
 
702
                                        {
 
703
                                                
 
704
                                                // Save the original root cause:
 
705
                                                if (exc == null)
 
706
                                                {
 
707
                                                        exc = err;
 
708
                                                }
 
709
                                                
 
710
                                                Lucene.Net.Index.SegmentInfos.Message("primary Exception on '" + segmentFileName + "': " + err + "'; will retry: retry=" + retry + "; gen = " + gen);
 
711
                                                
 
712
                                                if (!retry && gen > 1)
 
713
                                                {
 
714
                                                        
 
715
                                                        // This is our first time trying this segments
 
716
                                                        // file (because retry is false), and, there is
 
717
                                                        // possibly a segments_(N-1) (because gen > 1).
 
718
                                                        // So, check if the segments_(N-1) exists and
 
719
                                                        // try it if so:
 
720
                                                        System.String prevSegmentFileName = IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen - 1);
 
721
                                                        
 
722
                                                        if (directory.FileExists(prevSegmentFileName))
 
723
                                                        {
 
724
                                                                Lucene.Net.Index.SegmentInfos.Message("fallback to prior segment file '" + prevSegmentFileName + "'");
 
725
                                                                try
 
726
                                                                {
 
727
                                                                        System.Object v = DoBody(prevSegmentFileName);
 
728
                                                                        if (exc != null)
 
729
                                                                        {
 
730
                                                                                Lucene.Net.Index.SegmentInfos.Message("success on fallback " + prevSegmentFileName);
 
731
                                                                        }
 
732
                                                                        return v;
 
733
                                                                }
 
734
                                                                catch (System.IO.IOException err2)
 
735
                                                                {
 
736
                                                                        Lucene.Net.Index.SegmentInfos.Message("secondary Exception on '" + prevSegmentFileName + "': " + err2 + "'; will retry");
 
737
                                                                }
 
738
                                                        }
 
739
                                                }
 
740
                                        }
136
741
                                }
137
742
                        }
138
 
                        finally
139
 
                        {
140
 
                                input.Close();
141
 
                        }
142
 
                        
143
 
                        if (format < 0)
144
 
                                return version;
145
 
                        
146
 
                        // We cannot be sure about the format of the file.
147
 
                        // Therefore we have to read the whole file and cannot simply seek to the version entry.
148
 
                        
149
 
                        SegmentInfos sis = new SegmentInfos();
150
 
                        sis.Read(directory);
151
 
                        return sis.GetVersion();
 
743
                        
 
744
                        /// <summary> Subclass must implement this.  The assumption is an
 
745
                        /// IOException will be thrown if something goes wrong
 
746
                        /// during the processing that could have been caused by
 
747
                        /// a writer committing.
 
748
                        /// </summary>
 
749
                        public abstract System.Object DoBody(System.String segmentFileName);
152
750
                }
153
751
 
154
752
                public void Optimize(Directory directory)
156
754
                        string[] files = directory.List();
157
755
 
158
756
                        System.Collections.ArrayList segment_names = new System.Collections.ArrayList();
 
757
 
159
758
                        foreach (SegmentInfo si in this)
160
759
                                segment_names.Add (si.name);
161
760
 
164
763
                                if (segment_names.Contains (basename))
165
764
                                        continue;
166
765
 
167
 
                                if (basename == IndexFileNames.DELETABLE || basename == IndexFileNames.SEGMENTS)
 
766
                                // Allowed files deletable, segments, segments.gen, segments_N
 
767
                                if (basename == IndexFileNames.DELETABLE || basename.StartsWith (IndexFileNames.SEGMENTS))
168
768
                                        continue;
169
769
 
170
770
                                Console.WriteLine ("WARNING! Deleting stale data {0}", file);
171
 
                                directory.DeleteFile (file);
 
771
                                try {
 
772
                                        directory.DeleteFile (file);
 
773
                                } catch { /* Could be already deleted. */ }
172
774
                        }
173
775
                }
174
776
        }