use of org.h2.mvstore.Cursor in project h2database by h2database.
the class ResultTempTable method addRow.
@Override
public int addRow(Value[] values) {
Row row = convertToRow(values);
if (distinct) {
Cursor cursor = find(row);
if (cursor == null) {
table.addRow(session, row);
rowCount++;
}
} else {
table.addRow(session, row);
rowCount++;
}
return rowCount;
}
use of org.h2.mvstore.Cursor in project h2database by h2database.
the class MVSpatialIndex method add.
@Override
public void add(Session session, Row row) {
TransactionMap<SpatialKey, Value> map = getMap(session);
SpatialKey key = getKey(row);
if (key.isNull()) {
return;
}
if (indexType.isUnique()) {
// this will detect committed entries only
RTreeCursor cursor = spatialMap.findContainedKeys(key);
Iterator<SpatialKey> it = map.wrapIterator(cursor, false);
while (it.hasNext()) {
SpatialKey k = it.next();
if (k.equalsIgnoringId(key)) {
throw getDuplicateKeyException(key.toString());
}
}
}
try {
map.put(key, ValueLong.get(0));
} catch (IllegalStateException e) {
throw mvTable.convertException(e);
}
if (indexType.isUnique()) {
// check if there is another (uncommitted) entry
RTreeCursor cursor = spatialMap.findContainedKeys(key);
Iterator<SpatialKey> it = map.wrapIterator(cursor, true);
while (it.hasNext()) {
SpatialKey k = it.next();
if (k.equalsIgnoringId(key)) {
if (map.isSameTransaction(k)) {
continue;
}
map.remove(key);
if (map.get(k) != null) {
// committed
throw getDuplicateKeyException(k.toString());
}
throw DbException.get(ErrorCode.CONCURRENT_UPDATE_1, table.getName());
}
}
}
}
use of org.h2.mvstore.Cursor in project h2database by h2database.
the class ArchiveToolStore method expand.
private void expand(String targetDir) throws Exception {
start();
long tempSize = 8 * 1024 * 1024;
String tempFileName = fileName + ".temp";
FileUtils.createDirectories(targetDir);
MVStore store = new MVStore.Builder().fileName(fileName).open();
MVMap<String, int[]> files = store.openMap("files");
System.out.println("Extracting " + files.size() + " files");
MVStore storeTemp = null;
FileUtils.delete(tempFileName);
long totalSize = 0;
int lastSegment = 0;
for (int i = 1; ; i++) {
if (!store.hasMap("data" + i)) {
lastSegment = i - 1;
break;
}
}
storeTemp = new MVStore.Builder().fileName(tempFileName).autoCommitDisabled().open();
MVMap<Integer, String> fileNames = storeTemp.openMap("fileNames");
MVMap<String, int[]> filesTemp = storeTemp.openMap("files");
int fileId = 0;
for (Entry<String, int[]> e : files.entrySet()) {
fileNames.put(fileId++, e.getKey());
filesTemp.put(e.getKey(), e.getValue());
totalSize += e.getValue().length / 4;
}
storeTemp.commit();
files = filesTemp;
long currentSize = 0;
int chunkSize = 0;
for (int s = 1; s <= lastSegment; s++) {
MVMap<int[], byte[]> segmentData = store.openMap("data" + s);
// key: fileId, blockId; value: data
MVMap<int[], byte[]> fileData = storeTemp.openMap("fileData" + s);
fileId = 0;
for (Entry<String, int[]> e : files.entrySet()) {
int[] keys = e.getValue();
if (keys.length == 1) {
fileId++;
continue;
}
for (int i = 0; i < keys.length; i += 4) {
int[] dk = new int[4];
dk[0] = keys[i];
dk[1] = keys[i + 1];
dk[2] = keys[i + 2];
dk[3] = keys[i + 3];
byte[] bytes = segmentData.get(dk);
if (bytes != null) {
int[] k = new int[] { fileId, i / 4 };
fileData.put(k, bytes);
chunkSize += bytes.length;
if (chunkSize > tempSize) {
storeTemp.commit();
chunkSize = 0;
}
currentSize++;
printProgress(0, 50, currentSize, totalSize);
}
}
fileId++;
}
storeTemp.commit();
}
ArrayList<Cursor<int[], byte[]>> list = New.arrayList();
totalSize = 0;
currentSize = 0;
for (int i = 1; i <= lastSegment; i++) {
MVMap<int[], byte[]> fileData = storeTemp.openMap("fileData" + i);
totalSize += fileData.sizeAsLong();
Cursor<int[], byte[]> c = fileData.cursor(null);
if (c.hasNext()) {
c.next();
list.add(c);
}
}
String lastFileName = null;
OutputStream file = null;
int[] lastKey = null;
while (list.size() > 0) {
Collections.sort(list, new Comparator<Cursor<int[], byte[]>>() {
@Override
public int compare(Cursor<int[], byte[]> o1, Cursor<int[], byte[]> o2) {
int[] k1 = o1.getKey();
int[] k2 = o2.getKey();
int comp = 0;
for (int i = 0; i < k1.length; i++) {
long x1 = k1[i];
long x2 = k2[i];
if (x1 > x2) {
comp = 1;
break;
} else if (x1 < x2) {
comp = -1;
break;
}
}
return comp;
}
});
Cursor<int[], byte[]> top = list.get(0);
int[] key = top.getKey();
byte[] bytes = top.getValue();
String f = targetDir + "/" + fileNames.get(key[0]);
if (!f.equals(lastFileName)) {
if (file != null) {
file.close();
}
String p = FileUtils.getParent(f);
if (p != null) {
FileUtils.createDirectories(p);
}
file = new BufferedOutputStream(new FileOutputStream(f));
lastFileName = f;
} else {
if (key[0] != lastKey[0] || key[1] != lastKey[1] + 1) {
System.out.println("missing entry after " + Arrays.toString(lastKey));
}
}
lastKey = key;
file.write(bytes);
if (!top.hasNext()) {
list.remove(0);
} else {
top.next();
}
currentSize++;
printProgress(50, 100, currentSize, totalSize);
}
for (Entry<String, int[]> e : files.entrySet()) {
String f = targetDir + "/" + e.getKey();
int[] keys = e.getValue();
if (keys.length == 1) {
FileUtils.createDirectories(f);
} else if (keys.length == 0) {
// empty file
String p = FileUtils.getParent(f);
if (p != null) {
FileUtils.createDirectories(p);
}
new FileOutputStream(f).close();
}
}
if (file != null) {
file.close();
}
store.close();
storeTemp.close();
FileUtils.delete(tempFileName);
System.out.println();
printDone();
}
use of org.h2.mvstore.Cursor in project h2database by h2database.
the class ArchiveToolStore method compress.
private void compress(String sourceDir) throws Exception {
start();
long tempSize = 8 * 1024 * 1024;
String tempFileName = fileName + ".temp";
ArrayList<String> fileNames = New.arrayList();
System.out.println("Reading the file list");
long totalSize = addFiles(sourceDir, fileNames);
System.out.println("Compressing " + totalSize / MB + " MB");
FileUtils.delete(tempFileName);
FileUtils.delete(fileName);
MVStore storeTemp = new MVStore.Builder().fileName(tempFileName).autoCommitDisabled().open();
final MVStore store = new MVStore.Builder().fileName(fileName).pageSplitSize(2 * 1024 * 1024).compressHigh().autoCommitDisabled().open();
MVMap<String, int[]> filesTemp = storeTemp.openMap("files");
long currentSize = 0;
int segmentId = 1;
int segmentLength = 0;
ByteBuffer buff = ByteBuffer.allocate(1024 * 1024);
for (String s : fileNames) {
String name = s.substring(sourceDir.length() + 1);
if (FileUtils.isDirectory(s)) {
// directory
filesTemp.put(name, new int[1]);
continue;
}
buff.clear();
buff.flip();
ArrayList<Integer> posList = new ArrayList<>();
try (FileChannel fc = FileUtils.open(s, "r")) {
boolean eof = false;
while (true) {
while (!eof && buff.remaining() < 512 * 1024) {
int remaining = buff.remaining();
buff.compact();
buff.position(remaining);
int l = fc.read(buff);
if (l < 0) {
eof = true;
}
buff.flip();
}
if (buff.remaining() == 0) {
break;
}
int position = buff.position();
int c = getChunkLength(buff.array(), position, buff.limit()) - position;
byte[] bytes = Arrays.copyOfRange(buff.array(), position, position + c);
buff.position(position + c);
int[] key = getKey(bucket, bytes);
key[3] = segmentId;
while (true) {
MVMap<int[], byte[]> data = storeTemp.openMap("data" + segmentId);
byte[] old = data.get(key);
if (old == null) {
// new
data.put(key, bytes);
break;
}
if (Arrays.equals(old, bytes)) {
// duplicate
break;
}
// same checksum: change checksum
key[2]++;
}
for (int i = 0; i < key.length; i++) {
posList.add(key[i]);
}
segmentLength += c;
currentSize += c;
if (segmentLength > tempSize) {
storeTemp.commit();
segmentId++;
segmentLength = 0;
}
printProgress(0, 50, currentSize, totalSize);
}
}
int[] posArray = new int[posList.size()];
for (int i = 0; i < posList.size(); i++) {
posArray[i] = posList.get(i);
}
filesTemp.put(name, posArray);
}
storeTemp.commit();
ArrayList<Cursor<int[], byte[]>> list = New.arrayList();
totalSize = 0;
for (int i = 1; i <= segmentId; i++) {
MVMap<int[], byte[]> data = storeTemp.openMap("data" + i);
totalSize += data.sizeAsLong();
Cursor<int[], byte[]> c = data.cursor(null);
if (c.hasNext()) {
c.next();
list.add(c);
}
}
segmentId = 1;
segmentLength = 0;
currentSize = 0;
MVMap<int[], byte[]> data = store.openMap("data" + segmentId);
MVMap<int[], Boolean> keepSegment = storeTemp.openMap("keep");
while (list.size() > 0) {
Collections.sort(list, new Comparator<Cursor<int[], byte[]>>() {
@Override
public int compare(Cursor<int[], byte[]> o1, Cursor<int[], byte[]> o2) {
int[] k1 = o1.getKey();
int[] k2 = o2.getKey();
int comp = 0;
for (int i = 0; i < k1.length - 1; i++) {
long x1 = k1[i];
long x2 = k2[i];
if (x1 > x2) {
comp = 1;
break;
} else if (x1 < x2) {
comp = -1;
break;
}
}
return comp;
}
});
Cursor<int[], byte[]> top = list.get(0);
int[] key = top.getKey();
byte[] bytes = top.getValue();
int[] k2 = Arrays.copyOf(key, key.length);
k2[key.length - 1] = 0;
// TODO this lookup can be avoided
// if we remember the last entry with k[..] = 0
byte[] old = data.get(k2);
if (old == null) {
if (segmentLength > tempSize) {
// switch only for new entries
// where segmentId is 0,
// so that entries with the same
// key but different segmentId
// are in the same segment
store.commit();
segmentLength = 0;
segmentId++;
data = store.openMap("data" + segmentId);
}
key = k2;
// new entry
data.put(key, bytes);
segmentLength += bytes.length;
} else if (Arrays.equals(old, bytes)) {
// duplicate
} else {
// almost a duplicate:
// keep segment id
keepSegment.put(key, Boolean.TRUE);
data.put(key, bytes);
segmentLength += bytes.length;
}
if (!top.hasNext()) {
list.remove(0);
} else {
top.next();
}
currentSize++;
printProgress(50, 100, currentSize, totalSize);
}
MVMap<String, int[]> files = store.openMap("files");
for (Entry<String, int[]> e : filesTemp.entrySet()) {
String k = e.getKey();
int[] ids = e.getValue();
if (ids.length == 1) {
// directory
files.put(k, ids);
continue;
}
int[] newIds = Arrays.copyOf(ids, ids.length);
for (int i = 0; i < ids.length; i += 4) {
int[] id = new int[4];
id[0] = ids[i];
id[1] = ids[i + 1];
id[2] = ids[i + 2];
id[3] = ids[i + 3];
if (!keepSegment.containsKey(id)) {
newIds[i + 3] = 0;
}
}
files.put(k, newIds);
}
store.commit();
storeTemp.close();
FileUtils.delete(tempFileName);
store.close();
System.out.println();
System.out.println("Compressed to " + FileUtils.size(fileName) / MB + " MB");
printDone();
}
use of org.h2.mvstore.Cursor in project h2database by h2database.
the class H2Database method rawQuery.
/**
* Execute the query.
*
* @param sql the SQL statement
* @param selectionArgs the parameter values
* @return the cursor
*/
public Cursor rawQuery(String sql, String[] selectionArgs) {
Prepared prep = prepare(sql, selectionArgs);
ResultInterface result = prep.query(0);
return new H2Cursor(result);
}
Aggregations