// $Id$ // $Log: not supported by cvs2svn $ // Revision 1.8 2007/01/06 00:23:55 timur // merging production branch changes to database layer to improve performance and reduce number of updates // /* * CopyFileRequestStorage.java * * Created on June 17, 2004, 4:49 PM */ package org.dcache.srm.request.sql; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.escape.CharEscaperBuilder; import com.google.common.escape.Escaper; import org.springframework.dao.DataAccessException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import org.dcache.srm.request.CopyFileRequest; import org.dcache.srm.request.Job; import org.dcache.srm.util.Configuration; /** * * @author timur */ public class CopyFileRequestStorage extends DatabaseFileRequestStorage<CopyFileRequest> { public static final String TABLE_NAME="copyfilerequests"; private static final String UPDATE_REQUEST_SQL = "UPDATE " + TABLE_NAME + " SET "+ "NEXTJOBID=?, " + "CREATIONTIME=?, " + "LIFETIME=?, " + "STATE=?, " + "ERRORMESSAGE=?, " +//5 "SCHEDULERID=?, " + "SCHEDULERTIMESTAMP=?," + "NUMOFRETR=?," + "LASTSTATETRANSITIONTIME=?, " + "REQUESTID=?, "+ // 10 "CREDENTIALID=?, "+ "STATUSCODE=?, "+ "FROMURL=? ,"+ "TOURL =?,"+ "FROMTURL=? ,"+ // 15 "TOTURL=? ,"+ "FROMLOCALPATH=? ,"+ "TOLOCALPATH=? ,"+ "SIZE=? ,"+ "FROMFILEID=? ,"+ // 20 "TOFILEID=? ,"+ "REMOTEREQUESTID=? ,"+ "REMOTEFILEID=? , "+ "SPACERESERVATIONID=? , "+ "TRANSFERID=?, "+ // 25 "EXTRAINFO=? " + "WHERE ID=? "; private static final Escaper AS_PERCENT_VALUE = new CharEscaperBuilder(). addEscape('%', "%25"). addEscape(',', "%2C"). addEscape('=', "%3D"). toEscaper(); private static String serialiseMap(Map<String,String> map) { Map<String,String> transformed = Maps.newHashMapWithExpectedSize(map.size()); for (Map.Entry<String,String> e : map.entrySet()) { transformed.put(AS_PERCENT_VALUE.escape(e.getKey()), AS_PERCENT_VALUE.escape(e.getValue())); } return Joiner.on(',').withKeyValueSeparator("=").join(transformed); } private static ImmutableMap<String,String> deserialiseMap(String serialised) { ImmutableMap.Builder<String,String> builder = new ImmutableMap.Builder<>(); for (Map.Entry<String,String> entry : Splitter.on(',').omitEmptyStrings(). withKeyValueSeparator('=').split(serialised).entrySet()) { try { builder.put(URLDecoder.decode(entry.getKey(), "UTF-8"), URLDecoder.decode(entry.getValue(), "UTF-8")); } catch (UnsupportedEncodingException e) { Throwables.propagate(e); } } return builder.build(); } private PreparedStatement getStatement(Connection connection, String query, Job job) throws SQLException { CopyFileRequest request = (CopyFileRequest)job; return getPreparedStatement(connection, query, request.getNextJobId(), request.getCreationTime(), request.getLifetime(), request.getState().getStateId(), request.latestHistoryEvent(), request.getSchedulerId(), request.getSchedulerTimeStamp(), 0, // num of retries request.getLastStateTransitionTime(), request.getRequestId(), // 10 request.getCredentialId(), request.getStatusCodeString(), request.getSourceSurl().toString(), request.getDestinationSurl().toString(), (request.getSourceTurl()!=null?request.getSourceTurl().toString():null), (request.getDestinationTurl()!=null?request.getDestinationTurl().toString():null), request.getLocalSourcePath(), request.getLocalDestinationPath(), request.getSize(),//20 null, // FromFileId (unused) null, // ToFileId (unused) request.getRemoteRequestId(), request.getRemoteFileId(), request.getSpaceReservationId(), request.getTransferId(), serialiseMap(request.getExtraInfo()), request.getId()); } @Override public PreparedStatement getUpdateStatement(Connection connection, Job job) throws SQLException { if(job == null || !(job instanceof CopyFileRequest)) { throw new IllegalArgumentException("job is not CopyFileRequest" ); } CopyFileRequest request = (CopyFileRequest)job; return getStatement(connection,UPDATE_REQUEST_SQL, request); } private static final String INSERT_SQL = "INSERT INTO "+ TABLE_NAME+ "( " + "ID ,"+ "NEXTJOBID ,"+ "CREATIONTIME ,"+ "LIFETIME ,"+ "STATE ,"+ //5 "ERRORMESSAGE ,"+ "SCHEDULERID ,"+ "SCHEDULERTIMESTAMP ,"+ "NUMOFRETR ,"+ "LASTSTATETRANSITIONTIME,"+ // 10 //DATABASE FILE REQUEST STORAGE "REQUESTID , " + "CREDENTIALID , "+ "STATUSCODE , "+ "FROMURL ,"+ "TOURL ,"+ // 15 "FROMTURL ,"+ "TOTURL ,"+ "FROMLOCALPATH ,"+ "TOLOCALPATH ,"+ "SIZE ,"+ // 20 "FROMFILEID ,"+ "TOFILEID ,"+ "REMOTEREQUESTID ,"+ "REMOTEFILEID , "+ "SPACERESERVATIONID , "+ // 25 "TRANSFERID, " + "EXTRAINFO) " + // 27 "VALUES (?,?,?,?,?,?,?,?,?,?," + "?,?,?,?,?,?,?,?,?,?," + "?,?,?,?,?,?,?)"; @Override public PreparedStatement getCreateStatement(Connection connection, Job job) throws SQLException { if(job == null || !(job instanceof CopyFileRequest)) { throw new IllegalArgumentException("fr is not CopyFileRequest" ); } CopyFileRequest request = (CopyFileRequest)job; return getPreparedStatement(connection, INSERT_SQL, request.getId(), request.getNextJobId(), request.getCreationTime(), request.getLifetime(), request.getState().getStateId(), request.latestHistoryEvent(), request.getSchedulerId(), request.getSchedulerTimeStamp(), 0, // num of retries request.getLastStateTransitionTime(), request.getRequestId(), request.getCredentialId(), request.getStatusCodeString(), request.getSourceSurl().toString(), request.getDestinationSurl().toString(), (request.getSourceTurl()!=null?request.getSourceTurl().toString():null), (request.getDestinationTurl()!=null?request.getDestinationTurl().toString():null), request.getLocalSourcePath(), request.getLocalDestinationPath(), request.getSize(), null, // FromFileId (unused) null, // ToFileId (unused) request.getRemoteRequestId(), request.getRemoteFileId(), request.getSpaceReservationId(), request.getTransferId(), serialiseMap(request.getExtraInfo())); } /** Creates a new instance of CopyFileRequestStorage */ public CopyFileRequestStorage(Configuration.DatabaseParameters configuration, ScheduledExecutorService executor) throws DataAccessException { super(configuration, executor); } @Override protected CopyFileRequest getFileRequest( Connection _con, long ID, Long NEXTJOBID, long CREATIONTIME, long LIFETIME, int STATE, String SCHEDULERID, long SCHEDULER_TIMESTAMP, int NUMOFRETR, long LASTSTATETRANSITIONTIME, long REQUESTID, Long CREDENTIALID, String STATUSCODE, ResultSet set, int next_index)throws SQLException { String FROMURL = set.getString(next_index++); String TOURL = set.getString(next_index++); String FROMTURL = set.getString(next_index++); String TOTURL = set.getString(next_index++); String FROMLOCALPATH = set.getString(next_index++); String TOLOCALPATH = set.getString(next_index++); long size = set.getLong(next_index++); String fromFileId = set.getString(next_index++); String toFileId = set.getString(next_index++); String REMOTEREQUESTID = set.getString(next_index++); String REMOTEFILEID = set.getString(next_index++); String SPACERESERVATIONID = set.getString(next_index++); String TRANSFERID = set.getString(next_index++); ImmutableMap<String,String> extraInfo = deserialiseMap(set.getString(next_index)); Job.JobHistory[] jobHistoryArray = getJobHistory(ID,_con); return new CopyFileRequest( ID, NEXTJOBID , this, CREATIONTIME, LIFETIME, STATE, SCHEDULERID, SCHEDULER_TIMESTAMP, NUMOFRETR, LASTSTATETRANSITIONTIME, jobHistoryArray, REQUESTID, CREDENTIALID, STATUSCODE, FROMURL, TOURL, FROMTURL, TOTURL, FROMLOCALPATH, TOLOCALPATH, size, fromFileId, toFileId, REMOTEREQUESTID, REMOTEFILEID, SPACERESERVATIONID, TRANSFERID, extraInfo); } @Override public String getTableName() { return TABLE_NAME; } }