EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.result]

COVERAGE SUMMARY FOR SOURCE FILE [RowList.java]

nameclass, %method, %block, %line, %
RowList.java100% (1/1)100% (13/13)96%  (480/502)96%  (125.8/131)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RowList100% (1/1)100% (13/13)96%  (480/502)96%  (125.8/131)
writeRow (Data, Row): void 100% (1/1)83%  (80/96)83%  (19.9/24)
readRow (Data): Row 100% (1/1)93%  (80/86)95%  (23.9/25)
RowList (Session): void 100% (1/1)100% (22/22)100% (7/7)
add (Row): void 100% (1/1)100% (31/31)100% (6/6)
close (): void 100% (1/1)100% (16/16)100% (6/6)
flushBuffer (Data): void 100% (1/1)100% (24/24)100% (6/6)
hasNext (): boolean 100% (1/1)100% (9/9)100% (1/1)
initBuffer (Data): void 100% (1/1)100% (6/6)100% (3/3)
invalidateCache (): void 100% (1/1)100% (4/4)100% (2/2)
next (): Row 100% (1/1)100% (96/96)100% (20/20)
reset (): void 100% (1/1)100% (25/25)100% (9/9)
size (): int 100% (1/1)100% (3/3)100% (1/1)
writeAllRows (): void 100% (1/1)100% (84/84)100% (21/21)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.result;
7 
8import java.util.ArrayList;
9import org.h2.engine.Constants;
10import org.h2.engine.Database;
11import org.h2.engine.Session;
12import org.h2.store.Data;
13import org.h2.store.FileStore;
14import org.h2.util.New;
15import org.h2.value.Value;
16 
17/**
18 * A list of rows. If the list grows too large, it is buffered to disk
19 * automatically.
20 */
21public class RowList {
22 
23    private final Session session;
24    private final ArrayList<Row> list = New.arrayList();
25    private int size;
26    private int index, listIndex;
27    private FileStore file;
28    private Data rowBuff;
29    private ArrayList<Value> lobs;
30    private final int maxMemory;
31    private int memory;
32    private boolean written;
33    private boolean readUncached;
34 
35    /**
36     * Construct a new row list for this session.
37     *
38     * @param session the session
39     */
40    public RowList(Session session) {
41        this.session = session;
42        if (session.getDatabase().isPersistent()) {
43            maxMemory = session.getDatabase().getMaxOperationMemory();
44        } else {
45            maxMemory = 0;
46        }
47    }
48 
49    private void writeRow(Data buff, Row r) {
50        buff.checkCapacity(1 + Data.LENGTH_INT * 8);
51        buff.writeByte((byte) 1);
52        buff.writeInt(r.getMemory());
53        int columnCount = r.getColumnCount();
54        buff.writeInt(columnCount);
55        buff.writeLong(r.getKey());
56        buff.writeInt(r.getVersion());
57        buff.writeInt(r.isDeleted() ? 1 : 0);
58        buff.writeInt(r.getSessionId());
59        for (int i = 0; i < columnCount; i++) {
60            Value v = r.getValue(i);
61            buff.checkCapacity(1);
62            if (v == null) {
63                buff.writeByte((byte) 0);
64            } else {
65                buff.writeByte((byte) 1);
66                if (v.getType() == Value.CLOB || v.getType() == Value.BLOB) {
67                    // need to keep a reference to temporary lobs,
68                    // otherwise the temp file is deleted
69                    if (v.getSmall() == null && v.getTableId() == 0) {
70                        if (lobs == null) {
71                            lobs = New.arrayList();
72                        }
73                        // need to create a copy, otherwise,
74                        // if stored multiple times, it may be renamed
75                        // and then not found
76                        v = v.copyToTemp();
77                        lobs.add(v);
78                    }
79                }
80                buff.checkCapacity(buff.getValueLen(v));
81                buff.writeValue(v);
82            }
83        }
84    }
85 
86    private void writeAllRows() {
87        if (file == null) {
88            Database db = session.getDatabase();
89            String fileName = db.createTempFile();
90            file = db.openFile(fileName, "rw", false);
91            file.setCheckedWriting(false);
92            file.seek(FileStore.HEADER_LENGTH);
93            rowBuff = Data.create(db, Constants.DEFAULT_PAGE_SIZE);
94            file.seek(FileStore.HEADER_LENGTH);
95        }
96        Data buff = rowBuff;
97        initBuffer(buff);
98        for (int i = 0, size = list.size(); i < size; i++) {
99            if (i > 0 && buff.length() > Constants.IO_BUFFER_SIZE) {
100                flushBuffer(buff);
101                initBuffer(buff);
102            }
103            Row r = list.get(i);
104            writeRow(buff, r);
105        }
106        flushBuffer(buff);
107        file.autoDelete();
108        list.clear();
109        memory = 0;
110    }
111 
112    private static void initBuffer(Data buff) {
113        buff.reset();
114        buff.writeInt(0);
115    }
116 
117    private void flushBuffer(Data buff) {
118        buff.checkCapacity(1);
119        buff.writeByte((byte) 0);
120        buff.fillAligned();
121        buff.setInt(0, buff.length() / Constants.FILE_BLOCK_SIZE);
122        file.write(buff.getBytes(), 0, buff.length());
123    }
124 
125    /**
126     * Add a row to the list.
127     *
128     * @param r the row to add
129     */
130    public void add(Row r) {
131        list.add(r);
132        memory += r.getMemory() + Constants.MEMORY_POINTER;
133        if (maxMemory > 0 && memory > maxMemory) {
134            writeAllRows();
135        }
136        size++;
137    }
138 
139    /**
140     * Remove all rows from the list.
141     */
142    public void reset() {
143        index = 0;
144        if (file != null) {
145            listIndex = 0;
146            if (!written) {
147                writeAllRows();
148                written = true;
149            }
150            list.clear();
151            file.seek(FileStore.HEADER_LENGTH);
152        }
153    }
154 
155    /**
156     * Check if there are more rows in this list.
157     *
158     * @return true it there are more rows
159     */
160    public boolean hasNext() {
161        return index < size;
162    }
163 
164    private Row readRow(Data buff) {
165        if (buff.readByte() == 0) {
166            return null;
167        }
168        int mem = buff.readInt();
169        int columnCount = buff.readInt();
170        long key = buff.readLong();
171        int version = buff.readInt();
172        if (readUncached) {
173            key = 0;
174        }
175        boolean deleted = buff.readInt() == 1;
176        int sessionId = buff.readInt();
177        Value[] values = new Value[columnCount];
178        for (int i = 0; i < columnCount; i++) {
179            Value v;
180            if (buff.readByte() == 0) {
181                v = null;
182            } else {
183                v = buff.readValue();
184                if (v.isLinked()) {
185                    // the table id is 0 if it was linked when writing
186                    // a temporary entry
187                    if (v.getTableId() == 0) {
188                        session.unlinkAtCommit(v);
189                    }
190                }
191            }
192            values[i] = v;
193        }
194        Row row = new Row(values, mem);
195        row.setKey(key);
196        row.setVersion(version);
197        row.setDeleted(deleted);
198        row.setSessionId(sessionId);
199        return row;
200    }
201 
202    /**
203     * Get the next row from the list.
204     *
205     * @return the next row
206     */
207    public Row next() {
208        Row r;
209        if (file == null) {
210            r = list.get(index++);
211        } else {
212            if (listIndex >= list.size()) {
213                list.clear();
214                listIndex = 0;
215                Data buff = rowBuff;
216                buff.reset();
217                int min = Constants.FILE_BLOCK_SIZE;
218                file.readFully(buff.getBytes(), 0, min);
219                int len = buff.readInt() * Constants.FILE_BLOCK_SIZE;
220                buff.checkCapacity(len);
221                if (len - min > 0) {
222                    file.readFully(buff.getBytes(), min, len - min);
223                }
224                while (true) {
225                    r = readRow(buff);
226                    if (r == null) {
227                        break;
228                    }
229                    list.add(r);
230                }
231            }
232            index++;
233            r = list.get(listIndex++);
234        }
235        return r;
236    }
237 
238    /**
239     * Get the number of rows in this list.
240     *
241     * @return the number of rows
242     */
243    public int size() {
244        return size;
245    }
246 
247    /**
248     * Do not use the cache.
249     */
250    public void invalidateCache() {
251        readUncached = true;
252    }
253 
254    /**
255     * Close the result list and delete the temporary file.
256     */
257    public void close() {
258        if (file != null) {
259            file.autoDelete();
260            file.closeAndDeleteSilently();
261            file = null;
262            rowBuff = null;
263        }
264    }
265 
266}

[all classes][org.h2.result]
EMMA 2.0.5312 (C) Vladimir Roubtsov