Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / tools / monkeydoc / Lucene.Net / Lucene.Net / Index / SegmentInfo.cs
1 /* 
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
8  * 
9  * http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 using System;
19
20 using Directory = Mono.Lucene.Net.Store.Directory;
21 using IndexInput = Mono.Lucene.Net.Store.IndexInput;
22 using IndexOutput = Mono.Lucene.Net.Store.IndexOutput;
23 using BitVector = Mono.Lucene.Net.Util.BitVector;
24
25 namespace Mono.Lucene.Net.Index
26 {
27         
28         /// <summary> Information about a segment such as it's name, directory, and files related
29         /// to the segment.
30         /// 
31         /// * <p/><b>NOTE:</b> This API is new and still experimental
32         /// (subject to change suddenly in the next release)<p/>
33         /// </summary>
34         public sealed class SegmentInfo : System.ICloneable
35         {
36                 
37                 internal const int NO = - 1; // e.g. no norms; no deletes;
38                 internal const int YES = 1; // e.g. have norms; have deletes;
39                 internal const int CHECK_DIR = 0; // e.g. must check dir to see if there are norms/deletions
40                 internal const int WITHOUT_GEN = 0; // a file name that has no GEN in it. 
41                 
42                 public System.String name; // unique name in dir
43                 public int docCount; // number of docs in seg
44                 public Directory dir; // where segment resides
45                 
46                 private bool preLockless; // true if this is a segments file written before
47                 // lock-less commits (2.1)
48                 
49                 private long delGen; // current generation of del file; NO if there
50                 // are no deletes; CHECK_DIR if it's a pre-2.1 segment
51                 // (and we must check filesystem); YES or higher if
52                 // there are deletes at generation N
53                 
54                 private long[] normGen; // current generation of each field's norm file.
55                 // If this array is null, for lockLess this means no 
56                 // separate norms.  For preLockLess this means we must 
57                 // check filesystem. If this array is not null, its 
58                 // values mean: NO says this field has no separate  
59                 // norms; CHECK_DIR says it is a preLockLess segment and    
60                 // filesystem must be checked; >= YES says this field  
61                 // has separate norms with the specified generation
62                 
63                 private sbyte isCompoundFile; // NO if it is not; YES if it is; CHECK_DIR if it's
64                 // pre-2.1 (ie, must check file system to see
65                 // if <name>.cfs and <name>.nrm exist)         
66                 
67                 private bool hasSingleNormFile; // true if this segment maintains norms in a single file; 
68                 // false otherwise
69                 // this is currently false for segments populated by DocumentWriter
70                 // and true for newly created merged segments (both
71                 // compound and non compound).
72                 
73                 private System.Collections.Generic.IList<string> files; // cached list of files that this segment uses
74                 // in the Directory
75                 
76                 internal long sizeInBytes = - 1; // total byte size of all of our files (computed on demand)
77                 
78                 private int docStoreOffset; // if this segment shares stored fields & vectors, this
79                 // offset is where in that file this segment's docs begin
80                 private System.String docStoreSegment; // name used to derive fields/vectors file we share with
81                 // other segments
82                 private bool docStoreIsCompoundFile; // whether doc store files are stored in compound file (*.cfx)
83                 
84                 private int delCount; // How many deleted docs in this segment, or -1 if not yet known
85                 // (if it's an older index)
86                 
87                 private bool hasProx; // True if this segment has any fields with omitTermFreqAndPositions==false
88
89         private System.Collections.Generic.IDictionary<string, string> diagnostics;
90                 
91                 public override System.String ToString()
92                 {
93                         return "si: " + dir.ToString() + " " + name + " docCount: " + docCount + " delCount: " + delCount + " delFileName: " + GetDelFileName();
94                 }
95                 
96                 public SegmentInfo(System.String name, int docCount, Directory dir)
97                 {
98                         this.name = name;
99                         this.docCount = docCount;
100                         this.dir = dir;
101                         delGen = NO;
102                         isCompoundFile = (sbyte) (CHECK_DIR);
103                         preLockless = true;
104                         hasSingleNormFile = false;
105                         docStoreOffset = - 1;
106                         docStoreSegment = name;
107                         docStoreIsCompoundFile = false;
108                         delCount = 0;
109                         hasProx = true;
110                 }
111                 
112                 public SegmentInfo(System.String name, int docCount, Directory dir, bool isCompoundFile, bool hasSingleNormFile):this(name, docCount, dir, isCompoundFile, hasSingleNormFile, - 1, null, false, true)
113                 {
114                 }
115                 
116                 public SegmentInfo(System.String name, int docCount, Directory dir, bool isCompoundFile, bool hasSingleNormFile, int docStoreOffset, System.String docStoreSegment, bool docStoreIsCompoundFile, bool hasProx):this(name, docCount, dir)
117                 {
118                         this.isCompoundFile = (sbyte) (isCompoundFile?YES:NO);
119                         this.hasSingleNormFile = hasSingleNormFile;
120                         preLockless = false;
121                         this.docStoreOffset = docStoreOffset;
122                         this.docStoreSegment = docStoreSegment;
123                         this.docStoreIsCompoundFile = docStoreIsCompoundFile;
124                         this.hasProx = hasProx;
125                         delCount = 0;
126                         System.Diagnostics.Debug.Assert(docStoreOffset == - 1 || docStoreSegment != null, "dso=" + docStoreOffset + " dss=" + docStoreSegment + " docCount=" + docCount);
127                 }
128                 
129                 /// <summary> Copy everything from src SegmentInfo into our instance.</summary>
130                 internal void  Reset(SegmentInfo src)
131                 {
132                         ClearFiles();
133                         name = src.name;
134                         docCount = src.docCount;
135                         dir = src.dir;
136                         preLockless = src.preLockless;
137                         delGen = src.delGen;
138                         docStoreOffset = src.docStoreOffset;
139                         docStoreIsCompoundFile = src.docStoreIsCompoundFile;
140                         if (src.normGen == null)
141                         {
142                                 normGen = null;
143                         }
144                         else
145                         {
146                                 normGen = new long[src.normGen.Length];
147                                 Array.Copy(src.normGen, 0, normGen, 0, src.normGen.Length);
148                         }
149                         isCompoundFile = src.isCompoundFile;
150                         hasSingleNormFile = src.hasSingleNormFile;
151                         delCount = src.delCount;
152                 }
153                 
154                 // must be Map<String, String>
155         internal void SetDiagnostics(System.Collections.Generic.IDictionary<string, string> diagnostics)
156                 {
157                         this.diagnostics = diagnostics;
158                 }
159                 
160                 // returns Map<String, String>
161         public System.Collections.Generic.IDictionary<string, string> GetDiagnostics()
162                 {
163                         return diagnostics;
164                 }
165                 
166                 /// <summary> Construct a new SegmentInfo instance by reading a
167                 /// previously saved SegmentInfo from input.
168                 /// 
169                 /// </summary>
170                 /// <param name="dir">directory to load from
171                 /// </param>
172                 /// <param name="format">format of the segments info file
173                 /// </param>
174                 /// <param name="input">input handle to read segment info from
175                 /// </param>
176                 internal SegmentInfo(Directory dir, int format, IndexInput input)
177                 {
178                         this.dir = dir;
179                         name = input.ReadString();
180                         docCount = input.ReadInt();
181                         if (format <= SegmentInfos.FORMAT_LOCKLESS)
182                         {
183                                 delGen = input.ReadLong();
184                                 if (format <= SegmentInfos.FORMAT_SHARED_DOC_STORE)
185                                 {
186                                         docStoreOffset = input.ReadInt();
187                                         if (docStoreOffset != - 1)
188                                         {
189                                                 docStoreSegment = input.ReadString();
190                                                 docStoreIsCompoundFile = (1 == input.ReadByte());
191                                         }
192                                         else
193                                         {
194                                                 docStoreSegment = name;
195                                                 docStoreIsCompoundFile = false;
196                                         }
197                                 }
198                                 else
199                                 {
200                                         docStoreOffset = - 1;
201                                         docStoreSegment = name;
202                                         docStoreIsCompoundFile = false;
203                                 }
204                                 if (format <= SegmentInfos.FORMAT_SINGLE_NORM_FILE)
205                                 {
206                                         hasSingleNormFile = (1 == input.ReadByte());
207                                 }
208                                 else
209                                 {
210                                         hasSingleNormFile = false;
211                                 }
212                                 int numNormGen = input.ReadInt();
213                                 if (numNormGen == NO)
214                                 {
215                                         normGen = null;
216                                 }
217                                 else
218                                 {
219                                         normGen = new long[numNormGen];
220                                         for (int j = 0; j < numNormGen; j++)
221                                         {
222                                                 normGen[j] = input.ReadLong();
223                                         }
224                                 }
225                                 isCompoundFile = (sbyte) input.ReadByte();
226                                 preLockless = (isCompoundFile == CHECK_DIR);
227                                 if (format <= SegmentInfos.FORMAT_DEL_COUNT)
228                                 {
229                                         delCount = input.ReadInt();
230                                         System.Diagnostics.Debug.Assert(delCount <= docCount);
231                                 }
232                                 else
233                                         delCount = - 1;
234                                 if (format <= SegmentInfos.FORMAT_HAS_PROX)
235                                         hasProx = input.ReadByte() == 1;
236                                 else
237                                         hasProx = true;
238                                 
239                                 if (format <= SegmentInfos.FORMAT_DIAGNOSTICS)
240                                 {
241                                         diagnostics = input.ReadStringStringMap();
242                                 }
243                                 else
244                                 {
245                                         diagnostics = new System.Collections.Generic.Dictionary<string,string>();
246                                 }
247                         }
248                         else
249                         {
250                                 delGen = CHECK_DIR;
251                                 normGen = null;
252                                 isCompoundFile = (sbyte) (CHECK_DIR);
253                                 preLockless = true;
254                                 hasSingleNormFile = false;
255                                 docStoreOffset = - 1;
256                                 docStoreIsCompoundFile = false;
257                                 docStoreSegment = null;
258                                 delCount = - 1;
259                                 hasProx = true;
260                                 diagnostics = new System.Collections.Generic.Dictionary<string,string>();
261                         }
262                 }
263                 
264                 internal void  SetNumFields(int numFields)
265                 {
266                         if (normGen == null)
267                         {
268                                 // normGen is null if we loaded a pre-2.1 segment
269                                 // file, or, if this segments file hasn't had any
270                                 // norms set against it yet:
271                                 normGen = new long[numFields];
272                                 
273                                 if (preLockless)
274                                 {
275                                         // Do nothing: thus leaving normGen[k]==CHECK_DIR (==0), so that later we know  
276                                         // we have to check filesystem for norm files, because this is prelockless.
277                                 }
278                                 else
279                                 {
280                                         // This is a FORMAT_LOCKLESS segment, which means
281                                         // there are no separate norms:
282                                         for (int i = 0; i < numFields; i++)
283                                         {
284                                                 normGen[i] = NO;
285                                         }
286                                 }
287                         }
288                 }
289                 
290                 /// <summary>Returns total size in bytes of all of files used by
291                 /// this segment. 
292                 /// </summary>
293                 public long SizeInBytes()
294                 {
295                         if (sizeInBytes == - 1)
296                         {
297                                 System.Collections.Generic.IList<string> files = Files();
298                                 int size = files.Count;
299                                 sizeInBytes = 0;
300                                 for (int i = 0; i < size; i++)
301                                 {
302                                         System.String fileName = (System.String) files[i];
303                                         // We don't count bytes used by a shared doc store
304                                         // against this segment:
305                                         if (docStoreOffset == - 1 || !IndexFileNames.IsDocStoreFile(fileName))
306                                                 sizeInBytes += dir.FileLength(fileName);
307                                 }
308                         }
309                         return sizeInBytes;
310                 }
311                 
312                 public bool HasDeletions()
313                 {
314                         // Cases:
315                         //
316                         //   delGen == NO: this means this segment was written
317                         //     by the LOCKLESS code and for certain does not have
318                         //     deletions yet
319                         //
320                         //   delGen == CHECK_DIR: this means this segment was written by
321                         //     pre-LOCKLESS code which means we must check
322                         //     directory to see if .del file exists
323                         //
324                         //   delGen >= YES: this means this segment was written by
325                         //     the LOCKLESS code and for certain has
326                         //     deletions
327                         //
328                         if (delGen == NO)
329                         {
330                                 return false;
331                         }
332                         else if (delGen >= YES)
333                         {
334                                 return true;
335                         }
336                         else
337                         {
338                                 return dir.FileExists(GetDelFileName());
339                         }
340                 }
341                 
342                 internal void  AdvanceDelGen()
343                 {
344                         // delGen 0 is reserved for pre-LOCKLESS format
345                         if (delGen == NO)
346                         {
347                                 delGen = YES;
348                         }
349                         else
350                         {
351                                 delGen++;
352                         }
353                         ClearFiles();
354                 }
355                 
356                 internal void  ClearDelGen()
357                 {
358                         delGen = NO;
359                         ClearFiles();
360                 }
361                 
362                 public System.Object Clone()
363                 {
364                         SegmentInfo si = new SegmentInfo(name, docCount, dir);
365                         si.isCompoundFile = isCompoundFile;
366                         si.delGen = delGen;
367                         si.delCount = delCount;
368                         si.hasProx = hasProx;
369                         si.preLockless = preLockless;
370                         si.hasSingleNormFile = hasSingleNormFile;
371             if (this.diagnostics != null)
372             {
373                 si.diagnostics = new System.Collections.Generic.Dictionary<string, string>();
374                 foreach (string o in diagnostics.Keys)
375                 {
376                     si.diagnostics.Add(o,diagnostics[o]);
377                 }
378             }
379                         if (normGen != null)
380                         {
381                                 si.normGen = new long[normGen.Length];
382                                 normGen.CopyTo(si.normGen, 0);
383                         }
384                         si.docStoreOffset = docStoreOffset;
385                         si.docStoreSegment = docStoreSegment;
386                         si.docStoreIsCompoundFile = docStoreIsCompoundFile;
387             if (this.files != null)
388             {
389                 si.files = new System.Collections.Generic.List<string>();
390                 foreach (string file in files)
391                 {
392                     si.files.Add(file);
393                 }
394             }
395             
396                         return si;
397                 }
398                 
399                 public System.String GetDelFileName()
400                 {
401                         if (delGen == NO)
402                         {
403                                 // In this case we know there is no deletion filename
404                                 // against this segment
405                                 return null;
406                         }
407                         else
408                         {
409                                 // If delGen is CHECK_DIR, it's the pre-lockless-commit file format
410                                 return IndexFileNames.FileNameFromGeneration(name, "." + IndexFileNames.DELETES_EXTENSION, delGen);
411                         }
412                 }
413
414         /// <summary> Returns true if this field for this segment has saved a separate norms file (_&lt;segment&gt;_N.sX).
415                 /// 
416                 /// </summary>
417                 /// <param name="fieldNumber">the field index to check
418                 /// </param>
419                 public bool HasSeparateNorms(int fieldNumber)
420                 {
421                         if ((normGen == null && preLockless) || (normGen != null && normGen[fieldNumber] == CHECK_DIR))
422                         {
423                                 // Must fallback to directory file exists check:
424                                 System.String fileName = name + ".s" + fieldNumber;
425                                 return dir.FileExists(fileName);
426                         }
427                         else if (normGen == null || normGen[fieldNumber] == NO)
428                         {
429                                 return false;
430                         }
431                         else
432                         {
433                                 return true;
434                         }
435                 }
436                 
437                 /// <summary> Returns true if any fields in this segment have separate norms.</summary>
438                 public bool HasSeparateNorms()
439                 {
440                         if (normGen == null)
441                         {
442                                 if (!preLockless)
443                                 {
444                                         // This means we were created w/ LOCKLESS code and no
445                                         // norms are written yet:
446                                         return false;
447                                 }
448                                 else
449                                 {
450                                         // This means this segment was saved with pre-LOCKLESS
451                                         // code.  So we must fallback to the original
452                                         // directory list check:
453                                         System.String[] result = dir.List();
454                                         if (result == null)
455                                         {
456                                                 throw new System.IO.IOException("cannot read directory " + dir + ": list() returned null");
457                                         }
458                                         
459                                         System.String pattern;
460                                         pattern = name + ".s";
461                                         int patternLength = pattern.Length;
462                                         for (int i = 0; i < result.Length; i++)
463                                         {
464                                                 if (result[i].StartsWith(pattern) && System.Char.IsDigit(result[i][patternLength]))
465                                                         return true;
466                                         }
467                                         return false;
468                                 }
469                         }
470                         else
471                         {
472                                 // This means this segment was saved with LOCKLESS
473                                 // code so we first check whether any normGen's are >= 1
474                                 // (meaning they definitely have separate norms):
475                                 for (int i = 0; i < normGen.Length; i++)
476                                 {
477                                         if (normGen[i] >= YES)
478                                         {
479                                                 return true;
480                                         }
481                                 }
482                                 // Next we look for any == 0.  These cases were
483                                 // pre-LOCKLESS and must be checked in directory:
484                                 for (int i = 0; i < normGen.Length; i++)
485                                 {
486                                         if (normGen[i] == CHECK_DIR)
487                                         {
488                                                 if (HasSeparateNorms(i))
489                                                 {
490                                                         return true;
491                                                 }
492                                         }
493                                 }
494                         }
495                         
496                         return false;
497                 }
498                 
499                 /// <summary> Increment the generation count for the norms file for
500                 /// this field.
501                 /// 
502                 /// </summary>
503                 /// <param name="fieldIndex">field whose norm file will be rewritten
504                 /// </param>
505                 internal void  AdvanceNormGen(int fieldIndex)
506                 {
507                         if (normGen[fieldIndex] == NO)
508                         {
509                                 normGen[fieldIndex] = YES;
510                         }
511                         else
512                         {
513                                 normGen[fieldIndex]++;
514                         }
515                         ClearFiles();
516                 }
517                 
518                 /// <summary> Get the file name for the norms file for this field.
519                 /// 
520                 /// </summary>
521                 /// <param name="number">field index
522                 /// </param>
523                 public System.String GetNormFileName(int number)
524                 {
525                         System.String prefix;
526                         
527                         long gen;
528                         if (normGen == null)
529                         {
530                                 gen = CHECK_DIR;
531                         }
532                         else
533                         {
534                                 gen = normGen[number];
535                         }
536                         
537                         if (HasSeparateNorms(number))
538                         {
539                                 // case 1: separate norm
540                                 prefix = ".s";
541                                 return IndexFileNames.FileNameFromGeneration(name, prefix + number, gen);
542                         }
543                         
544                         if (hasSingleNormFile)
545                         {
546                                 // case 2: lockless (or nrm file exists) - single file for all norms 
547                                 prefix = "." + IndexFileNames.NORMS_EXTENSION;
548                                 return IndexFileNames.FileNameFromGeneration(name, prefix, WITHOUT_GEN);
549                         }
550                         
551                         // case 3: norm file for each field
552                         prefix = ".f";
553                         return IndexFileNames.FileNameFromGeneration(name, prefix + number, WITHOUT_GEN);
554                 }
555                 
556                 /// <summary> Mark whether this segment is stored as a compound file.
557                 /// 
558                 /// </summary>
559                 /// <param name="isCompoundFile">true if this is a compound file;
560                 /// else, false
561                 /// </param>
562                 internal void  SetUseCompoundFile(bool isCompoundFile)
563                 {
564                         if (isCompoundFile)
565                         {
566                                 this.isCompoundFile = (sbyte) (YES);
567                         }
568                         else
569                         {
570                                 this.isCompoundFile = (sbyte) (NO);
571                         }
572                         ClearFiles();
573                 }
574                 
575                 /// <summary> Returns true if this segment is stored as a compound
576                 /// file; else, false.
577                 /// </summary>
578                 public bool GetUseCompoundFile()
579                 {
580                         if (isCompoundFile == NO)
581                         {
582                                 return false;
583                         }
584                         else if (isCompoundFile == YES)
585                         {
586                                 return true;
587                         }
588                         else
589                         {
590                                 return dir.FileExists(name + "." + IndexFileNames.COMPOUND_FILE_EXTENSION);
591                         }
592                 }
593                 
594                 public int GetDelCount()
595                 {
596                         if (delCount == - 1)
597                         {
598                                 if (HasDeletions())
599                                 {
600                                         System.String delFileName = GetDelFileName();
601                                         delCount = new BitVector(dir, delFileName).Count();
602                                 }
603                                 else
604                                         delCount = 0;
605                         }
606                         System.Diagnostics.Debug.Assert(delCount <= docCount);
607                         return delCount;
608                 }
609                 
610                 internal void  SetDelCount(int delCount)
611                 {
612                         this.delCount = delCount;
613                         System.Diagnostics.Debug.Assert(delCount <= docCount);
614                 }
615                 
616                 public int GetDocStoreOffset()
617                 {
618                         return docStoreOffset;
619                 }
620                 
621                 public bool GetDocStoreIsCompoundFile()
622                 {
623                         return docStoreIsCompoundFile;
624                 }
625                 
626                 internal void  SetDocStoreIsCompoundFile(bool v)
627                 {
628                         docStoreIsCompoundFile = v;
629                         ClearFiles();
630                 }
631                 
632                 public System.String GetDocStoreSegment()
633                 {
634                         return docStoreSegment;
635                 }
636                 
637                 internal void  SetDocStoreOffset(int offset)
638                 {
639                         docStoreOffset = offset;
640                         ClearFiles();
641                 }
642                 
643                 internal void  SetDocStore(int offset, System.String segment, bool isCompoundFile)
644                 {
645                         docStoreOffset = offset;
646                         docStoreSegment = segment;
647                         docStoreIsCompoundFile = isCompoundFile;
648                 }
649                 
650                 /// <summary> Save this segment's info.</summary>
651                 internal void  Write(IndexOutput output)
652                 {
653                         output.WriteString(name);
654                         output.WriteInt(docCount);
655                         output.WriteLong(delGen);
656                         output.WriteInt(docStoreOffset);
657                         if (docStoreOffset != - 1)
658                         {
659                                 output.WriteString(docStoreSegment);
660                                 output.WriteByte((byte) (docStoreIsCompoundFile?1:0));
661                         }
662                         
663                         output.WriteByte((byte) (hasSingleNormFile?1:0));
664                         if (normGen == null)
665                         {
666                                 output.WriteInt(NO);
667                         }
668                         else
669                         {
670                                 output.WriteInt(normGen.Length);
671                                 for (int j = 0; j < normGen.Length; j++)
672                                 {
673                                         output.WriteLong(normGen[j]);
674                                 }
675                         }
676                         output.WriteByte((byte) isCompoundFile);
677                         output.WriteInt(delCount);
678                         output.WriteByte((byte) (hasProx?1:0));
679                         output.WriteStringStringMap(diagnostics);
680                 }
681                 
682                 internal void  SetHasProx(bool hasProx)
683                 {
684                         this.hasProx = hasProx;
685                         ClearFiles();
686                 }
687                 
688                 public bool GetHasProx()
689                 {
690                         return hasProx;
691                 }
692                 
693                 private void  AddIfExists(System.Collections.Generic.IList<string> files, System.String fileName)
694                 {
695                         if (dir.FileExists(fileName))
696                                 files.Add(fileName);
697                 }
698                 
699                 /*
700                 * Return all files referenced by this SegmentInfo.  The
701                 * returns List is a locally cached List so you should not
702                 * modify it.
703                 */
704                 
705                 public System.Collections.Generic.IList<string> Files()
706                 {
707                         
708                         if (files != null)
709                         {
710                                 // Already cached:
711                                 return files;
712                         }
713
714             System.Collections.Generic.List<string> fileList = new System.Collections.Generic.List<string>();
715                         
716                         bool useCompoundFile = GetUseCompoundFile();
717                         
718                         if (useCompoundFile)
719                         {
720                 fileList.Add(name + "." + IndexFileNames.COMPOUND_FILE_EXTENSION);
721                         }
722                         else
723                         {
724                                 System.String[] exts = IndexFileNames.NON_STORE_INDEX_EXTENSIONS;
725                                 for (int i = 0; i < exts.Length; i++)
726                     AddIfExists(fileList, name + "." + exts[i]);
727                         }
728                         
729                         if (docStoreOffset != - 1)
730                         {
731                                 // We are sharing doc stores (stored fields, term
732                                 // vectors) with other segments
733                                 System.Diagnostics.Debug.Assert(docStoreSegment != null);
734                                 if (docStoreIsCompoundFile)
735                                 {
736                     fileList.Add(docStoreSegment + "." + IndexFileNames.COMPOUND_FILE_STORE_EXTENSION);
737                                 }
738                                 else
739                                 {
740                                         System.String[] exts = IndexFileNames.STORE_INDEX_EXTENSIONS;
741                                         for (int i = 0; i < exts.Length; i++)
742                         AddIfExists(fileList, docStoreSegment + "." + exts[i]);
743                                 }
744                         }
745                         else if (!useCompoundFile)
746                         {
747                                 // We are not sharing, and, these files were not
748                                 // included in the compound file
749                                 System.String[] exts = IndexFileNames.STORE_INDEX_EXTENSIONS;
750                                 for (int i = 0; i < exts.Length; i++)
751                     AddIfExists(fileList, name + "." + exts[i]);
752                         }
753                         
754                         System.String delFileName = IndexFileNames.FileNameFromGeneration(name, "." + IndexFileNames.DELETES_EXTENSION, delGen);
755                         if (delFileName != null && (delGen >= YES || dir.FileExists(delFileName)))
756                         {
757                 fileList.Add(delFileName);
758                         }
759                         
760                         // Careful logic for norms files    
761                         if (normGen != null)
762                         {
763                                 for (int i = 0; i < normGen.Length; i++)
764                                 {
765                                         long gen = normGen[i];
766                                         if (gen >= YES)
767                                         {
768                                                 // Definitely a separate norm file, with generation:
769                         fileList.Add(IndexFileNames.FileNameFromGeneration(name, "." + IndexFileNames.SEPARATE_NORMS_EXTENSION + i, gen));
770                                         }
771                                         else if (NO == gen)
772                                         {
773                                                 // No separate norms but maybe plain norms
774                                                 // in the non compound file case:
775                                                 if (!hasSingleNormFile && !useCompoundFile)
776                                                 {
777                                                         System.String fileName = name + "." + IndexFileNames.PLAIN_NORMS_EXTENSION + i;
778                                                         if (dir.FileExists(fileName))
779                                                         {
780                                 fileList.Add(fileName);
781                                                         }
782                                                 }
783                                         }
784                                         else if (CHECK_DIR == gen)
785                                         {
786                                                 // Pre-2.1: we have to check file existence
787                                                 System.String fileName = null;
788                                                 if (useCompoundFile)
789                                                 {
790                                                         fileName = name + "." + IndexFileNames.SEPARATE_NORMS_EXTENSION + i;
791                                                 }
792                                                 else if (!hasSingleNormFile)
793                                                 {
794                                                         fileName = name + "." + IndexFileNames.PLAIN_NORMS_EXTENSION + i;
795                                                 }
796                                                 if (fileName != null && dir.FileExists(fileName))
797                                                 {
798                             fileList.Add(fileName);
799                                                 }
800                                         }
801                                 }
802                         }
803                         else if (preLockless || (!hasSingleNormFile && !useCompoundFile))
804                         {
805                                 // Pre-2.1: we have to scan the dir to find all
806                                 // matching _X.sN/_X.fN files for our segment:
807                                 System.String prefix;
808                                 if (useCompoundFile)
809                                         prefix = name + "." + IndexFileNames.SEPARATE_NORMS_EXTENSION;
810                                 else
811                                         prefix = name + "." + IndexFileNames.PLAIN_NORMS_EXTENSION;
812                                 int prefixLength = prefix.Length;
813                                 System.String[] allFiles = dir.ListAll();
814                                 IndexFileNameFilter filter = IndexFileNameFilter.GetFilter();
815                                 for (int i = 0; i < allFiles.Length; i++)
816                                 {
817                                         System.String fileName = allFiles[i];
818                                         if (filter.Accept(null, fileName) && fileName.Length > prefixLength && System.Char.IsDigit(fileName[prefixLength]) && fileName.StartsWith(prefix))
819                                         {
820                                                 fileList.Add(fileName);
821                                         }
822                                 }
823                         }
824             //System.Diagnostics.Debug.Assert();
825             files = fileList;
826                         return files;
827                 }
828                 
829                 /* Called whenever any change is made that affects which
830                 * files this segment has. */
831                 private void  ClearFiles()
832                 {
833                         files = null;
834                         sizeInBytes = - 1;
835                 }
836                 
837                 /// <summary>Used for debugging </summary>
838                 public System.String SegString(Directory dir)
839                 {
840                         System.String cfs;
841                         try
842                         {
843                                 if (GetUseCompoundFile())
844                                         cfs = "c";
845                                 else
846                                         cfs = "C";
847                         }
848                         catch (System.IO.IOException ioe)
849                         {
850                                 cfs = "?";
851                         }
852                         
853                         System.String docStore;
854                         
855                         if (docStoreOffset != - 1)
856                                 docStore = "->" + docStoreSegment;
857                         else
858                                 docStore = "";
859                         
860                         return name + ":" + cfs + (this.dir == dir?"":"x") + docCount + docStore;
861                 }
862                 
863                 /// <summary>We consider another SegmentInfo instance equal if it
864                 /// has the same dir and same name. 
865                 /// </summary>
866                 public  override bool Equals(System.Object obj)
867                 {
868                         SegmentInfo other;
869                         try
870                         {
871                                 other = (SegmentInfo) obj;
872                         }
873                         catch (System.InvalidCastException cce)
874                         {
875                                 return false;
876                         }
877                         return other.dir == dir && other.name.Equals(name);
878                 }
879                 
880                 public override int GetHashCode()
881                 {
882                         return dir.GetHashCode() + name.GetHashCode();
883                 }
884         }
885 }