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

COVERAGE SUMMARY FOR SOURCE FILE [MultiVersionCursor.java]

nameclass, %method, %block, %line, %
MultiVersionCursor.java100% (1/1)100% (8/8)49%  (181/369)50%  (48.2/96)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MultiVersionCursor100% (1/1)100% (8/8)49%  (181/369)50%  (48.2/96)
next (): boolean 100% (1/1)28%  (51/184)27%  (15/56)
getSearchRow (): SearchRow 100% (1/1)40%  (12/30)60%  (3/5)
get (): Row 100% (1/1)60%  (18/30)55%  (2.8/5)
previous (): boolean 100% (1/1)65%  (11/17)88%  (2.6/3)
step (Cursor): boolean 100% (1/1)67%  (6/9)66%  (0.7/1)
loadNext (boolean): void 100% (1/1)76%  (34/45)84%  (8.4/10)
loadCurrent (): void 100% (1/1)83%  (25/30)97%  (6.8/7)
MultiVersionCursor (Session, MultiVersionIndex, Cursor, Cursor, Object): void 100% (1/1)100% (24/24)100% (9/9)

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.index;
7 
8import org.h2.engine.Session;
9import org.h2.engine.SysProperties;
10import org.h2.message.DbException;
11import org.h2.result.Row;
12import org.h2.result.SearchRow;
13import org.h2.util.MathUtils;
14 
15/**
16 * The cursor implementation for the multi-version index.
17 */
18public class MultiVersionCursor implements Cursor {
19 
20    private final MultiVersionIndex index;
21    private final Session session;
22    private final Cursor baseCursor, deltaCursor;
23    private final Object sync;
24    private SearchRow baseRow;
25    private Row deltaRow;
26    private boolean onBase;
27    private boolean end;
28    private boolean needNewDelta, needNewBase;
29    private boolean reverse;
30 
31    MultiVersionCursor(Session session, MultiVersionIndex index, Cursor base,
32            Cursor delta, Object sync) {
33        this.session = session;
34        this.index = index;
35        this.baseCursor = base;
36        this.deltaCursor = delta;
37        this.sync = sync;
38        needNewDelta = true;
39        needNewBase = true;
40    }
41 
42    /**
43     * Load the current row.
44     */
45    void loadCurrent() {
46        synchronized (sync) {
47            baseRow = baseCursor.getSearchRow();
48            deltaRow = deltaCursor.get();
49            needNewDelta = false;
50            needNewBase = false;
51        }
52    }
53 
54    private void loadNext(boolean base) {
55        synchronized (sync) {
56            if (base) {
57                if (step(baseCursor)) {
58                    baseRow = baseCursor.getSearchRow();
59                } else {
60                    baseRow = null;
61                }
62            } else {
63                if (step(deltaCursor)) {
64                    deltaRow = deltaCursor.get();
65                } else {
66                    deltaRow = null;
67                }
68            }
69        }
70    }
71 
72    private boolean step(Cursor cursor) {
73        return reverse ? cursor.previous() : cursor.next();
74    }
75 
76    @Override
77    public Row get() {
78        synchronized (sync) {
79            if (end) {
80                return null;
81            }
82            return onBase ? baseCursor.get() : deltaCursor.get();
83        }
84    }
85 
86    @Override
87    public SearchRow getSearchRow() {
88        synchronized (sync) {
89            if (end) {
90                return null;
91            }
92            return onBase ? baseCursor.getSearchRow() : deltaCursor.getSearchRow();
93        }
94    }
95 
96    @Override
97    public boolean next() {
98        synchronized (sync) {
99            if (SysProperties.CHECK && end) {
100                DbException.throwInternalError();
101            }
102            while (true) {
103                if (needNewDelta) {
104                    loadNext(false);
105                    needNewDelta = false;
106                }
107                if (needNewBase) {
108                    loadNext(true);
109                    needNewBase = false;
110                }
111                if (deltaRow == null) {
112                    if (baseRow == null) {
113                        end = true;
114                        return false;
115                    }
116                    onBase = true;
117                    needNewBase = true;
118                    return true;
119                }
120                int sessionId = deltaRow.getSessionId();
121                boolean isThisSession = sessionId == session.getId();
122                boolean isDeleted = deltaRow.isDeleted();
123                if (isThisSession && isDeleted) {
124                    needNewDelta = true;
125                    continue;
126                }
127                if (baseRow == null) {
128                    if (isDeleted) {
129                        if (isThisSession) {
130                            end = true;
131                            return false;
132                        }
133                        // the row was deleted by another session: return it
134                        onBase = false;
135                        needNewDelta = true;
136                        return true;
137                    }
138                    DbException.throwInternalError();
139                }
140                int compare = index.compareRows(deltaRow, baseRow);
141                if (compare == 0) {
142                    // can't use compareKeys because the
143                    // version would be compared as well
144                    long k1 = deltaRow.getKey();
145                    long k2 = baseRow.getKey();
146                    compare = MathUtils.compareLong(k1, k2);
147                }
148                if (compare == 0) {
149                    if (isDeleted) {
150                        if (isThisSession) {
151                            DbException.throwInternalError();
152                        }
153                        // another session updated the row
154                    } else {
155                        if (isThisSession) {
156                            onBase = false;
157                            needNewBase = true;
158                            needNewDelta = true;
159                            return true;
160                        }
161                        // another session inserted the row: ignore
162                        needNewBase = true;
163                        needNewDelta = true;
164                        continue;
165                    }
166                }
167                if (compare > 0) {
168                    onBase = true;
169                    needNewBase = true;
170                    return true;
171                }
172                onBase = false;
173                needNewDelta = true;
174                return true;
175            }
176        }
177    }
178 
179    @Override
180    public boolean previous() {
181        reverse = true;
182        try {
183            return next();
184        } finally {
185            reverse = false;
186        }
187    }
188 
189}

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