Package org.xmlBlaster.util.queue.jdbc

Source Code of org.xmlBlaster.util.queue.jdbc.XBRefFactory

/*------------------------------------------------------------------------------
Name:      XbMeatFactory.java
Project:   xmlBlaster.org
Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
------------------------------------------------------------------------------*/

package org.xmlBlaster.util.queue.jdbc;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.xmlBlaster.contrib.I_Info;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.queue.I_QueueEntry;
import org.xmlBlaster.util.queue.ReturnDataHolder;

/**
* @author <a href='mailto:mr@ruff.info'>Marcel Ruff</a>
* @author <a href='mailto:michele@laghi.eu'>Michele Laghi</a>
*/

public class XBRefFactory extends XBFactory {

   private final static Logger log = Logger.getLogger(XBRefFactory.class.getName());
  
   private final static int REF_ID = 1;
   private final static int STORE_ID = 2;
   private final static int MEAT_ID = 3;
   private final static int DURABLE = 4;
   private final static int BYTE_SIZE = 5;
   private final static int META_INFO = 6;
   private final static int FLAG1 = 7;
   private final static int PRIO = 8;
   private final static int METHOD_NAME = 9;
   private final static int LAST_ROW = METHOD_NAME;
  
   private String getAndDeleteSt;
   private String getBySamePrioSt;
   private String getByPrioSt;
   private String deleteWithLimitInclSt;
   private String deleteWithLimitExclSt;
   private String getWithLimitSt;
   private String getFirstRefEntriesStartAtSt;
   private String getFirstRefAndMeatEntriesStartAtSt;
  
   private XBMeatFactory meatFactory;
  
   /**
    * <pre>
    *  xbrefid NUMBER(20) primary key,
    *  xbstoreid NUMBER(20) not null,
    *  xbmeatid NUMBER(20) ,
    *  xbdurable char(1) default 'F' not null ,
    *  xbbytesize NUMBER(10) ,
    *  xbmetainfo clob default '',
    *  xbflag1 varchar(32) default '',
    *  xbprio  NUMBER(10)
    * </pre>
    *
    */
  
   static String getName() {
      return "xbref";
   }
  
   public XBRefFactory(String prefix) {
      super(prefix, getName());
   }

   protected void prepareDefaultStatements() {
      super.prepareDefaultStatements();
      StringBuffer buf = new StringBuffer(512);
     
      if (getDbVendor().equals(POSTGRES)) {
         getCompleteSt = "select * from ${table} left outer join ${xbmeat} on (${table}.xbmeatid=${xbmeat}.xbmeatid)";

         buf.append("create table ${table} (\n");
         buf.append("xbrefid int8 not null,\n");
         buf.append("xbstoreid int8 not null,\n");
         buf.append("xbmeatid int8,\n");
         buf.append("-- creationts timestamp not null default current_timestamp,\n");
         buf.append("-- modifiedts timestamp not null default current_timestamp,\n");
         buf.append("xbdurable char(1) not null default 'F',\n");
         buf.append("xbbytesize int8,\n");
         buf.append("xbmetainfo text default '',\n");
         buf.append("xbflag1 varchar(32) default '',\n");
         buf.append("xbprio int4,\n");
         buf.append("xbmethodname varchar(32) default '',\n");
         buf.append("constraint xbrefpk primary key(xbrefid, xbstoreid));\n");
        
         buf.append("    alter table ${table} \n");
         buf.append("            add constraint fkxbstoreref\n");
         buf.append("            foreign key (xbstoreid) \n");
         buf.append("            references ${xbstore} on delete cascade;\n");
         /*
         buf.append("    alter table ${table} \n");
         buf.append("            add constraint fkxbmeat\n");
         buf.append("            foreign key (xbmeatid) \n");
         buf.append("            references ${xbmeat};\n");
         */

         //  "select * from ${table}  limit ?";
      }
      else if (getDbVendor().equals(ORACLE)) {
         getCompleteSt = "select * from ${table} join ${xbmeat} on (${table}.xbmeatid=${xbmeat}.xbmeatid(+))";

         buf.append("create table ${table} (\n");
         buf.append("      xbrefid NUMBER(20) not null,\n");
         buf.append("      xbstoreid NUMBER(20) not null,\n");
         buf.append("      xbmeatid NUMBER(20) ,\n");
         buf.append("      xbdurable char(1) default 'F' not null ,\n");
         buf.append("      xbbytesize NUMBER(20) ,\n");
         buf.append("      xbmetainfo clob default '',\n");
         buf.append("      xbflag1 varchar(32) default '',\n");
         buf.append("      xbprio  NUMBER(10),\n");
         buf.append("      xbmethodname varchar(32) default '',\n");
         buf.append("      constraint xbrefpk primary key(xbrefid, xbstoreid));\n");
       
         buf.append("    alter table ${table} \n");
         buf.append("            add constraint fkxbstoreref\n");
         buf.append("            foreign key (xbstoreid) \n");
         buf.append("            references ${xbstore} on delete cascade;\n");
        
         /*
         buf.append("    alter table ${table} \n");
         buf.append("            add constraint fkxbmeat\n");
         buf.append("            foreign key (xbmeatid) \n");
         buf.append("            references ${xbmeat};\n");
         */
         // "select * from (select * from ${table}) where rownum <= ?";
      }
      else if (getDbVendor().equals(SQLSERVER_2005)) {
         getCompleteSt = "select * from ${table} left outer join ${xbmeat} on (${table}.xbmeatid=${xbmeat}.xbmeatid)";

         buf.append("create table ${table} (\n");
         buf.append("      xbrefid bigint not null,\n");
         buf.append("      xbstoreid bigint not null,\n");
         buf.append("      xbmeatid bigint,\n");
         buf.append("      xbdurable char(1) not null default 'F',\n");
         buf.append("      xbbytesize bigint,\n");
         buf.append("      xbmetainfo varchar(MAX) default '',\n");
         buf.append("      xbflag1 varchar(32) default '',\n");
         buf.append("      xbprio int,\n");
         buf.append("      xbmethodname varchar(32) default '',\n");
         buf.append("constraint xbrefpk primary key(xbrefid, xbstoreid));\n");

         buf.append(" alter table ${table} \n");
         buf.append("      add constraint fkxbstoreref\n");
         buf.append("      foreign key (xbstoreid)\n");
         buf.append("      references xbstore on delete cascade;\n");
        
         buf.append(" create index IX_REF_DURABLE ON XBREF (xbdurable);\n");
         buf.append(" create index IX_REF_PRIO ON XBREF (xbprio);\n");
      }
      /*
      else if (getDbVendor().equals(DB2)) {
         // create statements
      }
      else if (getDbVendor().equals(FIREBIRD)) {
         // create statements
         // "select first ? * from ${table}";
      }
      else if (getDbVendor().equals(MYSQL)) {
         // "select * from ${table} limit ?";
      }
      else if (getDbVendor().equals(SQLITE)) {
         // "select * from ${table} limit ?";
      }
      */
      else { // if (getDbVendor().equals(HSQLDB))
         getCompleteSt = "select * from ${table} left outer join ${xbmeat} on (${table}.xbmeatid=${xbmeat}.xbmeatid)";

         buf.append("create table ${table} (\n");
         buf.append("      xbrefid bigint not null,\n");
         buf.append("      xbstoreid bigint not null,\n");
         buf.append("      xbmeatid bigint ,\n");
         buf.append("      xbdurable char(1) default 'F' not null ,\n");
         buf.append("      xbbytesize bigint ,\n");
         buf.append("      xbmetainfo varchar default '',\n");
         buf.append("      xbflag1 varchar(32) default '',\n");
         buf.append("      xbprio  integer,\n");
         buf.append("      xbmethodname varchar(32) default '',\n");
         buf.append("      constraint xbrefpk primary key(xbrefid, xbstoreid));\n");

         buf.append("    alter table ${table} \n");
         buf.append("            add constraint fkxbstoreref\n");
         buf.append("            foreign key (xbstoreid) \n");
         buf.append("            references ${xbstore} on delete cascade;\n");
         /*
         buf.append("    alter table ${table} \n");
         buf.append("            add constraint fkxbmeat\n");
         buf.append("            foreign key (xbmeatid) \n");
         buf.append("            references ${xbmeat};\n");
         */
         // "select limit ? * from ${table}";
      }
      createSt =  buf.toString();

      insertSt = "insert into ${table} values ( ?, ?, ?, ?, ?, ?, ?, ?, ?)";
      deleteCompleteSt = "delete from ${table}";
      deleteAllSt = deleteCompleteSt + " where xbstoreid=?";
      deleteSt = deleteAllSt + " and xbrefid=?";
      deleteTransientsSt = deleteAllSt + " and xbdurable='F'";
      // getAllSt = "select * from ${table}";
      deleteWithLimitInclSt = "delete from ${table} where xbstoreid=? and (xbprio > ? or (xbprio = ? and xbrefid <= ?) )";
      deleteWithLimitExclSt = "delete from ${table} where xbstoreid=? and (xbprio > ? or (xbprio = ? and xbrefid < ?) )";
      getNumOfAllSt = "select xbdurable, count(xbbytesize), sum(xbbytesize) from ${table} where xbstoreid=? group by xbdurable";

      getAllSt = getCompleteSt + " where ${table}.xbstoreid=?";
      getWithLimitSt = getAllSt + " and (xbprio > ? or (xbprio = ? and xbrefid < ?) ) order by  xbprio desc, xbrefid asc";

      getSt = getAllSt + " and xbrefid=?";
      getAndDeleteSt = getAllSt + " order by xbprio asc, ${table}.xbrefid desc";
      // these all can be optimized when numEntries is not -1 (see limit alternatives below)
      getFirstEntriesSt = getAllSt + " order by xbprio desc, xbrefid asc";
      getFirstRefAndMeatEntriesStartAtSt = getAllSt + " and xbprio<=? and xbrefid>? order by xbprio desc, xbrefid asc";
      getFirstRefEntriesStartAtSt = "select * from ${table} where ${table}.xbstoreid=? and xbprio<=? and xbrefid>? order by xbprio desc, xbrefid asc";
      getByPrioSt = getAllSt + " and xbprio >= ? and xbprio <= ? order by xbprio desc, xbrefid asc";
      getBySamePrioSt = getAllSt + " and xbprio=(select max(xbprio) from ${table} where xbstoreid=?) order by xbrefid asc";

      inList = " and xbrefid in (";
   }
  
   protected void doInit(I_Info info) throws XmlBlasterException {
      // Replaces ${table} to xbref:
      getCompleteSt =  info.get(prefix + ".getCompleteStatement", getCompleteSt);
      deleteCompleteSt =  info.get(prefix + ".deleteCompleteStatement", deleteCompleteSt);
      getAndDeleteSt = info.get(prefix + ".getAndDeleteStatement", getAndDeleteSt);
      getFirstEntriesSt = info.get(prefix + ".getFirstEntriesStatement", getFirstEntriesSt);
      getFirstRefEntriesStartAtSt = info.get(prefix + ".getFirstRefEntriesStartAtStatement", getFirstRefEntriesStartAtSt);
      getFirstRefAndMeatEntriesStartAtSt = info.get(prefix + ".getFirstRefAndMeatEntriesStartAtSt",
            getFirstRefAndMeatEntriesStartAtSt);
      getByPrioSt = info.get(prefix + ".getByPrioStatement", getByPrioSt);
      getBySamePrioSt = info.get(prefix + ".getBySamePrioStatement", getBySamePrioSt);
      deleteWithLimitInclSt = info.get(prefix + ".deleteWithLimitInclStatement", deleteWithLimitInclSt);
      deleteWithLimitExclSt = info.get(prefix + ".deleteWithLimitExclStatement", deleteWithLimitExclSt);
      getWithLimitSt = info.get(prefix + ".getWithLimitStatement", getWithLimitSt);
     
      meatFactory = new XBMeatFactory(prefix);
      meatFactory.init(info);
     
   }
  
   /**
    * Inserts an entry in the database
    * @param table
    * @param xbMeat The object to store. Note that
    * @param conn The database connection to use
    * @param timeout the time in seconds it has to wait for a response. If less than 1 it is not
    * set.
    * @throws SQLException If an exception occurs in the backend. For example if the entry already
    * exists in the database.
    */
   public void insert(XBRef xbRef, Connection conn, int timeout) throws SQLException, UnsupportedEncodingException {
      if (xbRef == null || conn == null)
         return;
      PreparedStatement preStatement = conn.prepareStatement(insertSt);
      try {
         if (timeout > 0)
            preStatement.setQueryTimeout(timeout);
         preStatement.setLong(REF_ID, xbRef.getId());
         preStatement.setLong(STORE_ID, xbRef.getStoreId());
         long val = xbRef.getMeatId();
         if (val != 0)
            preStatement.setLong(MEAT_ID, val);
         else
            preStatement.setNull(MEAT_ID, Types.NUMERIC);

         if (xbRef.isDurable())
            preStatement.setString(DURABLE, "T");
         else
            preStatement.setString(DURABLE, "F");

         preStatement.setLong(BYTE_SIZE, xbRef.getByteSize());

         fillDbCol(preStatement, META_INFO, xbRef.getMetaInfo());
         fillDbCol(preStatement, FLAG1, xbRef.getFlag1());

         preStatement.setInt(PRIO, xbRef.getPrio());

         fillDbCol(preStatement, METHOD_NAME, xbRef.getMethodName());

         preStatement.execute();
      }
      finally {
         if (preStatement != null)
            preStatement.close();
      }
   }

   protected XBRef rsToEntry(XBStore store, ResultSet rs) throws SQLException, IOException {
      XBRef xbRef = new XBRef();
      xbRef.setId(rs.getLong(REF_ID));
      xbRef.setStoreId(rs.getLong(STORE_ID));
      xbRef.setMeatId(rs.getLong(MEAT_ID));

      String tmp = rs.getString(DURABLE);
      xbRef.setDurable(isTrue(tmp));
      xbRef.setByteSize(rs.getLong(BYTE_SIZE));
     
      xbRef.setMetaInfo(getDbCol(rs, META_INFO));
      xbRef.setFlag1(getDbCol(rs, FLAG1));
      xbRef.setPrio(rs.getInt(PRIO));
      xbRef.setMethodName(getDbCol(rs, METHOD_NAME));
     
      if (!store.isRefCounted()) {
         XBMeat meat = XBMeatFactory.buildFromRs(rs, LAST_ROW);
         if (meat != null)
            xbRef.setMeat(meat);
      }
      return xbRef;
   }
  
   public List<XBRef> getFirstRefEntries(XBStore store, Connection conn, long numOfEntries, long numOfBytes, int timeout)
         throws SQLException, IOException {
      PreparedStatement ps = null;
      try {
         ps = conn.prepareStatement(getFirstEntriesSt);
         if (numOfEntries != -1)
            ps.setMaxRows((int) numOfEntries);
         boolean storeMustBeSet = getFirstEntriesSt.indexOf('?') > -1;
         if (storeMustBeSet)
            ps.setLong(1, store.getId());

         ResultSet rs = ps.executeQuery();
         long countEntries = 0L;
         long countBytes = 0L;
         List<XBRef> list = new ArrayList<XBRef>();
         while ((rs.next()) && ((countEntries < numOfEntries) || (numOfEntries < 0))
               && ((countBytes < numOfBytes) || (numOfBytes < 0))) {
            long byteSize = getByteSize(rs, 0);
            if ((numOfBytes < 0) || (countBytes + byteSize < numOfBytes) || (countEntries == 0)) {
               XBRef entry = rsToEntry(store, rs);
               list.add(entry);
               countBytes += byteSize;
               countEntries++;
            }
         }
         return list;
      } finally {
         if (ps != null)
            ps.close();
      }
   }


   public List<XBRef> getFirstRefEntriesStartAt(XBStore store, Connection conn, long numOfEntries, long numOfBytes,
         int timeout, I_QueueEntry firstEntryExlusive)
   throws SQLException, IOException {
      if (firstEntryExlusive == null) {
         return getFirstRefEntries(store, conn, numOfEntries, numOfBytes, timeout);
      }
     
      PreparedStatement ps = null;
      try {
         String stmt = (store.isRefCounted()) ? getFirstRefEntriesStartAtSt : getFirstRefAndMeatEntriesStartAtSt;
         ps = conn.prepareStatement(stmt);
         if (numOfEntries != -1)
            ps.setMaxRows((int)numOfEntries);
         ps.setLong(1, store.getId());
         ps.setLong(2, firstEntryExlusive.getRef().getPrio());
         ps.setLong(3, firstEntryExlusive.getRef().getId());
         // select xbrefid from xbref where xbref.xbstoreid=1226799982562000000 and xbprio<=5 and xbrefid>1205160650462000000 order by xbprio desc, xbrefid asc
         ResultSet rs = ps.executeQuery();
         long countEntries = 0L;
         long countBytes = 0L;
         List<XBRef> list = new ArrayList<XBRef>();
         while ( (rs.next()) && ((countEntries < numOfEntries) || (numOfEntries < 0)) &&
               ((countBytes < numOfBytes) || (numOfBytes < 0))) {
            long byteSize = getByteSize(rs, 0);
            if ( (numOfBytes < 0) || (countBytes + byteSize < numOfBytes) || (countEntries == 0)) {
               XBRef entry = rsToEntry(store, rs);
               list.add(entry);
               countBytes += byteSize;
               countEntries++;
            }
         }
         return list;
      }
      finally {
         if (ps != null)
            ps.close();
      }
   }

   /**
    *
    * @param sql The select statement to use to fill the objects.
    * @param conn
    * @return null if the object has not been found or the object if it has been found on the backend.
    * @throws SQLException
    */
   public XBRef get(XBStore store, long id, Connection conn, int timeout) throws SQLException, IOException {
      if (conn == null)
         return null;
      PreparedStatement preStatement = conn.prepareStatement(getSt);
      ResultSet rs = null;
      try {
         if (timeout > 0)
            preStatement.setQueryTimeout(timeout);
         preStatement.setLong(1, store.getId());
         preStatement.setLong(2, id);
         rs = preStatement.executeQuery();
         if (!rs.next())
            return null;
         return (XBRef)rsToEntry(store, rs);
      }
      finally {
         if (preStatement != null)
            preStatement.close();
      }
   }
  
  
   /**
    * Helper method to find out if still to retrieve entries in getAndDeleteLowest or not.
    */
   private final boolean isInsideRange(int numEntries, int maxNumEntries, long numBytes, long maxNumBytes) {
      if (maxNumEntries < 0) {
         if (maxNumBytes <0L) return true;
         return numBytes < maxNumBytes;
      }
      // then maxNumEntries >= 0
      if (maxNumBytes <0L) return numEntries < maxNumEntries;
      // then the less restrictive of both is used (since none is negative)
      return numEntries < maxNumEntries || numBytes < maxNumBytes;
   }

   /**
    * Under the same transaction it gets and deletes all the entries which fit
    * into the constrains specified in the argument list. The entries are really
    * deleted only if doDelete is true, otherwise they are left untouched on the
    * queue
    *
    * @return ReturnDataHolder.refList is filled!! (ReturnDataHolder.list is
    *         empty)
    * @see org.xmlBlaster.util.queue.I_Queue#takeLowest(int, long,
    *      org.xmlBlaster.util.queue.I_QueueEntry, boolean)
    */
   ReturnDataHolder getAndDeleteLowest(XBStore store, Connection conn, int numOfEntries, long numOfBytes,
      int maxPriority, long minUniqueId, boolean leaveOne, boolean doDelete, int maxStLength, int maxNumSt, int timeout) throws SQLException, IOException {

      ReturnDataHolder ret = new ReturnDataHolder();
      ret.refList = new ArrayList<XBRef>();
      PreparedStatement st = null;
      try {
         // TODO optimize this statement by adding a LIMIT
         st = conn.prepareStatement(getAndDeleteSt);
         // String req = "select * from ${table} where xbstoreid=? order by xbprio asc, xbmeatid desc";
         st.setLong(1, store.getId());
         ResultSet rs = st.executeQuery();
         boolean doContinue = true;
         boolean stillEntriesInQueue = false;

         while ( (stillEntriesInQueue=rs.next()) && doContinue) {
            XBRef ref = (XBRef)rsToEntry(store, rs);
            if (!isInsideRange((int)ret.countEntries, numOfEntries, ret.countBytes, numOfBytes))
               break;
            // check if allowed or already outside the range ...
            int prio = ref.getPrio();
            long dataId = ref.getId();
            if ((prio < maxPriority) || ((prio == maxPriority) && (dataId > minUniqueId)) ) {
               ret.refList.add(ref);
               ret.countBytes += ref.getByteSize();
               if (ref.isDurable())
                  ret.countPersistentBytes += ref.getByteSize();
            }
            else
               doContinue = false;
            ret.countEntries++;
            if (ref.isDurable())
               ret.countPersistentEntries++;
         }

         // prepare for deleting (we don't use deleteEntries since we want
         // to use the same transaction (and the same connection)
         if (leaveOne) {
            // leave at least one entry
            if (stillEntriesInQueue)
               stillEntriesInQueue = rs.next();
            if ((!stillEntriesInQueue) && (ret.refList.size() > 0)) {
               ret.countEntries--;
               XBRef entryToDelete = (XBRef) ret.refList.remove(ret.refList.size() - 1);
               ret.countBytes -= entryToDelete.getByteSize();
               boolean persistent = entryToDelete.isDurable();
               if (persistent) {
                  ret.countPersistentEntries--;
                  ret.countPersistentBytes -= entryToDelete.getByteSize();
               }
               if (log.isLoggable(Level.FINE))
                  log.fine("takeLowest size to delete: "  + entryToDelete.getByteSize());
            }
         }

         if (doDelete) {
            final boolean commitInBetween = false;
            XBRef[] refs = ret.refList.toArray(new XBRef[ret.refList.size()]);
            deleteList(store, conn, refs, maxStLength, maxNumSt, commitInBetween, timeout);
         }
         return ret;
      }
      finally {
         if (st != null)
            st.close();
      }
   }


   private List<XBRef> rs2List(XBStore store, ResultSet rs, long numOfEntries, long numOfBytes, boolean onlyId)
         throws SQLException, IOException {
      List<XBRef> entries = new ArrayList<XBRef>();
      int count = 0;
      long amount = 0L;

      while ( (rs.next()) && ((count < numOfEntries) || (numOfEntries < 0)) &&
         ((amount < numOfBytes) || (numOfBytes < 0))) {
         XBRef ref = null;
         if(onlyId) {
            ref = new XBRef();
            ref.setId(rs.getLong(1));
         }
         else {
            ref = (XBRef)rsToEntry(store, rs);
            if ( (numOfBytes < 0) || (ref.getByteSize() + amount < numOfBytes) || (count == 0)) {
               amount += ref.getByteSize();
            }
         }
         entries.add(ref);
         count++;
      }
      return entries;
   }
  
  
   /**
    * gets the first numOfEntries of the queue which have the priority in the
    * range specified by prioMin and prioMax (inclusive).
    * If there are not so many entries in the queue, all elements in the queue
    * are returned.
    *
    * @param storageId the storageId of the queue/storage from which to retrieve the information.
    * @param numOfEntries the maximum number of elements to retrieve. If negative there is no constriction.
    * @param numOfBytes the maximum number of bytes to retrieve. If negative, there is no constriction.
    * @param minPrio the minimum priority to retreive (inclusive).
    * @param maxPrio the maximum priority to retrieve (inclusive).
    *
    */
   public List<XBRef> getEntriesByPriority(XBStore store, Connection conn, int numOfEntries,
                             long numOfBytes, int minPrio, int maxPrio, boolean onlyId)
      throws SQLException, IOException {

      PreparedStatement st = null;
      try {
         st = conn.prepareStatement(getByPrioSt);
         int pos = 1;
         st.setLong(pos, store.getId());
         pos++;
         st.setInt(pos, minPrio);
         pos++;
         st.setInt(pos, maxPrio);
         pos++;
         ResultSet rs = st.executeQuery();

         return rs2List(store, rs, numOfEntries, numOfBytes, onlyId);
      }
      finally {
         if (st != null)
            st.close();
      }
   }


   public List<XBRef> getWithLimit(XBStore store, Connection conn, XBRef limitRef) throws SQLException, IOException {
      PreparedStatement st = null;
      try {
         st = conn.prepareStatement(getWithLimitSt);
         //  getWithLimitSt = getAllSt + " where xbstoreid=? and (xbprio > ? or (xbprio = ? and xbrefid < ?) ) order by  xbprio desc, xbrefid asc";
         st.setLong(1, store.getId());
         st.setInt(2, limitRef.getPrio());
         st.setInt(3, limitRef.getPrio());
         st.setLong(4, limitRef.getId());
         ResultSet rs = st.executeQuery();
         final long numEntries = -1L;
         final long numBytes = -1L;
         final boolean onlyId = false;
         return rs2List(store, rs, numEntries, numBytes, onlyId);
      }
      finally {
         if (st != null)
            st.close();
      }
   }

   /**
    * gets the first numOfEntries of the queue which have the same priority.
    * If there are not so many entries in the queue, all elements in the queue
    * are returned.
    *
    * @param numOfEntries the maximum number of elements to retrieve
    *
    */
   public List<XBRef> getEntriesBySamePriority(XBStore store, Connection conn, int numOfEntries, long numOfBytes)
      throws SQLException, IOException {
      PreparedStatement st = null;
      try {
         st = conn.prepareStatement(getBySamePrioSt);
         int pos = 1;
         st.setLong(pos, store.getId());
         pos++;
         st.setLong(pos, store.getId());
         pos++;

         ResultSet rs = st.executeQuery();
         final boolean onlyId = false;
         return rs2List(store, rs, numOfEntries, numOfBytes, onlyId);
      }
      finally {
         if (st != null)
            st.close();
      }
   }
  
  
   /**
    * deletes the first numOfEntries of the queue until the limitEntry is reached.
    * @param numOfEntries the maximum number of elements to retrieve
    */
   public long deleteWithLimit(XBStore store, Connection conn, XBRef limitEntry, boolean inclusive)
      throws SQLException {
      PreparedStatement st = null;
      try {
         if (inclusive)
            st = conn.prepareStatement(deleteWithLimitInclSt);
         else
            st = conn.prepareStatement(deleteWithLimitExclSt);
        
         int limitPrio = limitEntry.getPrio();
         long limitId = limitEntry.getId();
         st.setLong(1, store.getId());
         st.setInt(2, limitPrio);
         st.setInt(3, limitPrio);
         st.setLong(4, limitId);
         return st.executeUpdate();
      }
      finally {
         if (st != null)
            st.close();
      }
   }
  

   public int deleteAllStore(XBStore store, Connection conn, int timeout) throws SQLException {
      if (conn == null)
         return 0;
      PreparedStatement preStatement = conn.prepareStatement(deleteAllSt);
      if (timeout > 0)
         preStatement.setQueryTimeout(timeout);
      try {
         preStatement.setLong(1, store.getId());
         return preStatement.executeUpdate();
      }
      finally {
         if (preStatement != null)
            preStatement.close();
      }
   }

   protected long getByteSize(ResultSet rs, int offset) throws SQLException {
      return rs.getLong(BYTE_SIZE + offset);
   }

  
   /**
    * Deletes the specified entries. Since all entry may not fit in one single operation,
    * they are splitted over different operations.
    * If you specified  commitInBetween or the auto-commit flag is set to true,
    * It always returns the number of deleted entries. If a batch could not be completely deleted,
    * it returns the number of operations previously deleted.
    *
    * @param  store the store to use.
    * @param  the connection to be used.
    * @param   ids the array containing all ids to delete.
    * @return the number of entries successfully processed. These are the first. If an
    * error occurs it stops.
    *
    */
   public long deleteList(XBStore store, Connection conn, XBEntry[] entries, int maxStLength, int maxNumSt, boolean commitInBetween, int timeout) throws SQLException {
      long ret = super.deleteList(store, conn, entries, maxStLength, maxNumSt, commitInBetween, timeout);
      // prepare to delete meats if any:
      List<XBMeat> meatList = new ArrayList<XBMeat>();
      for (int i=0; i < entries.length; i++) {
         XBRef ref = (XBRef)entries[i];
         if (!store.isRefCounted()) {
            XBMeat meat = ref.getMeat();
            if (meat == null) {
               if (ref.getMeatId() == 0)
                  throw new SQLException("The reference " + ref.toXml("") + " has 'oneToMany' set to false but has no meat defined: this is not allowed");
               meat = new XBMeat(ref.getMeatId());
            }
            meatList.add(meat);
         }
      }
      if (meatList.size() > 0) {
         XBEntry[] meatEntries = (XBEntry[])meatList.toArray(new XBEntry[meatList.size()]);
         meatFactory.deleteList(store, conn, meatEntries, maxStLength, maxNumSt, commitInBetween, timeout);
      }
      return ret;
   }

}
TOP

Related Classes of org.xmlBlaster.util.queue.jdbc.XBRefFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.