Source Code Cross Referenced for JDBCRC.java in  » Workflow-Engines » pegasus-2.1.0 » org » griphyn » common » catalog » replica » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Workflow Engines » pegasus 2.1.0 » org.griphyn.common.catalog.replica 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * This file or a portion of this file is licensed under the terms of
0003:         * the Globus Toolkit Public License, found in file GTPL, or at
0004:         * http://www.globus.org/toolkit/download/license.html. This notice must
0005:         * appear in redistributions of this file, with or without modification.
0006:         *
0007:         * Redistributions of this Software, with or without modification, must
0008:         * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
0009:         * some other similar material which is provided with the Software (if
0010:         * any).
0011:         *
0012:         * Copyright 1999-2004 University of Chicago and The University of
0013:         * Southern California. All rights reserved.
0014:         */
0015:
0016:        package org.griphyn.common.catalog.replica;
0017:
0018:        import java.util.*;
0019:        import java.sql.*;
0020:        import org.griphyn.common.catalog.Catalog;
0021:        import org.griphyn.common.catalog.ReplicaCatalog;
0022:        import org.griphyn.common.catalog.ReplicaCatalogEntry;
0023:        import org.griphyn.common.util.VDSProperties;
0024:        import org.griphyn.cPlanner.common.LogManager;
0025:
0026:        /**
0027:         * This class implements a replica catalog on top of a simple table in a
0028:         * JDBC database. This enables a variety of replica catalog
0029:         * implementations in a transactionally safe, concurrent environment.
0030:         * The table must be defined using the statements appropriate for your
0031:         * database - they are part of the setup in $PEGASUS_HOME/sql/.
0032:         *
0033:         * If you chose to use an unsupported database, please check, if your
0034:         * database either supports sequence number, or if it supports auto
0035:         * increment columns. If your database supports sequences (e.g.
0036:         * PostGreSQL), you can use a setup similar to the following (for
0037:         * Oracle, the autoinc can be implemented via a trigger).
0038:         *
0039:         * <pre>
0040:         * create sequence rc_lfn_id;
0041:         *
0042:         * create table rc_lfn (
0043:         *   id      bigint default nextval('rc_lfn_id'::text),
0044:         *   lfn     varchar(255) not null,
0045:         *   pfn     varchar(255) not null,
0046:         *
0047:         *   constraint pk_rc_lfn primary key(id),
0048:         *   constraint sk_rc_lfn unique(lfn,pfn)
0049:         * );
0050:         *
0051:         * create index idx_rc_lfn on rc_lfn(lfn);
0052:         *
0053:         * create table rc_attr (
0054:         *   id      bigint,
0055:         *   name    varchar(64) not null,
0056:         *   value   varchar(255) not null,
0057:         *
0058:         *   constraint pk_rc_attr primary key(id,name),
0059:         *   constraint fk_rc_attr foreign key(id) references rc_lfn(id) on delete cascade
0060:         * );
0061:         *
0062:         * create index idx_rc_attr on rc_attr(name);
0063:         * </pre>
0064:         *
0065:         * In case of databases that do not support sequences (e.g. MySQL), do
0066:         * not specify the <code>create sequence</code>, and use an
0067:         * auto-increment column for the primary key instead, e.g.:
0068:         *
0069:         * <pre>
0070:         * create table rc_lfn (
0071:         *   id      bigint default null auto_increment,
0072:         *   lfn     varchar(255) not null,
0073:         *   pfn     varchar(255) not null,
0074:         *
0075:         *   constraint pk_rc_lfn primary key(id),
0076:         *   constraint sk_rc_lfn unique(lfn,pfn)
0077:         * );
0078:         *
0079:         * create index idx_rc_lfn on rc_lfn(lfn);
0080:         *
0081:         * create table rc_attr (
0082:         *   id      bigint,
0083:         *   name    varchar(64) not null,
0084:         *   value   varchar(255) not null,
0085:         *
0086:         *   constraint pk_rc_attr primary key(id,name),
0087:         *   constraint fk_rc_attr foreign key id references rc_lfn(id) on delete cascade
0088:         * );
0089:         *
0090:         * create index idx_rc_attr on rc_attr(name);
0091:         * </pre>
0092:         *
0093:         * The site attribute should be specified whenever possible. For the
0094:         * shell planner, it will always be of value "local".
0095:         *
0096:         * @author Jens-S. Vöckler
0097:         * @author Yong Zhao
0098:         * @version $Revision: 83 $
0099:         */
0100:        public class JDBCRC implements  ReplicaCatalog {
0101:            /**
0102:             * This message is sent whenever one of the member function is executed
0103:             * which relies on an established database context.
0104:             */
0105:            private static final String c_error = "The database connection is not established";
0106:
0107:            /**
0108:             * Maintains the connection to the database over the lifetime of
0109:             * this instance.
0110:             */
0111:            protected Connection mConnection = null;
0112:
0113:            /**
0114:             * Maintains an essential set of prepared statement, ready to use.
0115:             */
0116:            protected PreparedStatement mStatements[] = null;
0117:
0118:            /**
0119:             * The handle to the logging object.
0120:             */
0121:            protected LogManager mLogger;
0122:
0123:            /**
0124:             * The statement to prepare to slurp attributes.
0125:             */
0126:            private static final String mCStatements[] = { // 0:
0127:                    "SELECT name,value FROM rc_attr WHERE id=?",
0128:                    // 1:
0129:                    "SELECT id,pfn FROM rc_lfn WHERE lfn=?",
0130:                    // 2:
0131:                    "SELECT r.id,r.pfn FROM rc_lfn r, rc_attr a WHERE r.id=a.id"
0132:                            + " AND r.lfn=? AND a.name=? AND a.value=?",
0133:                    // 3:
0134:                    "SELECT r.id,r.pfn FROM rc_lfn r, rc_attr a WHERE r.id=a.id"
0135:                            + " AND r.lfn=? AND a.name=? AND a.value IS NULL",
0136:                    // 4:
0137:                    "INSERT INTO rc_attr(id,name,value) VALUES(?,?,?)",
0138:                    // 5:
0139:                    "DELETE FROM rc_lfn WHERE lfn=?",
0140:                    // 6:
0141:                    "DELETE FROM rc_lfn WHERE id IN"
0142:                            + " ( SELECT id FROM rc_attr WHERE name=? AND value=? )",
0143:                    // 7:
0144:                    "DELETE FROM rc_lfn WHERE id IN"
0145:                            + " ( SELECT id FROM rc_attr WHERE name=? AND value IS NULL )",
0146:                    // 8:
0147:                    "DELETE FROM rc_lfn WHERE lfn=? AND id IN"
0148:                            + " ( SELECT id FROM rc_attr WHERE name=? AND value=? )",
0149:                    // 9:
0150:                    "DELETE FROM rc_lfn WHERE lfn=? AND id IN"
0151:                            + " ( SELECT id FROM rc_attr WHERE name=? AND value IS NULL )", };
0152:
0153:            /**
0154:             * Remembers if obtaining generated keys will work or not.
0155:             */
0156:            private boolean m_autoinc = false;
0157:
0158:            /**
0159:             * Convenience c'tor: Establishes the connection to the replica
0160:             * catalog database. The usual suspects for the class name include:
0161:             *
0162:             * <pre>
0163:             * org.postgresql.Driver
0164:             * com.mysql.jdbc.Driver
0165:             * com.microsoft.jdbc.sqlserver.SQLServerDriver
0166:             * SQLite.JDBCDriver
0167:             * sun.jdbc.odbc.JdbcOdbcDriver
0168:             * </pre>
0169:             *
0170:             * @param jdbc is a string containing the full name of the java class
0171:             * that must be dynamically loaded. This is usually an external jar
0172:             * file which contains the Java database driver.
0173:             * @param url is the database driving URL. This string is database
0174:             * specific, and tell the JDBC driver, at which host and port the
0175:             * database listens, permits additional arguments, and selects the
0176:             * database inside the rDBMS to connect to. Please refer to your
0177:             * JDBC driver documentation for the format and permitted values.
0178:             * @param username is the database user account name to connect with.
0179:             * @param password is the database account password to use.
0180:             *
0181:             * @throws LinkageError if linking the dynamically loaded driver fails.
0182:             * This is a run-time error, and does not need to be caught.
0183:             * @throws ExceptionInInitializerError if the initialization function
0184:             * of the driver's instantiation threw an exception itself. This is a
0185:             * run-time error, and does not need to be caught.
0186:             * @throws ClassNotFoundException if the class in your jdbc parameter
0187:             * cannot be found in your given CLASSPATH environment. Callers must
0188:             * catch this exception.
0189:             * @throws SQLException if something goes awry with the database.
0190:             * Callers must catch this exception.
0191:             */
0192:            public JDBCRC(String jdbc, String url, String username,
0193:                    String password) throws LinkageError,
0194:                    ExceptionInInitializerError, ClassNotFoundException,
0195:                    SQLException {
0196:                this ();
0197:                // load database driver jar
0198:                Class.forName(jdbc);
0199:                // may throw LinkageError,
0200:                // may throw ExceptionInInitializerError,
0201:                // may throw ClassNotFoundException
0202:
0203:                // establish connection to database generically
0204:                connect(url, username, password);
0205:                // may throws SQLException
0206:            }
0207:
0208:            /**
0209:             * Default empty constructor creates an object that is not yet connected
0210:             * to any database. You must use support methods to connect before this
0211:             * instance becomes usable.
0212:             *
0213:             * @see #connect( String, String, String )
0214:             */
0215:            public JDBCRC() {
0216:                // make connection defunc
0217:                mConnection = null;
0218:                mStatements = null;
0219:                mLogger = LogManager.getInstance();
0220:            }
0221:
0222:            /**
0223:             * Connects to the database. This is effectively an accessor to
0224:             * initialize the internal connection instance variable. <b>Warning!
0225:             * You must call {@link java.lang.Class#forName( String )} yourself
0226:             * to load the database JDBC driver jar!</b>
0227:             *
0228:             * @param url is the database driving URL. This string is database
0229:             * specific, and tell the JDBC driver, at which host and port the
0230:             * database listens, permits additional arguments, and selects the
0231:             * database inside the rDBMS to connect to. Please refer to your
0232:             * JDBC driver documentation for the format and permitted values.
0233:             * @param username is the database user account name to connect with.
0234:             * @param password is the database account password to use.
0235:             * @throws SQLException if something goes awry with the database.
0236:             * Callers must catch this exception.
0237:             * @see #JDBCRC( String, String, String, String )
0238:             * @see java.sql.DriverManager#getConnection( String, String, String )
0239:             */
0240:            public void connect(String url, String username, String password)
0241:                    throws SQLException {
0242:                // establish connection to database generically
0243:                mConnection = DriverManager.getConnection(url, username,
0244:                        password);
0245:
0246:                // may throws SQLException
0247:                m_autoinc = mConnection.getMetaData()
0248:                        .supportsGetGeneratedKeys();
0249:
0250:                // prepared statements are Singletons -- prepared on demand
0251:                mStatements = new PreparedStatement[mCStatements.length];
0252:                for (int i = 0; i < mCStatements.length; ++i)
0253:                    mStatements[i] = null;
0254:            }
0255:
0256:            /**
0257:             * Establishes a connection to the database from the properties. You
0258:             * can specify a <tt>driver</tt> property to contain the class name of
0259:             * the JDBC driver for your database. This property will be removed
0260:             * before attempting to connect. You must speficy a <tt>url</tt>
0261:             * property to describe the connection. It will be removed before
0262:             * attempting to connect.
0263:             *
0264:             * @param props is the property table with sufficient settings to
0265:             * establish a link with the database. The minimum key required key is
0266:             * "url", and possibly "driver". Any other keys depend on the database
0267:             * driver.
0268:             * @return true if connected, false if failed to connect.
0269:             * @see java.sql.DriverManager#getConnection( String, Properties )
0270:             *
0271:             * @throws Error subclasses for runtime errors in the class loader.
0272:             */
0273:            public boolean connect(Properties props) {
0274:
0275:                boolean result = false;
0276:                // class loader: Will propagate any runtime errors!!!
0277:                String driver = (String) props.remove("db.driver");
0278:
0279:                Properties localProps = VDSProperties.matchingSubset(
0280:                        (Properties) props.clone(), "db", false);
0281:
0282:                String url = (String) localProps.remove("url");
0283:                if (url == null || url.length() == 0) {
0284:                    return result;
0285:                }
0286:
0287:                try {
0288:                    if (driver != null) {
0289:                        //only support mysql and postgres for time being
0290:                        if (driver.equalsIgnoreCase("MySQL")) {
0291:                            driver = "com.mysql.jdbc.Driver";
0292:                        } else if (driver.equalsIgnoreCase("Postgres")) {
0293:                            driver = "org.postgresql.Driver";
0294:                        }
0295:                        Class.forName(driver);
0296:                    }
0297:                } catch (Exception e) {
0298:                    mLogger.log("While connecting to JDBCRC Replica Catalog",
0299:                            e, LogManager.DEBUG_MESSAGE_LEVEL);
0300:                    return result;
0301:                }
0302:
0303:                try {
0304:                    mConnection = DriverManager.getConnection(url, localProps);
0305:                    m_autoinc = mConnection.getMetaData()
0306:                            .supportsGetGeneratedKeys();
0307:
0308:                    // prepared statements are Singletons -- prepared on demand
0309:                    mStatements = new PreparedStatement[mCStatements.length];
0310:                    for (int i = 0; i < mCStatements.length; ++i) {
0311:                        mStatements[i] = null;
0312:                    }
0313:
0314:                    result = true;
0315:                } catch (SQLException e) {
0316:                    mLogger.log("While connecting to JDBCRC Replica Catalog",
0317:                            e, LogManager.DEBUG_MESSAGE_LEVEL);
0318:                    result = false;
0319:                }
0320:
0321:                return result;
0322:            }
0323:
0324:            /**
0325:             * Explicitely free resources before the garbage collection hits.
0326:             */
0327:            public void close() {
0328:
0329:                if (mConnection != null) {
0330:                    try {
0331:                        if (!mConnection.getAutoCommit())
0332:                            mConnection.commit();
0333:                    } catch (SQLException e) {
0334:                        // ignore
0335:                    }
0336:                }
0337:
0338:                if (mStatements != null) {
0339:                    try {
0340:                        for (int i = 0; i < mCStatements.length; ++i) {
0341:                            if (mStatements[i] != null) {
0342:                                mStatements[i].close();
0343:                                mStatements[i] = null;
0344:                            }
0345:                        }
0346:                    } catch (SQLException e) {
0347:                        // ignore
0348:                    } finally {
0349:                        mStatements = null;
0350:                    }
0351:                }
0352:
0353:                if (mConnection != null) {
0354:                    try {
0355:                        mConnection.close();
0356:                    } catch (SQLException e) {
0357:                        // ignore
0358:                    } finally {
0359:                        mConnection = null;
0360:                    }
0361:                }
0362:            }
0363:
0364:            /**
0365:             * Predicate to check, if the connection with the catalog's
0366:             * implementation is still active. This helps determining, if it makes
0367:             * sense to call <code>close()</code>.
0368:             *
0369:             * @return true, if the implementation is disassociated, false otherwise.
0370:             * @see #close()
0371:             */
0372:            public boolean isClosed() {
0373:                return (mConnection == null);
0374:            }
0375:
0376:            /**
0377:             * Quotes a string that may contain special SQL characters.
0378:             * @param s is the raw string.
0379:             * @return the quoted string, which may be just the input string.
0380:             */
0381:            protected String quote(String s) {
0382:                if (s.indexOf('\'') != -1) {
0383:                    StringBuffer result = new StringBuffer();
0384:                    for (int i = 0; i < s.length(); ++i) {
0385:                        char ch = s.charAt(i);
0386:                        result.append(ch);
0387:                        if (ch == '\'')
0388:                            result.append(ch);
0389:                    }
0390:                    return result.toString();
0391:                } else {
0392:                    return s;
0393:                }
0394:            }
0395:
0396:            /**
0397:             * Singleton manager for prepared statements. This instruction
0398:             * checks that a prepared statement is ready to use, and will
0399:             * create an instance of the prepared statement, if it was unused
0400:             * previously.
0401:             *
0402:             * @param i is the index which prepared statement to check.
0403:             * @return a handle to the prepared statement.
0404:             */
0405:            protected PreparedStatement getStatement(int i) throws SQLException {
0406:                if (mStatements[i] == null)
0407:                    mStatements[i] = mConnection
0408:                            .prepareStatement(mCStatements[i]);
0409:                else
0410:                    mStatements[i].clearParameters();
0411:
0412:                return mStatements[i];
0413:            }
0414:
0415:            /**
0416:             * Retrieves the entry for a given filename and site handle from the
0417:             * replica catalog.
0418:             *
0419:             * @param lfn is the logical filename to obtain information for.
0420:             * @param handle is the resource handle to obtain entries for.
0421:             * @return the (first) matching physical filename, or
0422:             * <code>null</code> if no match was found.
0423:             */
0424:            public String lookup(String lfn, String handle) {
0425:                String result = null;
0426:                int which = (handle == null ? 3 : 2);
0427:                String query = mCStatements[which];
0428:
0429:                // sanity check
0430:                if (lfn == null)
0431:                    return result;
0432:                if (mConnection == null)
0433:                    throw new RuntimeException(c_error);
0434:
0435:                try {
0436:                    PreparedStatement ps = getStatement(which);
0437:                    ps.setString(1, quote(lfn));
0438:                    ps.setString(2, quote(ReplicaCatalogEntry.RESOURCE_HANDLE));
0439:                    if (handle != null)
0440:                        ps.setString(3, quote(handle));
0441:
0442:                    // there should only be one result
0443:                    ResultSet rs = ps.executeQuery();
0444:                    if (rs.next())
0445:                        result = rs.getString("pfn");
0446:
0447:                    rs.close();
0448:                } catch (SQLException e) {
0449:                    throw new RuntimeException(
0450:                            "Unable to query database about " + query + ": "
0451:                                    + e.getMessage());
0452:                }
0453:
0454:                // done
0455:                return result;
0456:            }
0457:
0458:            /**
0459:             * Slurps all attributes from related to a mapping into a map.
0460:             *
0461:             * @param id is the reference id to slurp from as string. Especially
0462:             * Postgres's indexing mechanism goes from tables scans to btrees, if
0463:             * the numeric key is represented as a string. Strings should be safe
0464:             * for other databases, too.
0465:             * @return a Map with the attributes, which may be empty.
0466:             */
0467:            private Map attributes(String id) throws SQLException {
0468:                Map result = new TreeMap();
0469:
0470:                // sanity checks
0471:                if (id == null)
0472:                    return result;
0473:
0474:                // parametrize
0475:                PreparedStatement ps = getStatement(0);
0476:                ps.setString(1, id);
0477:
0478:                // slurp results
0479:                ResultSet rs = ps.executeQuery();
0480:                while (rs.next())
0481:                    result.put(rs.getString(1), rs.getString(2));
0482:
0483:                // done
0484:                rs.close();
0485:                return result;
0486:            }
0487:
0488:            /**
0489:             * Retrieves all entries for a given LFN from the replica catalog.
0490:             * Each entry in the result set is a tuple of a PFN and all its
0491:             * attributes.
0492:             *
0493:             * @param lfn is the logical filename to obtain information for.
0494:             * @return a collection of replica catalog entries
0495:             * @see ReplicaCatalogEntry
0496:             */
0497:            public Collection lookup(String lfn) {
0498:                List result = new ArrayList();
0499:                String query = mCStatements[1];
0500:
0501:                // sanity check
0502:                if (lfn == null)
0503:                    return result;
0504:                if (mConnection == null)
0505:                    throw new RuntimeException(c_error);
0506:
0507:                // start to ask
0508:                try {
0509:                    PreparedStatement ps = getStatement(1);
0510:                    ps.setString(1, quote(lfn));
0511:
0512:                    ResultSet rs = ps.executeQuery();
0513:                    while (rs.next()) {
0514:                        result.add(new ReplicaCatalogEntry(rs.getString("pfn"),
0515:                                attributes(rs.getString("id"))));
0516:                    }
0517:
0518:                    rs.close();
0519:                } catch (SQLException e) {
0520:                    throw new RuntimeException(
0521:                            "Unable to query database about " + query + ": "
0522:                                    + e.getMessage());
0523:                }
0524:
0525:                // done
0526:                return result;
0527:            }
0528:
0529:            /**
0530:             * Retrieves all entries for a given LFN from the replica catalog.
0531:             * Each entry in the result set is just a PFN string. Duplicates
0532:             * are reduced through the set paradigm.
0533:             *
0534:             * @param lfn is the logical filename to obtain information for.
0535:             * @return a set of PFN strings
0536:             */
0537:            public Set lookupNoAttributes(String lfn) {
0538:                Set result = new TreeSet();
0539:                String query = mCStatements[1];
0540:
0541:                // sanity check
0542:                if (lfn == null)
0543:                    return result;
0544:                if (mConnection == null)
0545:                    throw new RuntimeException(c_error);
0546:
0547:                // start to ask
0548:                try {
0549:                    PreparedStatement ps = getStatement(1);
0550:                    ps.setString(1, quote(lfn));
0551:
0552:                    ResultSet rs = ps.executeQuery(query);
0553:                    while (rs.next())
0554:                        result.add(rs.getString("pfn"));
0555:
0556:                    rs.close();
0557:                } catch (SQLException e) {
0558:                    throw new RuntimeException(
0559:                            "Unable to query database about " + query + ": "
0560:                                    + e.getMessage());
0561:                }
0562:
0563:                // done
0564:                return result;
0565:            }
0566:
0567:            /**
0568:             * Retrieves multiple entries for a given logical filename, up to the
0569:             * complete catalog. Retrieving full catalogs should be harmful, but
0570:             * may be helpful in an online display or portal.
0571:             *
0572:             * @param lfns is a set of logical filename strings to look up.
0573:             * @return a map indexed by the LFN. Each value is a collection
0574:             * of replica catalog entries for the LFN.
0575:             * @see org.griphyn.common.catalog.ReplicaCatalogEntry
0576:             */
0577:            public Map lookup(Set lfns) {
0578:                Map result = new HashMap();
0579:                String query = mCStatements[1];
0580:
0581:                // sanity check
0582:                if (lfns == null || lfns.size() == 0)
0583:                    return result;
0584:                if (mConnection == null)
0585:                    throw new RuntimeException(c_error);
0586:
0587:                try {
0588:                    ResultSet rs = null;
0589:                    PreparedStatement ps = getStatement(1);
0590:                    for (Iterator i = lfns.iterator(); i.hasNext();) {
0591:                        List value = new ArrayList();
0592:                        String lfn = (String) i.next();
0593:                        ps.setString(1, quote(lfn));
0594:                        rs = ps.executeQuery();
0595:                        while (rs.next()) {
0596:                            value.add(new ReplicaCatalogEntry(rs
0597:                                    .getString("pfn"), attributes(rs
0598:                                    .getString("id"))));
0599:                        }
0600:                        rs.close();
0601:                        result.put(lfn, value);
0602:                    }
0603:                } catch (SQLException e) {
0604:                    throw new RuntimeException("Unable to query database with "
0605:                            + query + ": " + e.getMessage());
0606:                }
0607:
0608:                // done
0609:                return result;
0610:            }
0611:
0612:            /**
0613:             * Retrieves multiple entries for a given logical filename, up to the
0614:             * complete catalog. Retrieving full catalogs should be harmful, but
0615:             * may be helpful in an online display or portal.
0616:             *
0617:             * @param lfns is a set of logical filename strings to look up.
0618:             * @return a map indexed by the LFN. Each value is a set
0619:             * of PFN strings.
0620:             */
0621:            public Map lookupNoAttributes(Set lfns) {
0622:                Map result = new HashMap();
0623:                String query = mCStatements[1];
0624:
0625:                // sanity check
0626:                if (lfns == null || lfns.size() == 0)
0627:                    return result;
0628:                if (mConnection == null)
0629:                    throw new RuntimeException(c_error);
0630:
0631:                try {
0632:                    ResultSet rs = null;
0633:                    PreparedStatement ps = getStatement(1);
0634:                    for (Iterator i = lfns.iterator(); i.hasNext();) {
0635:                        Set value = new TreeSet();
0636:                        String lfn = (String) i.next();
0637:                        ps.setString(1, quote(lfn));
0638:                        rs = ps.executeQuery();
0639:                        while (rs.next())
0640:                            value.add(rs.getString("pfn"));
0641:                        rs.close();
0642:                        result.put(lfn, value);
0643:                    }
0644:                } catch (SQLException e) {
0645:                    throw new RuntimeException("Unable to query database with "
0646:                            + query + ": " + e.getMessage());
0647:                }
0648:
0649:                // done
0650:                return result;
0651:            }
0652:
0653:            /**
0654:             * Retrieves multiple entries for a given logical filename, up to the
0655:             * complete catalog. Retrieving full catalogs should be harmful, but
0656:             * may be helpful in online display or portal.<p>
0657:             *
0658:             * @param lfns is a set of logical filename strings to look up.
0659:             * @param handle is the resource handle, restricting the LFNs.
0660:             * @return a map indexed by the LFN. Each value is a collection
0661:             * of replica catalog entries (all attributes).
0662:             * @see ReplicaCatalogEntry
0663:             */
0664:            public Map lookup(Set lfns, String handle) {
0665:                Map result = new HashMap();
0666:                int which = (handle == null ? 3 : 2);
0667:                String query = mCStatements[which];
0668:
0669:                // sanity check
0670:                if (lfns == null || lfns.size() == 0)
0671:                    return result;
0672:                if (mConnection == null)
0673:                    throw new RuntimeException(c_error);
0674:
0675:                try {
0676:                    ResultSet rs = null;
0677:                    PreparedStatement ps = getStatement(which);
0678:                    ps.setString(2, quote(ReplicaCatalogEntry.RESOURCE_HANDLE));
0679:                    if (handle != null)
0680:                        ps.setString(3, quote(handle));
0681:
0682:                    for (Iterator i = lfns.iterator(); i.hasNext();) {
0683:                        List value = new ArrayList();
0684:                        String lfn = (String) i.next();
0685:                        ps.setString(1, quote(lfn));
0686:                        rs = ps.executeQuery();
0687:                        while (rs.next()) {
0688:                            value.add(new ReplicaCatalogEntry(rs
0689:                                    .getString("pfn"), attributes(rs
0690:                                    .getString("id"))));
0691:                        }
0692:                        rs.close();
0693:                        result.put(lfn, value);
0694:                    }
0695:                } catch (SQLException e) {
0696:                    throw new RuntimeException("Unable to query database with "
0697:                            + query + ": " + e.getMessage());
0698:                }
0699:
0700:                // done
0701:                return result;
0702:            }
0703:
0704:            /**
0705:             * Retrieves multiple entries for a given logical filename, up to the
0706:             * complete catalog. Retrieving full catalogs should be harmful, but
0707:             * may be helpful in online display or portal.<p>
0708:             *
0709:             * @param lfns is a set of logical filename strings to look up.
0710:             * @param handle is the resource handle, restricting the LFNs.
0711:             * @return a map indexed by the LFN. Each value is a set of
0712:             * physical filenames.
0713:             */
0714:            public Map lookupNoAttributes(Set lfns, String handle) {
0715:                Map result = new HashMap();
0716:                int which = (handle == null ? 3 : 2);
0717:                String query = mCStatements[which];
0718:
0719:                // sanity check
0720:                if (lfns == null || lfns.size() == 0)
0721:                    return result;
0722:                if (mConnection == null)
0723:                    throw new RuntimeException(c_error);
0724:
0725:                try {
0726:                    ResultSet rs = null;
0727:                    PreparedStatement ps = getStatement(which);
0728:                    ps.setString(2, quote(ReplicaCatalogEntry.RESOURCE_HANDLE));
0729:                    if (handle != null)
0730:                        ps.setString(3, quote(handle));
0731:
0732:                    for (Iterator i = lfns.iterator(); i.hasNext();) {
0733:                        Set value = new TreeSet();
0734:                        String lfn = (String) i.next();
0735:                        ps.setString(1, quote(lfn));
0736:                        rs = ps.executeQuery();
0737:                        while (rs.next())
0738:                            value.add(rs.getString("pfn"));
0739:                        rs.close();
0740:                        result.put(lfn, value);
0741:                    }
0742:                } catch (SQLException e) {
0743:                    throw new RuntimeException("Unable to query database with "
0744:                            + query + ": " + e.getMessage());
0745:                }
0746:
0747:                // done
0748:                return result;
0749:            }
0750:
0751:            /**
0752:             * Helper function to assemble various pieces.
0753:             *
0754:             * @param value is the value of the object from the map.
0755:             * @param obj is the name of the table column
0756:             * @param where is the decision, if we had a previous WHERE clause or not.
0757:             * @see #lookup( Map )
0758:             */
0759:            private String addItem(Object value, String obj, boolean where) {
0760:                // sanity check, no column can be NULL
0761:                if (value == null)
0762:                    return new String();
0763:
0764:                String v = (value instanceof  String) ? (String) value : value
0765:                        .toString();
0766:                StringBuffer q = new StringBuffer(80);
0767:                q.append(where ? " AND " : " WHERE ");
0768:                q.append(obj).append(" LIKE '").append(quote(v)).append('\'');
0769:
0770:                return q.toString();
0771:            }
0772:
0773:            /**
0774:             * Retrieves multiple entries for a given logical filename, up to the
0775:             * complete catalog. Retrieving full catalogs should be harmful, but
0776:             * may be helpful in online display or portal.
0777:             *
0778:             * @param constraints is mapping of keys 'lfn', 'pfn', or any
0779:             * attribute name, e.g. the resource handle 'site', to a string that
0780:             * has some meaning to the implementing system. This can be a SQL
0781:             * wildcard for queries, or a regular expression for Java-based memory
0782:             * collections. Unknown keys are ignored. Using an empty map requests
0783:             * the complete catalog.
0784:             * @return a map indexed by the LFN. Each value is a collection
0785:             * of replica catalog entries.
0786:             * @see ReplicaCatalogEntry
0787:             */
0788:            public Map lookup(Map constraints) {
0789:                Map result = new TreeMap();
0790:
0791:                // more sanity
0792:                if (mConnection == null)
0793:                    throw new RuntimeException(c_error);
0794:
0795:                // prepare statement
0796:                boolean flag = false;
0797:                boolean where = false;
0798:                StringBuffer q = new StringBuffer(256);
0799:                q
0800:                        .append("SELECT DISTINCT r.id,r.lfn,r.pfn FROM rc_lfn r, rc_attr a");
0801:
0802:                for (Iterator i = constraints.keySet().iterator(); i.hasNext();) {
0803:                    String s, key = (String) i.next();
0804:                    if (key.equals("lfn")) {
0805:                        s = addItem(constraints.get("lfn"), "r.lfn", where);
0806:                    } else if (key.equals("pfn")) {
0807:                        s = addItem(constraints.get("pfn"), "r.pfn", where);
0808:                    } else {
0809:                        if (!flag) {
0810:                            q.append(where ? " AND " : " WHERE ").append(
0811:                                    "r.id=a.id");
0812:                            flag = true;
0813:                        }
0814:                        s = addItem(constraints.get(key), "a." + key, where);
0815:                    }
0816:                    if (s.length() > 0) {
0817:                        where = true;
0818:                        q.append(s);
0819:                    }
0820:                }
0821:
0822:                // start to ask
0823:                String lfn = null;
0824:                ReplicaCatalogEntry pair = null;
0825:                String query = q.toString();
0826:                try {
0827:                    Statement st = mConnection.createStatement();
0828:                    ResultSet rs = st.executeQuery(query);
0829:                    while (rs.next()) {
0830:                        lfn = rs.getString("lfn");
0831:                        pair = new ReplicaCatalogEntry(rs.getString("pfn"),
0832:                                attributes(rs.getString("id")));
0833:
0834:                        // add list, if the LFN does not already exist
0835:                        if (!result.containsKey(lfn))
0836:                            result.put(lfn, new ArrayList());
0837:
0838:                        // now add to the list
0839:                        ((List) result.get(lfn)).add(pair);
0840:                    }
0841:                    rs.close();
0842:                    st.close();
0843:                } catch (SQLException e) {
0844:                    throw new RuntimeException(
0845:                            "Unable to query database about " + query + ": "
0846:                                    + e.getMessage());
0847:                }
0848:
0849:                // done
0850:                return result;
0851:            }
0852:
0853:            /**
0854:             * Lists all logical filenames in the catalog.
0855:             *
0856:             * @return A set of all logical filenames known to the catalog.
0857:             */
0858:            public Set list() {
0859:                // short-cut
0860:                return list(null);
0861:            }
0862:
0863:            /**
0864:             * Lists a subset of all logical filenames in the catalog.
0865:             *
0866:             * @param constraint is a constraint for the logical filename only. It
0867:             * is a string that has some meaning to the implementing system. This
0868:             * can be a SQL wildcard for queries, or a regular expression for
0869:             * Java-based memory collections.
0870:             * @return A set of logical filenames that match. The set may be empty
0871:             */
0872:            public Set list(String constraint) {
0873:                Set result = new TreeSet();
0874:
0875:                // more sanity
0876:                if (mConnection == null)
0877:                    throw new RuntimeException(c_error);
0878:
0879:                // prepare statement
0880:                // FIXME: work with pre-prepared statements
0881:                String query = "SELECT lfn FROM rc_lfn";
0882:                if (constraint != null && constraint.length() > 0)
0883:                    query += " WHERE lfn LIKE '" + quote(constraint) + "'";
0884:
0885:                // start to ask
0886:                try {
0887:                    Statement st = mConnection.createStatement();
0888:                    ResultSet rs = st.executeQuery(query);
0889:                    while (rs.next()) {
0890:                        result.add(rs.getString(0));
0891:                    }
0892:                    rs.close();
0893:                    st.close();
0894:                } catch (SQLException e) {
0895:                    throw new RuntimeException(
0896:                            "Unable to query database about " + query + ": "
0897:                                    + e.getMessage());
0898:                }
0899:
0900:                // done
0901:                return result;
0902:            }
0903:
0904:            /**
0905:             * Inserts a new mapping into the replica catalog.
0906:             *
0907:             * @param lfn is the logical filename under which to book the entry.
0908:             * @param tuple is the physical filename and associated PFN attributes.
0909:             *
0910:             * @return number of insertions, should always be 1. On failure,
0911:             * throw an exception, don't use zero.
0912:             */
0913:            public int insert(String lfn, ReplicaCatalogEntry tuple) {
0914:                String query = "[no query]";
0915:                int result = 0;
0916:                boolean autoCommitWasOn = false;
0917:                int state = 0;
0918:
0919:                // sanity checks
0920:                if (lfn == null || tuple == null)
0921:                    return result;
0922:                if (mConnection == null)
0923:                    throw new RuntimeException(c_error);
0924:
0925:                try {
0926:                    // delete-before-insert as one transaction
0927:                    if ((autoCommitWasOn = mConnection.getAutoCommit()))
0928:                        mConnection.setAutoCommit(false);
0929:                    state++; // state == 1
0930:
0931:                    // // delete before insert...
0932:                    // delete( lfn, tuple.getPFN() );
0933:                    state++; // state == 2
0934:
0935:                    ResultSet rs = null;
0936:                    Statement st = null;
0937:                    StringBuffer m = new StringBuffer(256);
0938:                    String id = null;
0939:                    if (!m_autoinc) {
0940:                        //
0941:                        // use sequences, no auto-generated keys possible
0942:                        //
0943:                        query = "SELECT nextval('rc_lfn_id')";
0944:                        st = mConnection.createStatement();
0945:                        rs = st.executeQuery(query);
0946:                        if (rs.next())
0947:                            id = rs.getString(1);
0948:                        else
0949:                            throw new SQLException(
0950:                                    "Unable to access sequence generator");
0951:                        rs.close();
0952:                        st.close();
0953:                        state++; // state == 3
0954:
0955:                        m.append("INSERT INTO rc_lfn(id,lfn,pfn) VALUES('");
0956:                        m.append(id).append("','");
0957:                        m.append(quote(lfn)).append("','");
0958:                        m.append(quote(tuple.getPFN())).append("')");
0959:                        query = m.toString();
0960:                        st = mConnection.createStatement();
0961:                        result = st.executeUpdate(query); // ,Statement.RETURN_GENERATED_KEYS);
0962:                        st.close();
0963:                        state++; // state == 4
0964:                    } else {
0965:                        //
0966:                        // use autoinc columns, obtain autogenerated keys afterwards
0967:                        //
0968:                        m.append("INSERT INTO rc_lfn(lfn,pfn) VALUES('");
0969:                        m.append(quote(lfn)).append("','");
0970:                        m.append(quote(tuple.getPFN())).append("')");
0971:                        query = m.toString();
0972:                        st = mConnection.createStatement();
0973:                        result = st.executeUpdate(query,
0974:                                Statement.RETURN_GENERATED_KEYS);
0975:                        state++; // state == 3
0976:
0977:                        rs = st.getGeneratedKeys();
0978:                        if (rs.next())
0979:                            id = rs.getString(1);
0980:                        else
0981:                            throw new SQLException(
0982:                                    "Unable to access autogenerated key");
0983:                        rs.close();
0984:                        st.close();
0985:                        state++; // state == 4
0986:                    }
0987:
0988:                    query = mCStatements[4];
0989:                    PreparedStatement ps = getStatement(4);
0990:                    //      ps.setString( 1, id ); // GRRR, Pg8!!!
0991:                    ps.setLong(1, Long.parseLong(id));
0992:
0993:                    for (Iterator i = tuple.getAttributeIterator(); i.hasNext();) {
0994:                        String name = (String) i.next();
0995:                        Object value = tuple.getAttribute(name);
0996:                        ps.setString(2, name);
0997:                        if (value == null)
0998:                            ps.setNull(3, Types.VARCHAR);
0999:                        else
1000:                            ps.setString(3,
1001:                                    value instanceof  String ? (String) value
1002:                                            : value.toString());
1003:                        ps.executeUpdate();
1004:                    }
1005:                    state++; // state == 5
1006:
1007:                    mConnection.commit();
1008:                } catch (SQLException e) {
1009:                    try {
1010:                        if (state > 0 && state < 4)
1011:                            mConnection.rollback();
1012:                    } catch (SQLException e2) {
1013:                        // ignore rollback problems
1014:                    }
1015:
1016:                    throw new RuntimeException("Unable to tell database "
1017:                            + query + " (state=" + state + "): "
1018:                            + e.getMessage());
1019:                } finally {
1020:                    // restore original auto-commit state
1021:                    try {
1022:                        if (autoCommitWasOn)
1023:                            mConnection.setAutoCommit(true);
1024:                    } catch (SQLException e) {
1025:                        // ignore
1026:                    }
1027:                }
1028:
1029:                return result;
1030:            }
1031:
1032:            /**
1033:             * Inserts a new mapping into the replica catalog. This is a
1034:             * convenience function exposing the resource handle. Internally, the
1035:             * <code>ReplicaCatalogEntry</code> element will be contructed, and
1036:             * passed to the appropriate insert function.
1037:             *
1038:             * @param lfn is the logical filename under which to book the entry.
1039:             * @param pfn is the physical filename associated with it.
1040:             * @param handle is a resource handle where the PFN resides.
1041:             * @return number of insertions, should always be 1. On failure,
1042:             * throw an exception, don't use zero.
1043:             * @see #insert( String, ReplicaCatalogEntry )
1044:             * @see ReplicaCatalogEntry
1045:             */
1046:            public int insert(String lfn, String pfn, String handle) {
1047:                return insert(lfn, new ReplicaCatalogEntry(pfn, handle));
1048:            }
1049:
1050:            /**
1051:             * Inserts multiple mappings into the replica catalog. The input is a
1052:             * map indexed by the LFN. The value for each LFN key is a collection
1053:             * of replica catalog entries.
1054:             *
1055:             * @param x is a map from logical filename string to list of replica
1056:             * catalog entries.
1057:             * @return the number of insertions.
1058:             * @see org.griphyn.common.catalog.ReplicaCatalogEntry
1059:             */
1060:            public int insert(Map x) {
1061:                int result = 0;
1062:
1063:                // sanity checks
1064:                if (x == null || x.size() == 0)
1065:                    return result;
1066:                if (mConnection == null)
1067:                    throw new RuntimeException(c_error);
1068:
1069:                // FIXME: Create a true bulk mode. This is inefficient, but will
1070:                // get the job done (for now).
1071:                Set lfns = x.keySet();
1072:                for (Iterator i = lfns.iterator(); i.hasNext();) {
1073:                    String lfn = (String) i.next();
1074:                    List value = (List) x.get(lfn);
1075:                    if (value != null && value.size() > 0) {
1076:                        for (Iterator j = value.iterator(); j.hasNext();) {
1077:                            result += insert(lfn, (ReplicaCatalogEntry) j
1078:                                    .next());
1079:                        }
1080:                    }
1081:                }
1082:
1083:                // done
1084:                return result;
1085:            }
1086:
1087:            /**
1088:             * Deletes multiple mappings into the replica catalog. The input is a
1089:             * map indexed by the LFN. The value for each LFN key is a collection
1090:             * of replica catalog entries. On setting matchAttributes to false, all entries
1091:             * having matching lfn pfn mapping to an entry in the Map are deleted.
1092:             * However, upon removal of an entry, all attributes associated with the pfn
1093:             * also evaporate (cascaded deletion).
1094:             *
1095:             * @param x                is a map from logical filename string to list of
1096:             *                         replica catalog entries.
1097:             * @param matchAttributes  whether mapping should be deleted only if all
1098:             *                         attributes match.
1099:             *
1100:             * @return the number of deletions.
1101:             * @see ReplicaCatalogEntry
1102:             */
1103:            public int delete(Map x, boolean matchAttributes) {
1104:                throw new java.lang.UnsupportedOperationException(
1105:                        "delete(Map,boolean) not implemented as yet");
1106:            }
1107:
1108:            /**
1109:             * Deletes a specific mapping from the replica catalog. We don't care
1110:             * about the resource handle. More than one entry could theoretically
1111:             * be removed. Upon removal of an entry, all attributes associated
1112:             * with the PFN also evaporate (cascading deletion).
1113:             *
1114:             * @param lfn is the logical filename in the tuple.
1115:             * @param pfn is the physical filename in the tuple.
1116:             * @return the number of removed entries.
1117:             */
1118:            public int delete(String lfn, String pfn) {
1119:                int result = 0;
1120:
1121:                // sanity checks
1122:                if (lfn == null || pfn == null)
1123:                    return result;
1124:                if (mConnection == null)
1125:                    throw new RuntimeException(c_error);
1126:
1127:                // prepare statement
1128:                // FIXME: work with pre-prepared statements
1129:                StringBuffer m = new StringBuffer(256);
1130:                m.append("DELETE FROM rc_lfn WHERE lfn='");
1131:                m.append(quote(lfn)).append('\'');
1132:                m.append(" AND pfn='").append(quote(pfn)).append('\'');
1133:                String query = m.toString();
1134:
1135:                try {
1136:                    Statement st = mConnection.createStatement();
1137:                    st.execute(query);
1138:                    result = st.getUpdateCount();
1139:                    st.close();
1140:                } catch (SQLException e) {
1141:                    throw new RuntimeException("Unable to tell database "
1142:                            + query + ": " + e.getMessage());
1143:                }
1144:
1145:                // done
1146:                return result;
1147:            }
1148:
1149:            /**
1150:             * Deletes a very specific mapping from the replica catalog. The LFN
1151:             * must be matches, the PFN, and all PFN attributes specified in the
1152:             * replica catalog entry. More than one entry could theoretically be
1153:             * removed. Upon removal of an entry, all attributes associated with
1154:             * the PFN also evaporate (cascading deletion).
1155:             *
1156:             * @param lfn is the logical filename in the tuple.
1157:             * @param tuple is a description of the PFN and its attributes.
1158:             * @return the number of removed entries, either 0 or 1.
1159:             */
1160:            public int delete(String lfn, ReplicaCatalogEntry tuple) {
1161:                int result = 0;
1162:                String query = "[no query]";
1163:
1164:                // sanity checks
1165:                if (lfn == null || tuple == null)
1166:                    return result;
1167:                if (mConnection == null)
1168:                    throw new RuntimeException(c_error);
1169:
1170:                try {
1171:                    StringBuffer m = new StringBuffer(256);
1172:                    for (Iterator i = tuple.getAttributeIterator(); i.hasNext();) {
1173:                        String name = (String) i.next();
1174:                        Object value = tuple.getAttribute(name);
1175:                        m.append("SELECT id FROM rc_attr WHERE name='");
1176:                        m.append(quote(name)).append("' AND value");
1177:                        if (value == null)
1178:                            m.append(" IS NULL");
1179:                        else
1180:                            m.append("='").append(quote(value.toString()))
1181:                                    .append('\'');
1182:                        if (i.hasNext())
1183:                            m.append(" INTERSECT ");
1184:                    }
1185:                    query = m.toString();
1186:
1187:                    m = new StringBuffer(256);
1188:                    m.append("DELETE FROM rc_lfn WHERE lfn='").append(
1189:                            quote(lfn));
1190:                    m.append("' AND pfn='").append(quote(tuple.getPFN()));
1191:                    m.append("' AND id=?");
1192:
1193:                    Statement st = mConnection.createStatement();
1194:                    ResultSet rs = st.executeQuery(query);
1195:
1196:                    query = m.toString();
1197:                    PreparedStatement ps = mConnection.prepareStatement(query);
1198:                    while (rs.next()) {
1199:                        ps.setString(1, rs.getString(1));
1200:                        result += ps.executeUpdate();
1201:                    }
1202:                    ps.close();
1203:                    rs.close();
1204:                    st.close();
1205:                } catch (SQLException e) {
1206:                    throw new RuntimeException("Unable to tell database "
1207:                            + query + ": " + e.getMessage());
1208:                }
1209:
1210:                // done
1211:                return result;
1212:            }
1213:
1214:            /**
1215:             * Deletes all PFN entries for a given LFN from the replica catalog
1216:             * where the PFN attribute is found, and matches exactly the object
1217:             * value. This method may be useful to remove all replica entries that
1218:             * have a certain MD5 sum associated with them. It may also be harmful
1219:             * overkill.
1220:             *
1221:             * @param lfn is the logical filename to look for.
1222:             * @param name is the PFN attribute name to look for.
1223:             * @param value is an exact match of the attribute value to match.
1224:             * @return the number of removed entries.
1225:             */
1226:            public int delete(String lfn, String name, Object value) {
1227:                int result = 0;
1228:                int which = value == null ? 9 : 8;
1229:                String query = mCStatements[which];
1230:
1231:                // sanity checks
1232:                if (lfn == null || name == null)
1233:                    return result;
1234:                if (mConnection == null)
1235:                    throw new RuntimeException(c_error);
1236:
1237:                try {
1238:                    PreparedStatement ps = getStatement(which);
1239:                    ps.setString(1, quote(lfn));
1240:                    ps.setString(2, quote(name));
1241:                    if (value != null)
1242:                        ps.setString(3, quote(value.toString()));
1243:                    result = ps.executeUpdate();
1244:                } catch (SQLException e) {
1245:                    throw new RuntimeException("Unable to tell database "
1246:                            + query + ": " + e.getMessage());
1247:                }
1248:
1249:                // done
1250:                return result;
1251:            }
1252:
1253:            /**
1254:             * Deletes all PFN entries for a given LFN from the replica catalog
1255:             * where the resource handle is found. Karan requested this
1256:             * convenience method, which can be coded like
1257:             * <pre>
1258:             *  delete( lfn, RESOURCE_HANDLE, handle )
1259:             * </pre>
1260:             *
1261:             * @param lfn is the logical filename to look for.
1262:             * @param handle is the resource handle
1263:             * @return the number of entries removed.
1264:             */
1265:            public int deleteByResource(String lfn, String handle) {
1266:                return delete(lfn, ReplicaCatalogEntry.RESOURCE_HANDLE, handle);
1267:            }
1268:
1269:            /**
1270:             * Removes all mappings for an LFN from the replica catalog.
1271:             *
1272:             * @param lfn is the logical filename to remove all mappings for.
1273:             * @return the number of removed entries.
1274:             */
1275:            public int remove(String lfn) {
1276:                int result = 0;
1277:                String query = mCStatements[5];
1278:
1279:                // sanity checks
1280:                if (lfn == null)
1281:                    return result;
1282:                if (mConnection == null)
1283:                    throw new RuntimeException(c_error);
1284:
1285:                try {
1286:                    PreparedStatement ps = getStatement(5);
1287:                    ps.setString(1, quote(lfn));
1288:                    result = ps.executeUpdate();
1289:                } catch (SQLException e) {
1290:                    throw new RuntimeException("Unable to tell database "
1291:                            + query + ": " + e.getMessage());
1292:                }
1293:
1294:                // done
1295:                return result;
1296:            }
1297:
1298:            /**
1299:             * Removes all mappings for a set of LFNs.
1300:             *
1301:             * @param lfns is a set of logical filename to remove all mappings for.
1302:             * @return the number of removed entries.
1303:             */
1304:            public int remove(Set lfns) {
1305:                int result = 0;
1306:                String query = mCStatements[5];
1307:
1308:                // sanity checks
1309:                if (lfns == null || lfns.size() == 0)
1310:                    return result;
1311:                if (mConnection == null)
1312:                    throw new RuntimeException(c_error);
1313:
1314:                try {
1315:                    PreparedStatement ps = getStatement(5);
1316:                    for (Iterator i = lfns.iterator(); i.hasNext();) {
1317:                        ps.setString(1, quote((String) i.next()));
1318:                        result += ps.executeUpdate();
1319:                    }
1320:                } catch (SQLException e) {
1321:                    throw new RuntimeException("Unable to tell database "
1322:                            + query + ": " + e.getMessage());
1323:                }
1324:
1325:                // done
1326:                return result;
1327:            }
1328:
1329:            /**
1330:             * Removes all entries from the replica catalog where the PFN attribute
1331:             * is found, and matches exactly the object value.
1332:             *
1333:             * @param name is the PFN attribute name to look for.
1334:             * @param value is an exact match of the attribute value to match.
1335:             * @return the number of removed entries.
1336:             */
1337:            public int removeByAttribute(String name, Object value) {
1338:                int result = 0;
1339:                int which = value == null ? 7 : 6;
1340:                String query = mCStatements[which];
1341:
1342:                // sanity checks
1343:                if (mConnection == null)
1344:                    throw new RuntimeException(c_error);
1345:
1346:                try {
1347:                    PreparedStatement ps = getStatement(which);
1348:                    ps.setString(1, quote(name));
1349:                    if (value != null)
1350:                        ps.setString(2, value.toString());
1351:                    result = ps.executeUpdate();
1352:                } catch (SQLException e) {
1353:                    throw new RuntimeException("Unable to tell database "
1354:                            + query + ": " + e.getMessage());
1355:                }
1356:
1357:                // done
1358:                return result;
1359:            }
1360:
1361:            /**
1362:             * Removes all entries associated with a particular resource handle.
1363:             * This is useful, if a site goes offline. It is a convenience method,
1364:             * which calls the generic <code>removeByAttribute</code> method.
1365:             *
1366:             * @param handle is the site handle to remove all entries for.
1367:             * @return the number of removed entries.
1368:             * @see #removeByAttribute( String, Object )
1369:             */
1370:            public int removeByAttribute(String handle) {
1371:                return removeByAttribute(ReplicaCatalogEntry.RESOURCE_HANDLE,
1372:                        handle);
1373:            }
1374:
1375:            /**
1376:             * Removes everything. Use with caution!
1377:             *
1378:             * @return the number of removed entries.
1379:             */
1380:            public int clear() {
1381:                int result = 0;
1382:
1383:                // sanity checks
1384:                if (mConnection == null)
1385:                    throw new RuntimeException(c_error);
1386:
1387:                // prepare statement
1388:                String query = "DELETE FROM lfn_rc";
1389:                try {
1390:                    Statement st = mConnection.createStatement();
1391:                    st.execute(query);
1392:                    result = st.getUpdateCount();
1393:                    st.close();
1394:                } catch (SQLException e) {
1395:                    throw new RuntimeException("Unable to tell database "
1396:                            + query + ": " + e.getMessage());
1397:                }
1398:
1399:                // done
1400:                return result;
1401:            }
1402:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.