001: package com.quadcap.sql;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.IOException;
042:
043: import java.util.ArrayList;
044: import java.util.Iterator;
045:
046: import java.sql.SQLException;
047:
048: import com.quadcap.sql.file.BlockFile;
049: import com.quadcap.sql.file.RandomAccess;
050:
051: import com.quadcap.util.ConfigNumber;
052: import com.quadcap.util.Debug;
053: import com.quadcap.util.Util;
054:
055: /**
056: * StatementContext which manages delete operations generated by a
057: * statement, defers those operations so consistency can be checked,
058: * and at the end of the statement's execution, performs all of the
059: * deletes.
060: *
061: * @author Stan Bailes
062: */
063: public class DeletedRows implements StatementContext {
064: Session session;
065: Table table;
066: ArrayList rowIds = new ArrayList();
067: RandomAccess ra = null;
068: long raBlock = 0;
069: long raSize = 0;
070:
071: /*{com.quadcap.sql.Datafile-conn.xml-50}
072: * <config-var>
073: * <config-name>qed.deletedRowCache</config-name>
074: * <config-dflt>1000</config-dflt>
075: * <config-desc>
076: * Maximum number of deleted rows before we go to disk.
077: * </config-desc>
078: * </config-var>
079: */
080: protected static final ConfigNumber maxList = ConfigNumber.find(
081: "qed.deletedRowCache", "1000");
082:
083: /**
084: * Constructor: session and table
085: */
086: public DeletedRows(Session session, Table table) throws IOException {
087: this .session = session;
088: this .table = table;
089: }
090:
091: /**
092: * Remember to delete 'rowId'
093: */
094: public void addEntry(long rowId) throws IOException, SQLException {
095: if (rowIds != null) {
096: if (rowIds.size() >= maxList.intValue()) {
097: // ---- start temp stream
098: BlockFile f = session.getDatabase().getTempFile();
099: raBlock = f.newPage();
100: ra = f.getStream(raBlock);
101: ra.resize(rowIds.size() * 8);
102: Iterator iter = rowIds.iterator();
103: raSize = 0;
104: while (iter.hasNext()) {
105: long v = ((Long) iter.next()).longValue();
106: ra.writeLong(raSize, v);
107: raSize += 8;
108: }
109: rowIds = null;
110: } else {
111: rowIds.add(new Long(rowId));
112: }
113: }
114: if (ra != null) {
115: ra.resize(raSize + 8);
116: ra.writeLong(raSize, rowId);
117: raSize += 8;
118: }
119:
120: }
121:
122: /**
123: * Showtime -- unless aborted, delete all the rows and free our
124: * resources
125: */
126: public void finish(boolean abort) throws SQLException, IOException {
127: LazyRow row = new LazyRow(table.getColumnCount());
128: Database db = session.getDatabase();
129:
130: if (rowIds != null) {
131: if (!abort) {
132: Iterator iter = rowIds.iterator();
133: while (iter.hasNext()) {
134: long rowId = ((Long) iter.next()).longValue();
135: if (table.hasBlobs()) {
136: db.getRow(rowId, row, false);
137: TableOps.freeBlobsInRow(session, table, row);
138: }
139: session
140: .doStep(new DeleteRow(session, table, rowId));
141: }
142: }
143: rowIds = null;
144: } else if (ra != null) {
145: if (!abort) {
146: for (int pos = 0; pos < raSize; pos += 8) {
147: long rowId = ra.readLong(pos);
148: if (table.hasBlobs()) {
149: db.getRow(rowId, row, false);
150: TableOps.freeBlobsInRow(session, table, row);
151: }
152: session
153: .doStep(new DeleteRow(session, table, rowId));
154: }
155: }
156: // not using BlockFile.freeStream here because we already
157: // have 'ra', this saves gc'ing a BlockAcess object.
158: ra.resize(0);
159: BlockFile f = session.getDatabase().getTempFile(false);
160: f.freePage(raBlock);
161: session.getDatabase().releaseTempFile();
162: ra = null;
163: }
164: }
165:
166: /**
167: * Whatever
168: */
169: public int priority() {
170: return 4;
171: }
172: }
|