VolD 0.1

Frontend.java

Go to the documentation of this file.
00001 
00002 package de.zib.vold.frontend;
00003 
00004 import de.zib.vold.common.VoldException;
00005 import de.zib.vold.common.Key;
00006 import de.zib.vold.volatilelogic.VolatileDirectory;
00007 
00008 import java.util.List;
00009 import java.util.Set;
00010 import java.util.Map;
00011 import java.util.HashMap;
00012 
00013 import java.util.concurrent.locks.ReentrantReadWriteLock;
00014 
00015 import org.slf4j.Logger;
00016 import org.slf4j.LoggerFactory;
00017 
00030 public class Frontend
00031 {
00032         private static final Logger log = LoggerFactory.getLogger( Frontend.class );
00033         private final ReentrantReadWriteLock rwlock;
00034 
00035         private VolatileDirectory volatileDirectory;
00036 
00037         final String scopeDelimiter = "/";
00038 
00039         // properties
00040         private boolean recursiveScopeLookups;
00041         private boolean prefixLookupsAllowed;
00042 
00046         public Frontend( )
00047         {
00048                 this.volatileDirectory = null;
00049 
00050                 this.rwlock = new ReentrantReadWriteLock( true );
00051 
00052                 // properties
00053                 setRecursiveScopeLookups( true );
00054                 setPrefixLookupsAllowed( true );
00055         }
00056 
00060         public void setVolatileDirectory( VolatileDirectory volatileDirectory )
00061         {
00062                 this.volatileDirectory = volatileDirectory;
00063         }
00064 
00068         public boolean getRecursiveScopeLookups( )
00069         {
00070                 return this.recursiveScopeLookups;
00071         }
00072 
00080         public void setRecursiveScopeLookups( boolean recursiveScopeLookups )
00081         {
00082                 this.recursiveScopeLookups = recursiveScopeLookups;
00083         }
00084 
00088         public boolean getPrefixLookupsAllowed( )
00089         {
00090                 return this.prefixLookupsAllowed;
00091         }
00092 
00099         public void setPrefixLookupsAllowed( boolean prefixLookupsAllowed )
00100         {
00101                 this.prefixLookupsAllowed = prefixLookupsAllowed;
00102         }
00103 
00107         protected void checkState( )
00108         {
00109                 if( null == volatileDirectory )
00110                 {
00111                         throw new IllegalStateException( "Tried to operate on frontend while it had not been initialized yet. You first need to set a volatile Directory!" );
00112                 }
00113         }
00114         
00120         private String prepare_prefix_key( String key )
00121         {
00122                 if( key.length() < 3 )
00123                         return key;
00124 
00125                 String suffix = key.substring( key.length()-3, key.length() );
00126                 if( suffix.equals( "..." ) )
00127                 {
00128                         return key.substring( 0, key.length()-3 );
00129                 }
00130                 else
00131                 {
00132                         return key;
00133                 }
00134         }
00135 
00145         public void insert( String source, Key key, Set<String> value )
00146         {
00147                 // guard
00148                 {
00149                         log.trace( "Insert: from source " + source + ": " + key._buildkey().toString() + " |--> " + value.toString()  );
00150 
00151                         checkState();
00152                 }
00153 
00154                 try
00155                 {
00156                         rwlock.writeLock().lock();
00157                         
00158                         List< String > _key = key._buildkey();
00159                         _key.add( source );
00160 
00161                         volatileDirectory.insert( _key, value );
00162                 }
00163                 finally
00164                 {
00165                         rwlock.writeLock().unlock();
00166                 }
00167         }
00168 
00175         public void refresh( String source, Key key )
00176         {
00177                 // guard
00178                 {
00179                         log.trace( "Refresh: from source " + source + ": " + key._buildkey().toString()  );
00180 
00181                         checkState();
00182                 }
00183 
00184                 try
00185                 {
00186                         rwlock.writeLock().lock();
00187                         
00188                         List< String > _key = key._buildkey();
00189                         _key.add( source );
00190 
00191                         volatileDirectory.refresh( _key );
00192                 }
00193                 finally
00194                 {
00195                         rwlock.writeLock().unlock();
00196                 }
00197         }
00198 
00205         public void delete( String source, Key key )
00206         {
00207                 // guard
00208                 {
00209                         log.trace( "Delete: from source " + source + ": " + key._buildkey().toString() );
00210 
00211                         checkState();
00212                 }
00213 
00214                 try
00215                 {
00216                         rwlock.writeLock().lock();
00217                         
00218                         List< String > _key = key._buildkey();
00219                         _key.add( source );
00220 
00221                         volatileDirectory.delete( _key );
00222                 }
00223                 finally
00224                 {
00225                         rwlock.writeLock().unlock();
00226                 }
00227         }
00228 
00238         public Map< Key, Set< String > > lookup( Key key )
00239         {
00240                 VoldException found_exception = null;
00241 
00242                 // guard
00243                 {
00244                         log.trace( "Lookup: " + key.toString() );
00245 
00246                         checkState();
00247                 }
00248 
00249                 try
00250                 {
00251                         rwlock.readLock().lock();
00252 
00253                         if( getRecursiveScopeLookups() )
00254                         {
00255                                 String scope = key.get_scope();
00256                                 Map< Key, Set< String > > result;
00257 
00258                                 while( true )
00259                                 {
00260                                         try
00261                                         {
00262                                                 result = scopeLookup( new Key( scope, key.get_type(), key.get_keyname() ) );
00263                                         }
00264                                         catch( VoldException e )
00265                                         {
00266                                                 log.error( "Error in recursive lookup for key " + key._buildkey().toString() + " (actual scope: " + scope + ") - simply skipping: " + e.getMessage() );
00267                                                 found_exception = e;
00268                                                 continue;
00269                                         }
00270 
00271                                         if( 0 != result.size() )
00272                                         {
00273                                                 return result;
00274                                         }
00275 
00276                                         scope = scope_base( scope );
00277 
00278                                         if( null == scope )
00279                                         {
00280                                                 if( null != found_exception )
00281                                                         throw found_exception;
00282 
00283                                                 return new HashMap< Key, Set< String > >();
00284                                         }
00285                                 }
00286                         }
00287                         else
00288                         {
00289                                 return scopeLookup( key );
00290                         }
00291                 }
00292                 finally
00293                 {
00294                         rwlock.readLock().unlock();
00295                 }
00296         }
00297 
00304         private String scope_base( String scope )
00305         {
00306                 int lastdelim = scope.lastIndexOf( scopeDelimiter, scope.length()-2 );
00307 
00308                 if( lastdelim < 0 )
00309                         return null;
00310 
00311                 return scope.substring( 0, lastdelim+1 );
00312         }
00313 
00323         private Map< Key, Set< String > > scopeLookup( Key key )
00324         {
00325                 if( null == key )
00326                 {
00327                         throw new IllegalArgumentException( "null is not allowed as key in Frontend.scopeLookup( key )!" );
00328                 }
00329 
00330                 Map< List< String >, Set< String > > _result; // results from backend
00331                 Map< Key, Set< String > > result = new HashMap< Key, Set< String > >(); // transformed results
00332 
00333                 // get results from directory
00334                 {
00335                         String preparedkey = prepare_prefix_key( key.get_keyname() );
00336 
00337                         if( getPrefixLookupsAllowed() && preparedkey.length() != key.get_keyname().length() )
00338                         {
00339                                 key = new Key( key.get_scope(), key.get_type(), preparedkey );
00340 
00341                                 try
00342                                 {
00343                                         _result = volatileDirectory.prefixLookup( key._buildkey() );
00344                                 }
00345                                 catch( VoldException e )
00346                                 {
00347                                         throw new VoldException( "In Frontend.scopeLookup( " + key._buildkey().toString() + "): ", e );
00348                                 }
00349                         }
00350                         else
00351                         {
00352                                 List< String > _key = key._buildkey();
00353 
00354                                 // add another empty directory to just make a prefix lookup for
00355                                 // this key but different hosts
00356                                 _key.add( new String() );
00357 
00358                                 try
00359                                 {
00360                                         _result = volatileDirectory.prefixLookup( _key );
00361                                 }
00362                                 catch( VoldException e )
00363                                 {
00364                                         throw new VoldException( "In Frontend.scopeLookup( " + _key.toString() + "): ", e );
00365                                 }
00366                         }
00367                 }
00368 
00369                 // merge keys with the same host
00370                 {
00371                         for( Map.Entry< List< String >, Set< String > > entry: _result.entrySet() )
00372                         {
00373                                 Key k;
00374                                 try
00375                                 {
00376                                         k = Key.buildkey( entry.getKey() );
00377                                 }
00378                                 catch( IllegalArgumentException e )
00379                                 {
00380                                         log.error( "Internal Error: simply skipping invalid key in backend: " + entry.getKey().toString() );
00381                                         continue;
00382                                 }
00383 
00384                                 // merge already existing entries -> same hosts
00385                                 if( result.containsKey( k ) )
00386                                 {
00387                                         Set< String > l = result.get( k );
00388 
00389                                         l.addAll( entry.getValue() );
00390                                 }
00391                                 else
00392                                 {
00393                                         result.put( k, entry.getValue() );
00394                                 }
00395                         }
00396                 }
00397 
00398                 return result;
00399         }
00400 }