package filerogue.server.ramdb; /** * Title: FileRogue * Description: Global unrestricted file sharing * Copyright: Copyright (c) 2000 * Company: ITP Web Solutions * @author Brian Cairns * @version 1.0 */ import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.logging.Level; import java.util.logging.Logger; import filerogue.*; import filerogue.server.*; import filerogue.server.ramdb.filecash.*; public class RAMDBFunctions implements FileDatabase { private static final Logger logger = Logger.getLogger( "global" ); IntegerKey lookupKey = new IntegerKey(); ExtensionIndexer extensionIndexer = new ExtensionIndexer(); Indexer indexer; SearchEngine searcher; NetworkStats netStats = new NetworkStats( 0, 0, 0 ); Hashtable htUsers = new Hashtable(); Hashtable htNameLookup = new Hashtable(); // table to convert ID's into names Hashtable htCatalogInsertFlags = new Hashtable(); // maps owner names to "killer" Flag objects // constructors ///////////////////////////////////////////////////////////////////////////// public RAMDBFunctions() { if ( Version.ENABLE_DRM ) { logger.log( Level.INFO, "Using Music Indexer" ); indexer = new MusicIndexer( this ); } else if ( Server.getProperty( "server.indexing", "triplet" ).equals( "triplet" ) ) { logger.log( Level.INFO, "Using Triplet Indexing" ); indexer = new TripletIndexer( this ); } else { logger.log( Level.INFO, "Using Null Indexing" ); indexer = new NullIndexer( this ); } if( Version.ENABLE_DRM ) { searcher = new MusicSearchEngine( this, indexer ); } else { searcher = new IndexedSearchEngine( this, indexer ); } } // DRM recheck ////////// /** * We must scan all catalogs against DRM again. Anything that fails must be reinserted */ public void validateAllCatalogs() { synchronized( htUsers ) { String name; UserRecord userRecord; CatalogData cat; for( Iterator iter = htUsers.keySet().iterator(); iter.hasNext(); ) { name = ( String )iter.next(); userRecord = ( UserRecord )htUsers.get( name ); if( userRecord != null ) { cat = userRecord.getCatalogData(); if( cat != null ) { validateCatalog( name, cat ); } } } } } private void validateCatalog( String name, CatalogData cat ) { SubDirData subDir; FileData fileData; int d, f; int dirCount, fileCount; dirCount = cat.getTotalDirCount(); for( d = 0; d < dirCount; d++ ) { subDir = cat.getSubDir( d ); if( subDir != null ) { fileCount = subDir.getFileCount(); for ( f = 0; f < fileCount; f++ ) { fileData = subDir.getFileData( f ); if( !DRM.check( fileData ) ) { // if a single file fails, just re-insert the entire thing (this will filter everything properly) insertCatalog( cat, name ); return; // an insertion automatically validates, so we're done here } } } } } // private methods /////////////////////////////////////////////////////////////////////////////////////////////// /** * adds or subtracts catalog summary info including byte, file, extension counts, and indexes */ void mergeCatalogMetaData( CatalogData cat, boolean add, Flag lifeLine ) { long extStart, start = System.currentTimeMillis(); { if ( add ) { indexer.addIndexes( cat, lifeLine, Server.getBannedExtensions() ); extStart = System.currentTimeMillis(); extensionIndexer.addExtensionData( cat, lifeLine ); } else { // Utilities.backtrace( 5 ); indexer.removeIndexes( cat, lifeLine ); extStart = System.currentTimeMillis(); extensionIndexer.removeExtensionData( cat, lifeLine ); } } long finish = System.currentTimeMillis(); logger.log( Level.FINE, "RAMDBFunctions.mergeCatalogMetaData( " + ( add ? "ADD" : "REMOVE" ) + " " + cat + " ) took " + ( finish - start ) + " ms (index=" + ( extStart - start ) + ", exts=" + ( finish - extStart ) + ")" ); // manualAudit(); } // summarizes network stats manually - for debugging purposes void manualAudit() { long time = System.currentTimeMillis(); String output = "*** Cons: " + Server.getConnections().size() + ", netStats: " + netStats.getUsers() + "u/" + netStats.getFiles() + "f/" + netStats.getBytes() + "b"; if ( Utilities.DEBUG ) { int userCount; int fileCount = 0; long byteCount = 0; UserRecord record; CatalogData cat; synchronized ( htUsers ) { userCount = htUsers.size(); for ( Iterator iter = htUsers.values().iterator(); iter.hasNext(); ) { if ( ( record = ( UserRecord ) iter.next() ) != null ) { if ( ( cat = record.getCatalogData() ) != null ) { fileCount += cat.getTotalFileCount(); byteCount += cat.getTotalByteCount(); } } } } output += ", manualAudit: " + userCount + "u/" + fileCount + "f/" + byteCount + "b, " + extensionIndexer.getManualExtensionSummary(); if ( userCount != netStats.getUsers() || fileCount != netStats.getFiles() || byteCount != netStats.getBytes() ) { logger.log( Level.SEVERE, "NetStats do not match manualAudit()!!! Correcting..." ); netStats = new NetworkStats( userCount, fileCount, byteCount ); } } logger.log( Level.INFO, output + " (" + ( System.currentTimeMillis() - time ) + "ms)" ); } // package level methods ///////////////////////////////////////////////////////////////////////////////////////// Hashtable getDB() { return htUsers; } SubDirData getSubDir( int user, int dir ) { try { return ( ( UserRecord ) htUsers.get( getUserName( user ) ) ).getCatalogData().getSubDir( dir ); } catch ( NullPointerException x ) { return null; } } ExtensionIndexer getExtensionIndexer() { return extensionIndexer; } public User getUser( String name ) { if ( name == null ) { return null; } UserRecord rec = ( UserRecord ) htUsers.get( name ); if ( rec != null ) { return rec.getUser(); } else { return null; } } // FileDatabase implementation /////////////////////////////////////////////////////////////////////////////////// public void login( User user ) { System.out.println( "FileDB.login: " + user.getSummary() ); UserRecord record = ( UserRecord ) htUsers.put( user.getName(), new UserRecord( user ) ); // if we are replacing an old entry, we need to properly remove the statistics for it first if ( record != null ) { deleteUserRecord( record ); } htNameLookup.put( new IntegerKey( user.getID() ), user.getName() ); netStats.incUsers( 1 ); } public NetworkStats getStats() { return netStats; } public void updateExtensionCount() { // do nothing, RAMDB does it real time baby // use this hook for debugging manualAudit(); } public void updateActiveUserStats( User a_user ) { if ( a_user != null ) { UserRecord record = ( UserRecord ) htUsers.get( a_user.getName() ); if ( record != null ) { User existingUser = record.getUser(); if ( existingUser != null ) { existingUser.setState( a_user.getState() ); existingUser.setAutoProxy( a_user.isAutoProxy() ); existingUser.setProxy( a_user.getProxy() ); existingUser.setPort( a_user.getPort() ); existingUser.setGlobalSlots( a_user.getGlobalSlots() ); } } else { logger.log( Level.SEVERE, "RAMDBFunctions.updateActiveUserStats() - Record for '" + a_user.getName() + "' no longer exists!" ); } } else { logger.log( Level.SEVERE, "RAMDBFunctions.updateActiveUserStats() - Called with NULL value" ); } } public void insertCatalog( CatalogData catalog, String username ) { UserRecord user = ( UserRecord ) htUsers.get( username ); if ( user != null ) { clearCatalog( user ); user.setCatalogData( catalog ); CatalogInserter.insert( this, user, catalog ); // add stats after catalog insertion, in case stuff is removed netStats.incFiles( catalog.getTotalFileCount() ); netStats.incBytes( catalog.getTotalByteCount() ); logger.log( Level.INFO, "Catalog and stats INSERTED for " + catalog ); } } // returns the user ID of the person logged out (-1 if not found) public int logout( String name ) { // logger.log( Level.FINE, "RAMDBFunctions.logout( " + name + " )" ); // logger.log( Level.INFO, "BLAH!"); UserRecord user = ( UserRecord ) htUsers.remove( name ); if ( user != null ) { deleteUserRecord( user ); return user.getUser().getID(); } return -1; } private void clearCatalog( UserRecord user ) { // cancel any ongoing asynch catalog insertions CatalogInserter.cancel( user.getUser().getName() ); // now remove any catalog or catalog fragment CatalogData cat = user.getCatalogData(); if ( cat != null ) { netStats.incFiles( -cat.getTotalFileCount() ); netStats.incBytes( -cat.getTotalByteCount() ); user.setCatalogData( null ); mergeCatalogMetaData( cat, false, new Flag( true ) ); logger.log( Level.INFO, "Catalog and stats CLEARED for " + cat ); } } // removes a UserRecord and associated statistic data private void deleteUserRecord( UserRecord user ) { if ( user != null ) { synchronized ( lookupKey ) { htNameLookup.remove( lookupKey.setValue( user.getUser().getID() ) ); } netStats.incUsers( -1 ); clearCatalog( user ); } } public String getUserName( int id ) { synchronized ( lookupKey ) { return ( String ) htNameLookup.get( lookupKey.setValue( id ) ); } } public ExtensionInfo[] getTopExtensions( int start, int count ) { return extensionIndexer.getExtensions( start, count ); // ArrayList matches = new ArrayList( count ); // ExtensionInfo[] results = null; // synchronized( liExtensions ) // { // ListIterator iter = null; // try // { // iter = liExtensions.listIterator( start ); // } // catch( IndexOutOfBoundsException x ) // { // logger.log( Level.SEVERE, "RAMDB.getTopExtensions(): index " + start + " does not exist - " + x.toString() ); // } // try // { // for( int i = 0; i < count; i++ ) matches.add( iter.next() ); // } // catch( NoSuchElementException x ) // { // logger.log( Level.SEVERE, "RAMDB.getTopExtensions(): ran out of extensions! - " + x.toString() ); // } // results = new ExtensionInfo[ matches.size() ]; // matches.toArray( results ); // } // return results; } public UserContact[] getActiveUserContacts() { UserContact[] contacts; synchronized ( htUsers ) { contacts = new UserContact[ htUsers.size() ]; Iterator users = htUsers.values().iterator(); int i = 0; while ( users.hasNext() ) { contacts[ i++ ] = new UserContact( ( ( UserRecord ) users.next() ).getUser() ); } } return contacts; } public CatalogSummaryData getCatalogSummary( String a_name ) { CatalogSummaryData catalogSummary = null; UserRecord user = ( UserRecord ) htUsers.get( a_name ); if ( user != null ) { CatalogData cat = user.getCatalogData(); if ( cat != null ) { catalogSummary = cat.getCatalogSummary(); // String[] baseDirs = new String[0];//cat.getBaseDirNames(); // SubDirSummary[] summaries = new SubDirSummary[ cat.getTotalDirCount() ]; // for( int i = 0; i < summaries.length; i++ ) // { // SubDirData sub = cat.getSubDir( i ); // summaries[ i ] = new SubDirSummary( i, baseDirs[ sub.getBaseDirID() ] + "/" + sub.getSubPath(), sub.getFileCount(), sub.getByteCount() ); // } // catalogSummary = new CatalogSummaryData( user.getUser().getID(), a_name, summaries ); } } return catalogSummary; } public int getFileCount( String user ) { int count = -1; UserRecord record = ( UserRecord ) htUsers.get( user ); if ( record != null ) { CatalogData cat = record.getCatalogData(); if ( cat != null ) { count = cat.getTotalFileCount(); } } return count; } public long getByteCount( String user ) { long count = -1; UserRecord record = ( UserRecord ) htUsers.get( user ); if ( record != null ) { CatalogData cat = record.getCatalogData(); if ( cat != null ) { count = cat.getTotalByteCount(); } } return count; } public void search( DBSearchRequest dbRequest, Connection con ) { searcher.doSearch( dbRequest, con ); } public String[] findOnlineUsers( String a_query ) { int found = 0; a_query = a_query.toLowerCase(); LinkedList matches = new LinkedList(); synchronized ( htUsers ) { Iterator names = htUsers.keySet().iterator(); while ( names.hasNext() && found < MAX_FIND_ONLINE_USERS ) { String stTemp = ( String ) names.next(); if ( stTemp.toLowerCase().indexOf( a_query ) != -1 ) { matches.add( stTemp ); found++; } } } String[] results = new String[ found ]; matches.toArray( results ); return results; } }