View Javadoc

1   package net.obsearch.ambient;
2   
3   import java.io.BufferedInputStream;
4   import java.io.BufferedOutputStream;
5   import java.io.File;
6   import java.io.FileInputStream;
7   import java.io.FileNotFoundException;
8   import java.io.FileOutputStream;
9   import java.io.IOException;
10  
11  import org.apache.log4j.Logger;
12  
13  import net.obsearch.Index;
14  import net.obsearch.OB;
15  import net.obsearch.exception.AlreadyFrozenException;
16  import net.obsearch.exception.IllegalIdException;
17  import net.obsearch.exception.NotFrozenException;
18  import net.obsearch.exception.OBException;
19  import net.obsearch.exception.OBStorageException;
20  import net.obsearch.exception.OutOfRangeException;
21  import net.obsearch.exception.PivotsUnavailableException;
22  import net.obsearch.storage.OBStoreFactory;
23  
24  
25  import com.thoughtworks.xstream.XStream;
26  import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
27  import com.thoughtworks.xstream.io.xml.XppDriver;
28  import com.thoughtworks.xstream.io.xml.xppdom.Xpp3Dom;
29  
30  /*
31   OBSearch: a distributed similarity search engine This project is to
32   similarity search what 'bit-torrent' is to downloads. 
33   Copyright (C) 2008 Arnoldo Jose Muller Molina
34  
35   This program is free software: you can redistribute it and/or modify
36   it under the terms of the GNU General Public License as published by
37   the Free Software Foundation, either version 3 of the License, or
38   (at your option) any later version.
39  
40   This program is distributed in the hope that it will be useful,
41   but WITHOUT ANY WARRANTY; without even the implied warranty of
42   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43   GNU General Public License for more details.
44  
45   You should have received a copy of the GNU General Public License
46   along with this program.  If not, see <http://www.gnu.org/licenses/>.
47   */
48  
49  /**
50   * An Ambient is the class that surrounds the index, its metadata and the storage
51   * devices. It helps to serialize the index and put the serialized data in an appropiate
52   * location. This is how you use an ambient:
53   * 1) Create the Index you want to use. 
54   * 2) Create the Ambient that holds the storage device you want to use and pass
55   *     the Index to it.
56   * 3) Forget about the Ambient, when you want to freeze the index, use the Ambient
57   *     to freeze the index so that metadata is stored properly.
58   * 4) When you have closed the index and you want to use it back again, call the ambient
59   *     and it will de-serialize the index and leave it ready for you to use it.
60   * 
61   *  Sub-classes of this class, create ambients  for different storage devices.
62   * @author Arnoldo Jose Muller Molina
63   * @param <I> The index that we want to create with this ambient.
64   */
65  
66  public abstract class AbstractAmbient<O extends OB,  I extends Index<O>> implements Ambient < O, I> {
67  
68  	private static Logger logger = Logger.getLogger(AbstractAmbient.class);
69  	
70  	
71      /**
72       * Index that will be used.
73       */
74      private I index;
75      
76      /**
77       * Directory in which everything will be stored.
78       */
79      private File directory;
80      
81      /**
82       * Factory that creates storage devices for the index.
83       */
84      protected OBStoreFactory fact;
85      
86      
87      /**
88       * 
89       * @param index An index whose isFrozen() == false.
90       * @param directory The directory in which everything will be stored.
91       * @throws AlreadyFrozenException if the given index is already frozen.
92       */
93      protected AbstractAmbient(I index, File directory) throws AlreadyFrozenException, FileNotFoundException, OBStorageException,
94      NotFrozenException, IllegalAccessException, InstantiationException,
95      OBException, IOException{
96          if(index.isFrozen()){
97              throw new AlreadyFrozenException();
98          }
99          this.index = index;
100         this.directory = directory;
101         initIndex();
102     }
103     
104     /**
105      * Constructor to be used after a freeze took place.
106      * @param directory We will load the database from here.
107      * @throws FileNotFoundException if no metadata is found
108      */
109     protected AbstractAmbient(File directory) throws FileNotFoundException, OBStorageException,
110     NotFrozenException, IllegalAccessException, InstantiationException,
111     OBException, IOException{
112         XStream xstream = new XStream(new XppDriver());
113         FileInputStream fs = new FileInputStream(metadataFile(directory));
114         BufferedInputStream bf = new BufferedInputStream(fs);
115         logger.debug("Reading seed");
116         index =  (I) xstream.fromXML(bf);
117         logger.debug("Seed read!");
118         this.directory = directory;
119         initIndex();
120     }
121     
122     /**
123      * Initializes the factory of the given index.
124      * @throws FileNotFoundException
125      * @throws OBStorageException
126      * @throws NotFrozenException
127      * @throws IllegalAccessException
128      * @throws InstantiationException
129      * @throws OBException
130      * @throws IOException
131      */
132     private void initIndex() throws FileNotFoundException, OBStorageException,
133     NotFrozenException, IllegalAccessException, InstantiationException,
134     OBException, IOException{
135         File dbDirectory = dataFile(directory);
136         fact = createFactory(dbDirectory);
137         dbDirectory.mkdirs();
138         index.init(fact);
139     }
140     
141     public void close() throws OBException{
142     	index.close();
143     }
144     
145     /* (non-Javadoc)
146      * @see net.obsearch.ambient.Ambient#getIndex()
147      */
148     public I getIndex(){
149         return index;
150     }
151     
152     /* (non-Javadoc)
153      * @see net.obsearch.ambient.Ambient#freeze()
154      */
155     public void freeze() throws IOException, AlreadyFrozenException,
156     IllegalIdException, IllegalAccessException, InstantiationException,
157     OBStorageException, OutOfRangeException, OBException, PivotsUnavailableException{
158         index.freeze();
159         // serialize the stream.
160         XStream xstream = new XStream();
161         
162         FileOutputStream fs = new FileOutputStream( metadataFile(directory) );
163         BufferedOutputStream bf = new BufferedOutputStream(fs);
164         xstream.toXML(index, bf);
165     }
166     
167     /**
168      * Creates the metadata file name.
169      */
170     private File metadataFile(File directory){
171         return new File(directory,
172                 METADATA_FILENAME);
173     }
174     
175     /**
176      * Creates the data folder name.
177      * @param directory
178      * @return The directory name where the data will be stored.
179      */
180     private File dataFile(File directory){
181         return new File(directory, "data");
182     }
183     
184     /**
185      * Creates the factory in the given folder.
186      * @param factoryDirectory The location where the factory will work.
187      * @return The factory ready to work!
188      * @throws OBStorageException if something goes wrong with the DB.
189      */
190     protected abstract OBStoreFactory createFactory(File factoryDirectory) throws OBStorageException;
191 
192 	@Override
193 	public OBStoreFactory getFactory() {
194 		// TODO Auto-generated method stub
195 		return fact;
196 	}
197     
198     
199 }