001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/search/tags/sakai_2-4-1/search-impl/impl/src/java/org/sakaiproject/search/index/impl/SegmentInfoImpl.java $
003: * $Id: SegmentInfoImpl.java 29315 2007-04-20 14:28:12Z ajpoland@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006, 2007 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.search.index.impl;
021:
022: import java.io.File;
023: import java.io.IOException;
024: import java.util.Date;
025: import java.util.Hashtable;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.sakaiproject.search.index.SegmentInfo;
030:
031: /**
032: * @author ieb
033: */
034: /**
035: * segment info contains information on the segment, name, version, in db
036: *
037: * @author ieb
038: */
039: public class SegmentInfoImpl implements SegmentInfo {
040: private static final Log log = LogFactory
041: .getLog(SegmentInfoImpl.class);
042:
043: public static final String TIMESTAMP_FILE = "_sakaicluster";
044:
045: // if this file exists in the segment, this is a new segment that has not
046: // been completed
047:
048: public static final String NEW_FILE = "_newsegment";
049:
050: // if this file exists in the segment, the segment has been deleted
051: public static final String DELETED_FILE = "_deletedsegment";
052:
053: private String name;
054:
055: private long version;
056:
057: private boolean indb;
058:
059: private String[] states = new String[] { "new", "created",
060: "deleted" };
061:
062: private boolean localStructuredStorage;
063:
064: private String searchIndexDirectory;
065:
066: private File segmentLocation;
067:
068: private File timestampFile;
069:
070: private File newFile;
071:
072: private File deletedFile;
073:
074: private long segmentSize;
075:
076: public static final int STATE_NEW = 0;
077:
078: public static final int STATE_CREATED = 1;
079:
080: public static final int STATE_DELETED = 2;
081:
082: private SegmentState storedSegmentState = null;
083:
084: private SegmentState liveSegmentState = null;
085:
086: private static Hashtable<String, String> checked = new Hashtable<String, String>();
087:
088: public String toString() {
089: return name + ":" + version + ":" + indb + ": State:"
090: + states[getState()] + ":Created:" + name + ": Update"
091: + new Date(version);
092: }
093:
094: public static SegmentInfo newSharedSegmentInfo(String name,
095: long version, boolean localStructuredStorage,
096: String searchIndexDirectory) {
097: return new SegmentInfoImpl(name, version, true,
098: localStructuredStorage, searchIndexDirectory);
099: }
100:
101: public static SegmentInfo newLocalSegmentInfo(File file,
102: boolean localStructuredStorage, String searchIndexDirectory) {
103: return new SegmentInfoImpl(file, false, localStructuredStorage,
104: searchIndexDirectory);
105: }
106:
107: /**
108: * Create Segment Info and set the version number explicity,
109: * normally as a result of the Segment vomming from the DB
110: * @param name
111: * @param version
112: * @param indb
113: * @param localStructuredStorage
114: * @param searchIndexDirectory
115: */
116: private SegmentInfoImpl(String name, long version, boolean indb,
117: boolean localStructuredStorage, String searchIndexDirectory) {
118: this .searchIndexDirectory = searchIndexDirectory;
119: this .localStructuredStorage = localStructuredStorage;
120: segmentLocation = getSegmentLocation(name,
121: localStructuredStorage, searchIndexDirectory);
122: timestampFile = new File(segmentLocation, TIMESTAMP_FILE);
123: newFile = new File(segmentLocation, NEW_FILE);
124: deletedFile = new File(segmentLocation, DELETED_FILE);
125: this .indb = indb;
126: this .version = version;
127: this .name = name;
128:
129: try {
130: storedSegmentState = new SegmentState(this , timestampFile);
131: } catch (IOException e) {
132: log.debug("Cant Load Stored Segment State");
133: }
134: try {
135: liveSegmentState = new SegmentState(this , null);
136: liveSegmentState.setTimeStamp(version);
137: } catch (IOException e) {
138: log.debug("Cant Load Live Segment State");
139: }
140: }
141:
142: /**
143: * Initialize a local segment
144: * @param file
145: * @param indb
146: * @param localStructuredStorage
147: * @param searchIndexDirectory
148: */
149: private SegmentInfoImpl(File file, boolean indb,
150: boolean localStructuredStorage, String searchIndexDirectory) {
151: this .searchIndexDirectory = searchIndexDirectory;
152: this .localStructuredStorage = localStructuredStorage;
153: segmentLocation = file;
154: timestampFile = new File(segmentLocation, TIMESTAMP_FILE);
155: newFile = new File(segmentLocation, NEW_FILE);
156: deletedFile = new File(segmentLocation, DELETED_FILE);
157: this .indb = indb;
158: this .name = file.getName();
159: /*
160: * The stored segment state is null, hence we have a potentially broken segment.
161: * We should set the version to -1 and let it update from the database if it can.
162: */
163: this .version = -1;
164: try {
165: storedSegmentState = new SegmentState(this , timestampFile);
166: this .version = storedSegmentState.getTimeStamp();
167: } catch (IOException e) {
168: log.debug("Cant Load Stored Segment State");
169: }
170: try {
171: liveSegmentState = new SegmentState(this , null);
172: } catch (IOException e) {
173: log.debug("Cant Load Live Segment State");
174: }
175: }
176:
177: public void setInDb(boolean b) {
178: indb = b;
179: }
180:
181: public String getName() {
182: return name;
183: }
184:
185: public boolean isInDb() {
186: return indb;
187: }
188:
189: public long getVersion() {
190: return version;
191: }
192:
193: public void setVersion(long l) {
194: version = l;
195:
196: }
197:
198: public void setState(int state) {
199: if (state == STATE_NEW) {
200: if (!newFile.exists()) {
201: try {
202: newFile.getParentFile().mkdirs();
203: newFile.createNewFile();
204: } catch (IOException e) {
205: log.error("Failed to create new segment marker at "
206: + newFile);
207: }
208: }
209: if (deletedFile.exists()) {
210: deletedFile.delete();
211: }
212: }
213: if (state == STATE_CREATED) {
214: if (deletedFile.exists()) {
215: deletedFile.delete();
216: }
217: if (newFile.exists()) {
218: newFile.delete();
219: }
220: }
221: if (state == STATE_DELETED) {
222: if (!deletedFile.exists()) {
223: try {
224: deletedFile.getParentFile().mkdirs();
225: deletedFile.createNewFile();
226: } catch (IOException e) {
227: log
228: .error("Failed to create deleted segment marker at "
229: + deletedFile);
230: }
231: }
232: if (newFile.exists()) {
233: newFile.delete();
234: }
235: }
236: }
237:
238: /*
239: * public static int getState(String name, boolean localStructuredStorage,
240: * String searchIndexDirectory) { File f = getSegmentLocation(name,
241: * localStructuredStorage, searchIndexDirectory); return getState(f); }
242: */
243:
244: public int getState() {
245: if (deletedFile.exists()) {
246: return STATE_DELETED;
247: } else if (newFile.exists()) {
248: return STATE_NEW;
249: } else {
250: return STATE_CREATED;
251: }
252:
253: }
254:
255: public File getSegmentLocation() {
256: return segmentLocation;
257: }
258:
259: public static File getSegmentLocation(String name,
260: boolean structured, String searchIndexDirectory) {
261: if (structured) {
262:
263: String hashName = name.substring(name.length() - 4, name
264: .length() - 2);
265: File hash = new File(searchIndexDirectory, hashName);
266: return new File(hash, name);
267: } else {
268: return new File(searchIndexDirectory, name);
269: }
270: }
271:
272: public void setNew() {
273: setState(STATE_NEW);
274: }
275:
276: public void setCreated() {
277: setState(STATE_CREATED);
278: }
279:
280: public void setDeleted() {
281: setState(STATE_DELETED);
282: }
283:
284: public boolean isNew() {
285: return (getState() == STATE_NEW);
286: }
287:
288: public boolean isCreated() {
289: return (getState() == STATE_CREATED);
290: }
291:
292: public boolean isDeleted() {
293: return (getState() == STATE_DELETED);
294: }
295:
296: /**
297: * set the timestamp in the segment
298: *
299: * @param l
300: * @throws IOException
301: */
302: public void setTimeStamp(long l) throws IOException {
303: liveSegmentState.analyze(this );
304: liveSegmentState.setTimeStamp(l);
305: liveSegmentState.save(timestampFile);
306: timestampFile.setLastModified(l);
307: }
308:
309: public boolean isClusterSegment() {
310: return (timestampFile.exists());
311: }
312:
313: /**
314: * get the checksum out of the segment by the segment name
315: *
316: * @param segmentName
317: * @return
318: * @throws Exception
319: * @throws IOException
320: */
321: /*
322: * private String getCheckSum(String segmentName) throws IOException { File
323: * segmentdir = SegmentInfo.getSegmentLocation(segmentName,
324: * localStructuredStorage, searchIndexDirectory); return
325: * getCheckSum(segmentLocation); }
326: */
327: public boolean checkSegmentValidity(boolean logging, String message) {
328: /**
329: * Dont check new segments, there will not be any state to check
330: */
331: if (isCreated()) {
332: return liveSegmentState.checkValidity(logging, message,
333: storedSegmentState);
334: }
335: return true;
336: }
337:
338: public long getLocalSegmentLastModified() {
339: long lm = segmentLocation.lastModified();
340: if (segmentLocation.isDirectory()) {
341: File[] l = segmentLocation.listFiles();
342: for (int i = 0; i < l.length; i++) {
343: if (l[i].lastModified() > lm) {
344: lm = l[i].lastModified();
345: }
346: }
347:
348: }
349: return lm;
350: }
351:
352: public long getLocalSegmentSize() {
353: if (segmentLocation.isDirectory()) {
354: long lm = 0;
355: File[] l = segmentLocation.listFiles();
356: for (int i = 0; i < l.length; i++) {
357: lm += l[i].length();
358: }
359: return lm;
360:
361: } else {
362: return segmentLocation.length();
363: }
364: }
365:
366: public long getTotalSize() {
367: return getTotalSize(segmentLocation);
368: }
369:
370: private long getTotalSize(File currentSegment) {
371: long totalSize = 0;
372: if (currentSegment.isDirectory()) {
373: File[] files = currentSegment.listFiles();
374: if (files != null) {
375: for (int i = 0; i < files.length; i++) {
376: if (files[i].isDirectory()) {
377: totalSize += getTotalSize(files[i]);
378: }
379: totalSize += files[i].length();
380: }
381: }
382: } else {
383: totalSize += currentSegment.length();
384: }
385: return totalSize;
386: }
387:
388: public void touchSegment() throws IOException {
389: setTimeStamp(System.currentTimeMillis());
390: }
391:
392: /*
393: * (non-Javadoc)
394: *
395: * @see org.sakaiproject.search.index.SegmentInfo#getSize()
396: */
397: public long getSize() {
398: return segmentSize;
399: }
400:
401: /*
402: * (non-Javadoc)
403: *
404: * @see org.sakaiproject.search.index.SegmentInfo#loadSize()
405: */
406: public void loadSize() {
407: segmentSize = getTotalSize();
408:
409: }
410:
411: /* (non-Javadoc)
412: * @see org.sakaiproject.search.index.SegmentInfo#doFinalDelete()
413: */
414: public void doFinalDelete() {
415: if (isDeleted()) {
416: File f = getSegmentLocation();
417: deleteAll(f);
418: } else {
419: log.error("Attempt to delete current Segment Data " + this );
420: }
421:
422: }
423:
424: /**
425: * delete all files under this file and including this file
426: *
427: * @param f
428: */
429: public static void deleteAll(File f) {
430: if (f.isDirectory()) {
431: File[] files = f.listFiles();
432: if (files != null) {
433: for (int i = 0; i < files.length; i++) {
434: if (files[i].isDirectory()) {
435: deleteAll(files[i]);
436: } else {
437: files[i].delete();
438: if (files[i].exists()) {
439: log.warn("Failed to delete "
440: + files[i].getPath());
441: }
442: }
443: }
444: }
445: }
446: f.delete();
447: if (f.exists()) {
448: log.warn("Failed to delete " + f.getPath());
449: }
450: }
451:
452: }
|