summaryrefslogtreecommitdiffstats
path: root/rasodmg
diff options
context:
space:
mode:
authorConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
committerConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
commit8f27e65bddd7d4b8515ce620fb485fdd78fcdf89 (patch)
treebd328a4dd4f92d32202241b5e3a7f36177792c5f /rasodmg
downloadrasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.gz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.xz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.zip
Initial commitv8.0
Diffstat (limited to 'rasodmg')
-rw-r--r--rasodmg/Makefile.am58
-rw-r--r--rasodmg/alignedtiling.cc635
-rw-r--r--rasodmg/alignedtiling.hh211
-rw-r--r--rasodmg/alignedtiling.icc31
-rw-r--r--rasodmg/collection.cc627
-rw-r--r--rasodmg/collection.hh224
-rw-r--r--rasodmg/collection.icc73
-rw-r--r--rasodmg/database.cc475
-rw-r--r--rasodmg/database.hh270
-rw-r--r--rasodmg/database.icc38
-rw-r--r--rasodmg/dirdecompose.cc147
-rw-r--r--rasodmg/dirdecompose.hh114
-rw-r--r--rasodmg/dirtiling.cc682
-rw-r--r--rasodmg/dirtiling.hh133
-rw-r--r--rasodmg/gmarray.cc484
-rw-r--r--rasodmg/gmarray.hh185
-rw-r--r--rasodmg/gmarray.icc119
-rw-r--r--rasodmg/interesttiling.cc809
-rw-r--r--rasodmg/interesttiling.hh183
-rw-r--r--rasodmg/iterator.cc216
-rw-r--r--rasodmg/iterator.hh137
-rw-r--r--rasodmg/iterator.icc39
-rw-r--r--rasodmg/marray.cc354
-rw-r--r--rasodmg/marray.hh145
-rw-r--r--rasodmg/marray.icc31
-rw-r--r--rasodmg/object.cc603
-rw-r--r--rasodmg/object.hh240
-rw-r--r--rasodmg/object.icc151
-rw-r--r--rasodmg/oqlquery.cc628
-rw-r--r--rasodmg/oqlquery.hh251
-rw-r--r--rasodmg/oqlquery.icc52
-rw-r--r--rasodmg/partinsert.cc199
-rw-r--r--rasodmg/partinsert.hh109
-rw-r--r--rasodmg/polycutout.cc709
-rw-r--r--rasodmg/polycutout.hh162
-rw-r--r--rasodmg/polygon.cc879
-rw-r--r--rasodmg/polygon.hh287
-rw-r--r--rasodmg/ref.cc656
-rw-r--r--rasodmg/ref.hh323
-rw-r--r--rasodmg/ref.icc64
-rw-r--r--rasodmg/set.cc92
-rw-r--r--rasodmg/set.hh79
-rw-r--r--rasodmg/stattiling.cc678
-rw-r--r--rasodmg/stattiling.hh210
-rw-r--r--rasodmg/storagelayout.cc182
-rw-r--r--rasodmg/storagelayout.hh132
-rw-r--r--rasodmg/storagelayout.icc31
-rw-r--r--rasodmg/test/Makefile372
-rw-r--r--rasodmg/test/Makefile.dep0
-rw-r--r--rasodmg/test/cmov_16.ql425
-rw-r--r--rasodmg/test/cmov_32.ql425
-rw-r--r--rasodmg/test/cmov_64.ql425
-rw-r--r--rasodmg/test/croll_16.ql180
-rw-r--r--rasodmg/test/croll_32.ql180
-rw-r--r--rasodmg/test/croll_64.ql180
-rw-r--r--rasodmg/test/croll_sliced.ql180
-rw-r--r--rasodmg/test/csel_16.ql43
-rw-r--r--rasodmg/test/csel_32.ql43
-rw-r--r--rasodmg/test/csel_64.ql43
-rw-r--r--rasodmg/test/csel_sliced.ql43
-rw-r--r--rasodmg/test/defconv.cc598
-rw-r--r--rasodmg/test/defdiff.cc537
-rw-r--r--rasodmg/test/defutil.hh412
-rw-r--r--rasodmg/test/deletecollection.cc720
-rw-r--r--rasodmg/test/earth.ql68
-rw-r--r--rasodmg/test/earth_16.ql41
-rw-r--r--rasodmg/test/earth_32.ql41
-rw-r--r--rasodmg/test/earth_64.ql41
-rw-r--r--rasodmg/test/gen_pattern.cc248
-rw-r--r--rasodmg/test/gen_query.pl116
-rw-r--r--rasodmg/test/gen_rollup.pl209
-rw-r--r--rasodmg/test/gen_s2k.pl65
-rw-r--r--rasodmg/test/init_fast_collection.pl111
-rw-r--r--rasodmg/test/polytest.poly3
-rw-r--r--rasodmg/test/rasql.cc126
-rw-r--r--rasodmg/test/rasql.hh38
-rw-r--r--rasodmg/test/readln.cc64
-rw-r--r--rasodmg/test/readln.hh45
-rw-r--r--rasodmg/test/runbm.sh94
-rw-r--r--rasodmg/test/small_16.ql42
-rw-r--r--rasodmg/test/small_32.ql42
-rw-r--r--rasodmg/test/small_64.ql42
-rw-r--r--rasodmg/test/stat1.dat3
-rw-r--r--rasodmg/test/stat2.dat7
-rw-r--r--rasodmg/test/stat3.dat4
-rw-r--r--rasodmg/test/system_basic.cc1945
-rw-r--r--rasodmg/test/system_basic.hh210
-rw-r--r--rasodmg/test/system_compare.cc273
-rw-r--r--rasodmg/test/system_compare.hh40
-rw-r--r--rasodmg/test/system_insert.cc384
-rw-r--r--rasodmg/test/system_insert.hh43
-rw-r--r--rasodmg/test/system_query.cc400
-rw-r--r--rasodmg/test/system_query.hh37
-rw-r--r--rasodmg/test/system_update.cc399
-rw-r--r--rasodmg/test/system_update.hh40
-rw-r--r--rasodmg/test/test_alignedtiling.cc126
-rw-r--r--rasodmg/test/test_all.sh9
-rw-r--r--rasodmg/test/test_benchmark.cc273
-rw-r--r--rasodmg/test/test_bmark_dir.cc257
-rw-r--r--rasodmg/test/test_bmark_dir1.cc318
-rw-r--r--rasodmg/test/test_bmark_int.cc241
-rw-r--r--rasodmg/test/test_bmark_int1.cc242
-rw-r--r--rasodmg/test/test_bmark_pet.cc235
-rw-r--r--rasodmg/test/test_bmark_stat.cc331
-rw-r--r--rasodmg/test/test_breakdown.cc112
-rw-r--r--rasodmg/test/test_collection.cc116
-rw-r--r--rasodmg/test/test_comp_conv.sh325
-rw-r--r--rasodmg/test/test_db2blob.sqC399
-rw-r--r--rasodmg/test/test_dirtiling.cc93
-rw-r--r--rasodmg/test/test_fastscale.cc293
-rw-r--r--rasodmg/test/test_gmarray.cc229
-rw-r--r--rasodmg/test/test_insert.cc235
-rw-r--r--rasodmg/test/test_insert3.cc843
-rw-r--r--rasodmg/test/test_interesttiling.cc97
-rw-r--r--rasodmg/test/test_iterator.cc135
-rw-r--r--rasodmg/test/test_lookup.cc378
-rw-r--r--rasodmg/test/test_marray.cc110
-rw-r--r--rasodmg/test/test_oqlquery.cc157
-rw-r--r--rasodmg/test/test_polygon.cc951
-rw-r--r--rasodmg/test/test_query.cc693
-rw-r--r--rasodmg/test/test_ref.cc69
-rw-r--r--rasodmg/test/test_set.cc104
-rw-r--r--rasodmg/test/test_stattiling.cc173
-rw-r--r--rasodmg/test/test_storage.cc282
-rw-r--r--rasodmg/test/test_transaction.cc152
-rw-r--r--rasodmg/test/tmov_16.ql425
-rw-r--r--rasodmg/test/tmov_32.ql425
-rw-r--r--rasodmg/test/tmov_64.ql425
-rw-r--r--rasodmg/test/tomo_ops.ql27
-rw-r--r--rasodmg/test/tomo_select.ql72
-rw-r--r--rasodmg/test/troll_16.ql180
-rw-r--r--rasodmg/test/troll_32.ql180
-rw-r--r--rasodmg/test/troll_64.ql180
-rw-r--r--rasodmg/test/troll_sliced.ql180
-rw-r--r--rasodmg/test/tsel_16.ql43
-rw-r--r--rasodmg/test/tsel_32.ql43
-rw-r--r--rasodmg/test/tsel_64.ql43
-rw-r--r--rasodmg/test/tsel_sliced.ql43
-rw-r--r--rasodmg/tiling.cc309
-rw-r--r--rasodmg/tiling.hh228
-rw-r--r--rasodmg/transaction.cc377
-rw-r--r--rasodmg/transaction.hh167
-rw-r--r--rasodmg/transaction.icc46
143 files changed, 34535 insertions, 0 deletions
diff --git a/rasodmg/Makefile.am b/rasodmg/Makefile.am
new file mode 100644
index 0000000..a2da39c
--- /dev/null
+++ b/rasodmg/Makefile.am
@@ -0,0 +1,58 @@
+# -*-Makefile-*- (for Emacs)
+#
+# This file is part of rasdaman community.
+#
+# Rasdaman community is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Rasdaman community is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+#
+# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+# rasdaman GmbH.
+#
+# For more information please see <http://www.rasdaman.org>
+# or contact Peter Baumann via <baumann@rasdaman.com>.
+#
+# MAKEFILE FOR:
+# module rasodmg
+#
+# COMMENTS:
+#
+##################################################################
+
+AM_CXXFLAGS=@CLIENTCXXFLAGS@
+AM_LDFLAGS=@CLIENTLDFLAGS@
+
+noinst_LIBRARIES=librasodmg.a
+
+librasodmg_a_SOURCES = collection.cc collection.hh collection.icc \
+ set.cc set.hh \
+ iterator.cc iterator.hh iterator.icc \
+ marray.cc marray.hh marray.icc \
+ ref.cc ref.hh ref.icc \
+ transaction.cc transaction.hh transaction.icc \
+ oqlquery.cc oqlquery.hh oqlquery.icc \
+ object.cc object.hh object.icc \
+ database.cc database.hh database.icc \
+ gmarray.cc gmarray.hh gmarray.icc \
+ storagelayout.cc storagelayout.hh storagelayout.icc \
+ tiling.cc tiling.hh \
+ alignedtiling.cc alignedtiling.hh alignedtiling.icc \
+ dirtiling.cc dirtiling.hh \
+ dirdecompose.cc dirdecompose.hh \
+ interesttiling.cc interesttiling.hh \
+ stattiling.cc stattiling.hh \
+ partinsert.cc partinsert.hh \
+ polygon.cc polygon.hh \
+ polycutout.cc polycutout.hh
+
+CLEANFILES = core
+
diff --git a/rasodmg/alignedtiling.cc b/rasodmg/alignedtiling.cc
new file mode 100644
index 0000000..13313f4
--- /dev/null
+++ b/rasodmg/alignedtiling.cc
@@ -0,0 +1,635 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: alignedtiling.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_AlignedTiling, r_DefaultTiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <vector>
+#include <math.h>
+#include <cstring>
+#include <cstdlib>
+
+#include "rasodmg/alignedtiling.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/rminit.hh"
+
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream>
+#endif
+
+const char*
+r_Aligned_Tiling::description = "tile configuration or tile dimension and tile size (in bytes) (ex: \"[0:9,0:9];100\" or \"2;100\")";
+
+r_Aligned_Tiling::r_Aligned_Tiling(const char* encoded) throw (r_Error)
+ : r_Dimension_Tiling(0, 0)
+ {
+
+ if(!encoded)
+ {
+ RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << (encoded?encoded: "NULL") << ")" << std::endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ r_Bytes tileS=0, lenToConvert=0;
+ r_Minterval* tileConf=NULL;
+ r_Dimension tileD=0;
+ bool state=false; //false for "tileconf;tilesize", true for "tiledim,tilesize"
+ const char *pStart=NULL, *pRes=NULL, *pEnd=NULL;
+ char *pToConvert=NULL;
+ pStart=encoded;
+ pEnd=pStart+strlen(pStart);
+ pRes=strstr(pStart, COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile configuration from tilingparams." << std::endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with first param
+ lenToConvert=pRes-pStart;
+ pToConvert = new char[lenToConvert+1];
+ memcpy(pToConvert,pStart,lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ if(*pToConvert == *LSQRBRA)
+ {
+ try
+ {
+ tileConf=new r_Minterval(pToConvert);
+ }
+ catch(r_Error& err)
+ {
+ RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile configuration \"" << pToConvert << "\" from tileparams." << std::endl;
+ RMInit::logOut << "Error " << err.get_errorno() << " : " << err.what() << std::endl;
+ delete [] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ }
+ else
+ {
+ tileD=strtol(pToConvert, (char**)NULL, DefaultBase);
+ if (!tileD)
+ {
+ RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile dimension \"" << pToConvert << "\" from tileparams." << std::endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileD < 0)
+ {
+ RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile dimension \"" << pToConvert << "\" from tileparams." << std::endl;
+ RMInit::logOut << "Dimension is negative." << std::endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ }
+
+ //skip COLON
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tiling, end of stream." << std::endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with second param
+ tileS=strtol(pRes,(char**) NULL, DefaultBase);
+ if (!tileS)
+ {
+ RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile size \"" << pRes << "\"." << std::endl;
+
+ if(tileConf)
+ delete tileConf;
+
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileS < 0)
+ {
+ RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile size \"" << pRes << "\", is negative." << std::endl;
+ if(tileConf)
+ delete tileConf;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //detect state
+ if(tileConf)
+ {
+ tile_config = *tileConf;
+ dimension = tile_config.dimension();
+ tile_size = tileS;
+ delete tileConf;
+ }
+ else
+ {
+ tile_config = r_Minterval(tileD);
+ dimension = tileD;
+ tile_size = tileS;
+ }
+
+ }
+
+r_Aligned_Tiling::r_Aligned_Tiling(r_Dimension dim, r_Bytes ts) throw (r_Error)
+ : r_Dimension_Tiling(dim, ts),
+ tile_config(dim)
+{
+ /// Default tile configuration - equal sides
+ for(r_Dimension i = 0; i < dim ; i++)
+ tile_config << r_Sinterval((r_Range)0, (r_Range)1);
+}
+
+r_Aligned_Tiling::r_Aligned_Tiling(const r_Minterval& tc, r_Bytes ts) throw (r_Error)
+ : r_Dimension_Tiling(tc.dimension(), ts),
+ tile_config(tc)
+{
+}
+
+r_Tiling*
+r_Aligned_Tiling::clone() const
+{
+ r_Aligned_Tiling* newAT = new r_Aligned_Tiling(tile_config, tile_size);
+ return newAT;
+}
+
+r_Aligned_Tiling::~r_Aligned_Tiling()
+{
+ tile_config.r_deactivate();
+}
+
+const r_Minterval&
+r_Aligned_Tiling::get_tile_config() const
+{
+ return tile_config;
+}
+
+r_Minterval
+r_Aligned_Tiling::compute_tile_domain(const r_Minterval& dom, r_Bytes cell_size) const
+{
+RMDBGENTER(3, RMDebug::module_rasodmg, "r_Aligned_Tiling", "compute_tile_domain(" << dom << ", " << cell_size << ")")
+ // Minimum optimal tile size. Below this value, the waste will be too big.
+ r_Bytes optMinTileSize = get_min_opt_tile_size();
+
+ // number of cells per tile according to storage options
+ r_Area numCellsTile = tile_size / cell_size;
+
+ // For final result.
+ r_Minterval tileDomain(dimension);
+
+ int startIx = -1;
+
+ for (r_Dimension i = 0; i < dimension ; i++)
+ {
+ if (tile_config[i].is_low_fixed() == 0 ||
+ tile_config[i].is_high_fixed() == 0)
+ startIx = i;
+ }
+ if (startIx >= 0) // Some limits are nonfixed
+ {
+ unsigned long size = cell_size;
+ int i;
+
+ for(i = startIx; i >=0 ; i--) // treat the non fixed limits first
+ {
+ r_Range l, h;
+
+ // If any of the limits is non-fixed along this direction, tiles
+ // will extend from one side to the other along this direction.
+ if ((tile_config[i].is_low_fixed() == 0) ||
+ (tile_config[i].is_high_fixed() == 0))
+ {
+
+ l = dom[i].low();
+ h = dom[i].high();
+
+ /*
+ Alternative interpretation of tile_config with non fixed limits
+ For the time being is useless because the splittile algorithm
+ doesn't take into account the origin of the tile
+ if (tile_config[i].is_low_fixed() == 0)
+ l = contentsDomain[i].low();
+ else
+ l = tile_config[i].low();
+ if (tileconfig[i].is_high_fixed() == 0)
+ h = contentsDomain[i].high();
+ else
+ h = tile_config[i].high();
+ */
+
+ if(size * (h - l + 1) > tile_size)
+ {
+ h = tile_size/size + l - 1;
+ }
+ size = size * (h - l + 1);
+ tileDomain[i] = r_Sinterval(r_Range(l) ,r_Range(h));
+ }
+ }
+ for(i = dimension-1; i >=0 ; i--) // treat fixed limits now
+ {
+ r_Range l, h;
+
+ // If any of the limits is non-fixed along this direction, tiles
+ // will extend from one side to the other along this direction.
+ if ((tile_config[i].is_low_fixed() != 0) &&
+ (tile_config[i].is_high_fixed() != 0))
+ {
+ l = tile_config[i].low();
+ h = tile_config[i].high();
+
+ if(size * (h - l + 1) > tile_size)
+ {
+ h = tile_size/size + l - 1;
+ }
+ size = size * (h - l + 1);
+ tileDomain[i] = r_Sinterval(r_Range(l) ,r_Range(h));
+ }
+ }
+
+ RMDBGEXIT(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "calculateTileDomain result : " << tileDomain <<std::endl)
+ return tileDomain;
+ }
+ else // tile_config has only fixed limits
+ {
+ unsigned long numCellsTileConfig = tile_config.cell_count();
+ unsigned long sizeTileConfig = numCellsTileConfig * cell_size;
+
+ if (sizeTileConfig > get_min_opt_tile_size() && sizeTileConfig < tile_size)
+ {
+ RMDBGEXIT(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "calculateTileDomain result : " << tile_config)
+ return tile_config;
+ }
+ else
+ {
+ float sizeFactor = (float) numCellsTile / numCellsTileConfig;
+
+ float f = float (1/ float(dimension));
+ float dimFactor = (float)pow(sizeFactor, f);
+ RMDBGMIDDLE(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "dim factor == " << dimFactor)
+
+ unsigned long l, h;
+ unsigned long newWidth;
+
+ // extending the bound of each r_Sinterval of tile_config by
+ // using the factor dimFactor
+ for (int i = 0; i < dimension ; i++)
+ {
+ l = tile_config[i].low();
+ h = tile_config[i].high();
+ newWidth = (unsigned long) ((h - l + 1) * dimFactor);
+ if (newWidth < 1) newWidth = 1;
+ tileDomain << r_Sinterval(r_Range(l), r_Range(l + newWidth - 1));
+ }
+
+ // Approximate the resulting tile size to the target one:
+
+ /*
+ r_Minterval tmpTileDomain =
+ get_opt_size(tileDomain, cell_size);
+ tileDomain = tmpTileDomain;
+ */
+
+/*
+ unsigned long sz = tileDomain.cell_count() * cell_size;
+
+ RMDBGOUT(2,"cell_size " << cell_size << " tileDomain "<< tileDomain << std::endl)
+ RMDBGOUT(2,"cell_count == " << tileDomain.cell_count() << " sz == " << sz << std::endl)
+
+ unsigned long newSz = sz;
+ for(i = dimension-1; i >= 0 && newSz < tile_size ; i--)
+ {
+ RMDBGOUT(2, "inside the cycle " << std::endl)
+ unsigned long deltaSz = cell_size;
+ for (int j = 0 ; j < dimension ; j++)
+ if (j != i)
+ deltaSz *= (tileDomain[j].high()-tileDomain[j].low()+1);
+
+ h = tileDomain[i].high();
+ if (deltaSz + newSz <= tile_size)
+ {
+ tileDomain[i].set_high(r_Range(h + 1));
+ newSz += deltaSz;
+ }
+ }
+*/
+
+ if (tileDomain.cell_count() * cell_size > tile_size)
+ RMDBGMIDDLE(2, RMDebug::module_rasodmg, "Error in r_Aligned_Tiling", "calculateTileDomain() " << std::endl);
+ if (tileDomain.cell_count() * cell_size < optMinTileSize)
+ RMDBGMIDDLE(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "calculateTileDomain() result non optimal " << std::endl);
+
+ RMDBGEXIT(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "calculateTileDomain result : " << tileDomain << std::endl)
+ // cout << "return 3"<<std::endl;
+ return tileDomain;
+ }
+ }
+}
+
+std::vector<r_Minterval>*
+r_Aligned_Tiling::compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error)
+{
+ std::vector<r_Minterval>* result = new std::vector<r_Minterval>;
+
+ r_Dimension dim = tile_config.dimension();
+
+ r_Minterval bigDom = obj_domain;
+
+ r_Minterval tileDom = compute_tile_domain(obj_domain, cell_size);
+
+ // cout << "r_Aligned_Tiling::compute_tiles() " << tileDom << std::endl;
+
+ r_Minterval currDom(tileDom.dimension());
+ r_Point cursor(tileDom.dimension());
+ r_Point tileSize;
+ r_Point origin;
+ int done = 0;
+
+ // initialize cursor
+ for(dim = 0; dim < cursor.dimension(); dim++)
+ cursor[dim] = 0;
+
+ // calculate size of Tiles
+ tileSize = tileDom.get_extent();
+
+ // origin of bigTile
+ origin = bigDom.get_origin();
+
+ // initialize currDom
+ for(dim=0; dim < cursor.dimension(); dim++)
+ currDom << r_Sinterval((r_Range) (origin[dim]), (r_Range) (origin[dim] + tileSize[dim] - 1));
+ // resets tileDom to lower left side of bigTile
+ tileDom = currDom;
+
+ // intersect with bigTile
+ currDom.intersection_with(bigDom);
+
+ // iterate with smallTile over bigTile
+ while(!done)
+ {
+ currDom.intersection_with(bigDom);
+
+ // create new smallTile
+ r_Minterval smallTile(dim);
+
+ smallTile = currDom;
+
+ // insert tile in set
+ result->push_back(smallTile);
+
+ // increment cursor, start with highest dimension
+ long i = cursor.dimension() - 1;
+ cursor[(unsigned int)i] += tileSize[(unsigned int)i];
+ // move cursor
+ currDom = tileDom.create_translation(cursor);
+ while(!(currDom.intersects_with(bigDom)))
+ {
+ cursor[(unsigned int)i] = 0;
+ i--;
+ if(i < 0)
+ {
+ done = 1;
+ break;
+ }
+ cursor[(unsigned int)i] += tileSize[(unsigned int)i];
+ // move cursor
+ currDom = tileDom.create_translation(cursor);
+ }
+ }
+ return result;
+}
+
+r_Minterval
+r_Aligned_Tiling::get_opt_size(const r_Minterval& tileDomain, r_Bytes cellSize) const
+{
+
+ unsigned long tileSize = get_tile_size();
+ unsigned long newSize = tileDomain.cell_count() * cellSize;
+ r_Minterval result = tileDomain;
+ r_Dimension dim = tileDomain.dimension();
+ int* ixArr = new int[dim];
+ int* tmpIxArr = new int[dim];
+ r_Minterval tmpResult = result;
+ int j;
+
+ for (j = 0; j < dim; j++)
+ ixArr[j] = j;
+
+ for(j = dim - 1; j >=0 && newSize < tileSize ; j--)
+ {
+ int i=0;
+ unsigned long h, wd;
+ unsigned minWidthIx = 0;
+ unsigned long minWidth = tileDomain[0].high()-tileDomain[0].low()+1;
+ for(int k = j; k >=0 ; k--)
+ {
+ i = ixArr[k];
+
+ h = result[i].high() + 1;
+ wd = result[i].high() - result[i].low() + 1;
+ if (wd < minWidth)
+ {
+ minWidth = wd;
+ minWidthIx = i;
+ }
+ }
+
+ int tmpIx = ixArr[j];
+ ixArr[minWidthIx] = tmpIx;
+
+ tmpResult[minWidthIx].set_high(r_Range(h));
+ newSize = tmpResult.cell_count() * cellSize;
+ if (newSize > tileSize)
+ {
+ for(i = dim-1; i >=0 ; i--)
+ {
+ h = result[i].high() + 1;
+ wd = result[i].high() - result[i].low() + 1;
+ if (wd < minWidth)
+ {
+ minWidth = wd;
+ minWidthIx = i;
+ }
+ }
+ }
+
+ result[minWidthIx].set_high(r_Range(h));
+ newSize = result.cell_count() * cellSize;
+ if (newSize > tileSize)
+ {
+ result[minWidthIx].set_high(r_Range(h - 1));
+ }
+ }
+ delete[] ixArr;
+ return result;
+}
+
+r_Tiling_Scheme
+r_Aligned_Tiling::get_tiling_scheme() const
+{
+ return r_AlignedTiling;
+}
+
+r_Bytes
+r_Aligned_Tiling::get_min_opt_tile_size() const
+{
+ return (get_tile_size() - get_tile_size()/10);
+}
+
+char*
+r_Aligned_Tiling::get_string_representation() const
+{
+
+ unsigned int bufferSize = 25; // should be enough!
+
+ // allocate buffer and initialize string stream
+ char* buffer = new char[bufferSize];
+ std::ostrstream domainStream(buffer, bufferSize);
+
+ // write into string stream
+
+ print_status(domainStream);
+ domainStream << std::ends;
+
+ // allocate memory taking the final string
+ char* returnString = strdup(buffer);
+
+ // delete buffer
+ delete[] buffer;
+
+ return returnString;
+}
+
+void
+r_Aligned_Tiling::print_status(std::ostream& os) const
+{
+ os << "r_Aligned_Tiling[ ";
+ r_Dimension_Tiling::print_status(os);
+ os << " tile configuration = "<< tile_config <<" ]";
+}
+
+/*
+std::ostream&
+operator<<(std::ostream& s, const r_Aligned_Tiling& at)
+{
+ at.print_status(s);
+ return s;
+}
+*/
+
+/*
+std::vector<r_Minterval>*
+r_Default_Tiling::compute_tiles(const r_Minterval& obj_domain, long cell_size)
+ const
+{
+ std::vector<r_Minterval>* result = new std::vector<r_Minterval>;
+
+ RMDBGENTER(4, RMDebug::module_rasodmg, "r_Default_Tiling", "compute_tiles")
+
+
+ r_Minterval bigDom = obj_domain;
+
+ r_Minterval tileDom(bigDom.dimension());
+
+ // compute the domain of the small tiles
+ // tiles are n-dimensional cubes with edge length n-th root of max tile size
+ //old implementations:
+ //long edgeLength = (long)floor(exp((1/(double)tileDom.dimension())*
+ // log(RMInit::tileSize/mar->get_type_length())));
+ //long edgeLength = (long)floor(exp((1/(double)tileDom.dimension())*
+ // log(get_tile_size()/cell_size)));
+
+ RMDBGMIDDLE(4, RMDebug::module_rasodmg, "r_Default_Tiling", "tile size == " << get_tile_size())
+ long edgeLength = (long) floor(pow(get_tile_size()/cell_size,
+ 1/(double)tileDom.dimension()));
+ r_Dimension dim;
+
+ for(dim=0; dim<tileDom.dimension(); dim++)
+ tileDom << r_Sinterval((r_Range)0, (r_Range)edgeLength-1);
+
+ r_Minterval currDom(tileDom.dimension());
+ r_Point cursor(tileDom.dimension());
+ r_Point tileSize;
+ r_Point origin;
+ int done = 0;
+
+ // initialize cursor
+ for(dim = 0; dim < cursor.dimension(); dim++)
+ cursor[dim] = 0;
+
+ // calculate size of Tiles
+ tileSize = tileDom.get_extent();
+
+ // origin of bigTile
+ origin = bigDom.get_origin();
+
+ // initialize currDom
+ for(dim=0; dim < cursor.dimension(); dim++)
+ currDom << r_Sinterval((r_Range) (origin[dim]), (r_Range) (origin[dim] + tileSize[dim] - 1));
+ // resets tileDom to lower left side of bigTile
+ tileDom = currDom;
+
+ // intersect with bigTile
+ currDom.intersection_with(bigDom);
+
+ // iterate with smallTile over bigTile
+ while(!done)
+ {
+ currDom.intersection_with(bigDom);
+
+ // create new smallTile
+ r_Minterval smallTile(dim);
+
+ smallTile = currDom;
+
+ // insert tile in set
+ result->push_back(smallTile);
+
+ // increment cursor, start with highest dimension
+ long i = cursor.dimension() - 1;
+ cursor[(unsigned int)i] += tileSize[(unsigned int)i];
+ // move cursor
+ currDom = tileDom.create_translation(cursor);
+ while(!(currDom.intersects_with(bigDom)))
+ {
+ cursor[(unsigned int)i] = 0;
+ i--;
+ if(i < 0)
+ {
+ done = 1;
+ break;
+ }
+ cursor[(unsigned int)i] += tileSize[(unsigned int)i];
+ // move cursor
+ currDom = tileDom.create_translation(cursor);
+ }
+ }
+ RMDBGEXIT(4, RMDebug::module_rasodmg, "r_Default_Tiling", "compute_tiles")
+ return result;
+}
+*/
diff --git a/rasodmg/alignedtiling.hh b/rasodmg/alignedtiling.hh
new file mode 100644
index 0000000..ba8c2a4
--- /dev/null
+++ b/rasodmg/alignedtiling.hh
@@ -0,0 +1,211 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: alignedtiling.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Aligned_Tiling, r_Default_Tiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_ALIGNEDTILING_HH_
+#define _R_ALIGNEDTILING_HH_
+
+class r_Aligned_Tiling;
+
+#include "rasodmg/tiling.hh"
+#include "raslib/minterval.hh"
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The {\tt r_Aligned_Tiling} class is used to express the options
+ for aligned tiling of {\tt r_Marray} objects.
+
+ The following options may be set:
+
+ \begin{itemize}
+ \item {\bf Tile configuration}
+
+ describes which format tiles should have. The tile configuration
+ is expressed using a multidimensional interval {\tt r_Minterval}.
+ This interval should have null lower limits and
+ must have the same dimensionality as that of the
+ objects to which it is to be applied. Its lengths along each
+ direction are interpreted relative to the others.
+
+ For example, if tile configuration is {\tt[ 0:9, 0:9, 0:19]}, tiles
+ will be three dimensional arrays with two sides of equal length and
+ double that length along the third direction.
+
+ If a fixed tile is required, tile configuration and
+ tile size should be set in such a way that the size of a tile
+ with the given configuration is equal to the specified tile size.
+ For example, if the tile configuration is {\tt [ 0:29, 0:39, 0:59]}
+ and cell size is 2, then the tile size should be set to
+ 144000. This will also result in more efficient computation of
+ the tiling since the given tile configuration is used unchanged if
+
+ {\tt 90% * tile_size < size of tile_config < tile_size}
+
+ (i.e., no computation is necessary). This applies equally to tile
+ configurations with non-fixed limits.
+
+ Tiles with non-fixed limits are used to express preferential
+ directions for tiling. For example, {\tt [ 0:9 , 0:* ]} expresses that
+ tiles should be done along the first direction, i.e., they
+ should have domains :
+
+ \begin{verbatim}
+ [ 0 : 9 , 0 : marray.domain[1].high() ]
+ [ 10 : 19 , 0 : marray.domain[1].high() ]
+ ...
+ \end{verbatim}
+
+ assuming this results in a tile with the given tile size. If not,
+ the limits in the first direction are changed. The higher dimensions
+ are given preference in that tiles will be preferably
+ extended along a higher dimension than a lower one if two or
+ more limits are open.
+
+ The default configuration corresponds to an interval with equal
+ lengths along all directions.
+
+ \item {\bf Tile size }
+
+ describes the size for tiles of the object in characters.
+ Tiling is done so that tiles are as big as possible but wit a
+ smaller size than this one.
+ The default tile size is the size specified for the RasDaMan client.
+
+ Notice: the tiling options are invalid if the rasdaman client is running
+ with the option notiling. In that case, no tiling is done,
+ independently of the storage layout chosen.
+*/
+
+class r_Aligned_Tiling : public r_Dimension_Tiling
+{
+ public:
+ /// read everything from encoded string
+ /// (e.g. "[0:9,0:9];100" or "2;100")
+ r_Aligned_Tiling(const char* encoded) throw (r_Error);
+
+ /// dimension and tile size.
+ r_Aligned_Tiling(r_Dimension dim, r_Bytes ts = RMInit::clientTileSize) throw (r_Error);
+
+ /// dimension and tile size will be taken from RMInit::clientTileSize.
+ //r_Aligned_Tiling(r_Dimension dim) throw (r_Error);
+
+ /// tile configuration and tile size.
+ r_Aligned_Tiling(const r_Minterval& tc, r_Bytes ts = RMInit::clientTileSize) throw (r_Error);
+
+ virtual r_Tiling* clone() const;
+
+ virtual ~r_Aligned_Tiling();
+
+ /// returns the current value for the tile configuration option
+ const r_Minterval& get_tile_config() const;
+
+ std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error);
+
+ char* get_string_representation() const;
+ /**
+ The string representation delivered by this method is allocated using
+ {\tt malloc()} and has to be freed using {\tt free()} in the end.
+ */
+
+ /// writes the state of the object to the specified stream
+ void print_status(std::ostream& s = cout) const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ static const char* description;
+
+ protected:
+
+ /// determines the individual tiles domains
+ r_Minterval compute_tile_domain(const r_Minterval& dom, r_Bytes cell_size) const;
+ /**
+ Determines the individual tiles domains for aligned tiling,
+ using the options expressed in this object.
+ Takes into account the tile size and the tile configuration,
+ as well as the cell size given by {\ttcell_size}.
+
+ Returns the domain for tiles in such a way that the tile
+ configuration is as close to {\tttile_config} set in this object and
+ the size is lower than {\tt tile_size}.
+
+ The origin of the returned interval is the same as that from
+ {\ttthis->tile_config}.
+
+ The data to partition has domain {\tt dom } and cells with size
+ {\tt cell_size}.
+ To be used before splitting a tile with domain {\tt dom} (typically,
+ containing all the cells belonging to an {\ttr_Marray} object).
+ */
+
+ /// tile configuration
+ r_Minterval tile_config;
+
+ ///
+ r_Bytes get_min_opt_tile_size() const;
+
+ ///
+ r_Minterval get_opt_size(const r_Minterval& tile_domain, r_Bytes cell_size) const;
+};
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The {\tt r_Default_Tiling} class is used to express the default tiling
+ of {\tt r_Marray} objects. According to this algorithm, tiles are divided
+ into equal sized multidimensional blocks qith equal lengths along
+ all directions of the spatial domain.
+
+ The following parameter may be set:
+
+ \item {\bf Tile size }
+
+ describes the size for tiles of the object in characters.
+ Tiling is done so that tiles have a smaller size than this one.
+ The default tile size is the size specified for the RasDaMan client.
+ In bytes.
+*/
+
+
+//@ManMemo: Module: {\bf rasodmg }
+/**
+ Output stream operator for objects of type {\tt const}
+ \Ref{r_Aligned_Tiling}.
+*/
+//extern std::ostream& operator<<(std::ostream& s, const r_Aligned_Tiling& at);
+
+#endif
+
+
+
+
diff --git a/rasodmg/alignedtiling.icc b/rasodmg/alignedtiling.icc
new file mode 100644
index 0000000..6abeb23
--- /dev/null
+++ b/rasodmg/alignedtiling.icc
@@ -0,0 +1,31 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: storage.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Storage
+ *
+ * COMMENTS:
+ * None
+*/
diff --git a/rasodmg/collection.cc b/rasodmg/collection.cc
new file mode 100644
index 0000000..c5da7de
--- /dev/null
+++ b/rasodmg/collection.cc
@@ -0,0 +1,627 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: collection.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Collection
+ *
+ * COMMENTS:
+ * None
+*/
+
+using namespace std;
+
+static const char rcsidcollection[] = "@(#)rasodmg, r_Collection: $Id: collection.cc,v 1.53 2005/07/06 23:30:22 rasdev Exp $";
+
+#include "raslib/rmdebug.hh"
+#include "raslib/collectiontype.hh"
+
+#include "rasodmg/collection.hh"
+#include "rasodmg/iterator.hh"
+#include "rasodmg/database.hh"
+
+#include "clientcomm/clientcomm.hh"
+#include <string.h>
+
+#ifndef __GNUG__
+#define NULL 0
+#endif
+
+template<class T>
+r_Collection<T>::r_Collection() throw(r_Error)
+ : r_Object( 2 ), card(0)
+{
+ init_node_list( coll );
+ init_node_list( removed_objects );
+}
+
+
+template<class T>
+r_Collection<T>::r_Collection( const r_Collection<T>& collection ) throw(r_Error)
+ : r_Object( collection, 2 )
+{
+ CNode* nptr;
+ CNode* optr;
+
+ coll = new CNode;
+ nptr = coll;
+ optr = collection.coll;
+
+ while ( optr->next != NULL )
+ {
+ nptr->next = new CNode;
+ nptr->elem = new T;
+ *(nptr->elem) = *(optr->elem);
+ nptr = nptr->next;
+ optr = optr->next;
+ }
+ if ( optr->elem != NULL )
+ {
+ nptr->elem = new T;
+ *(nptr->elem) = *(optr->elem);
+ }
+
+ nptr->next = NULL;
+ card = collection.cardinality();
+
+ init_node_list( removed_objects );
+}
+
+template<class T>
+r_Collection<T>::r_Collection( const void* node1 )
+{
+ // This constructor is nearly the same as a copy constrctor,
+ // except that the argument is not of type r_Collection but
+ // of type CNode* (the collection's internal representation).
+ // Does the same as function set_internal_representation.
+
+ // We assume that node1 is a correct CNode structure as
+ // defined in collection.hh
+ // copy it and determine cardinality
+ CNode* nptr;
+ CNode* optr;
+
+ card = 0;
+ coll = new CNode;
+ nptr = coll;
+ optr = (CNode*)node1;
+
+ while ( optr->next != NULL )
+ {
+ nptr->next = new CNode;
+ nptr->elem = new T;
+ card++;
+ *(nptr->elem) = *(optr->elem);
+ nptr = nptr->next;
+ optr = optr->next;
+ }
+ if ( optr->elem != NULL )
+ {
+ nptr->elem = new T;
+ card++;
+ *(nptr->elem) = *(optr->elem);
+ }
+
+ nptr->next = NULL;
+
+ init_node_list( removed_objects );
+}
+
+template<class T>
+r_Collection<T>::~r_Collection()
+{
+ RMDBGONCE(1, RMDebug::module_rasodmg, "r_Collection<T>", "~r_Collection")
+
+ r_deactivate();
+}
+
+
+
+/*************************************************************
+ * Method name...: r_deactivate()
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: This method is called when the object leaves
+ * the application cache. It frees all dynamic
+ * memory allocated within the class.
+ ************************************************************/
+template<class T>
+void
+r_Collection<T>::r_deactivate()
+{
+ RMDBGONCE(1, RMDebug::module_rasodmg, "r_Collection<T>", "r_deactivate()")
+
+ remove_all_nodes( coll );
+ remove_all_nodes( removed_objects );
+}
+
+
+
+template<class T>
+int
+r_Collection<T>::contains_element( const T& element ) const
+{
+ CNode* ptr = coll;
+
+ while ( *(ptr->elem) != element && ptr->next != NULL )
+ ptr = ptr->next;
+
+ if ( *(ptr->elem) == element )
+ return true;
+ else
+ return false;
+}
+
+template<class T>
+void
+r_Collection<T>::insert_element( const T& element, int no_modification )
+{
+ // add node to list...
+ add_node( coll, element );
+
+ // increase cardinaltity
+ card++;
+
+ // ...and remove it from removed objects if it exists
+ remove_node( removed_objects, element );
+
+ if( !no_modification )
+ mark_modified(); // remember modification
+}
+
+template<class T>
+void
+r_Collection<T>::remove_element( const T& element )
+{
+ // remove node from list...
+ if( remove_node( coll, element ) )
+ {
+ // ...and add it to removed objects list
+ add_node( removed_objects, element );
+
+ // decrease cardinality
+ card--;
+
+ mark_modified(); // remember modification
+ }
+}
+
+template<class T>
+void
+r_Collection<T>::remove_all()
+{
+ CNode* ptr = coll;
+ CNode* ptrLast = coll;
+
+ if ( ptr->elem != NULL )
+ {
+ add_node( removed_objects, *ptr->elem );
+ delete ptr->elem;
+ ptr->elem = NULL;
+ }
+ if ( ptr->next != NULL )
+ {
+ ptr = ptr->next;
+ while ( ptr->next != NULL )
+ {
+ add_node( removed_objects, *ptr->elem );
+ delete ptr->elem;
+ ptrLast = ptr;
+ ptr = ptr->next;
+ delete ptrLast;
+ }
+ delete ptr->elem;
+ delete ptr;
+ }
+ coll->next = NULL;
+ card = 0;
+
+ mark_modified(); // remember modification
+}
+
+
+
+template<class T>
+const r_Collection<T>&
+r_Collection<T>::operator=( const r_Collection<T>& collection )
+{
+ CNode* nptr;
+ CNode* optr;
+
+ if( this != &collection )
+ {
+ if( coll )
+ remove_all();
+ else
+ coll = new CNode;
+
+ nptr = coll;
+ optr = collection.coll;
+
+ while ( optr->next != NULL )
+ {
+ nptr->next = new CNode;
+ nptr->elem = new T;
+ *(nptr->elem) = *(optr->elem);
+ nptr = nptr->next;
+ optr = optr->next;
+ }
+ if ( optr->elem != NULL )
+ {
+ nptr->elem = new T;
+ *(nptr->elem) = *(optr->elem);
+ }
+
+ nptr->next = NULL;
+ card = collection.cardinality();
+ }
+
+ return *this;
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::set_internal_representation( const void* node1 )
+{
+ // We assume that node1 is a correct CNode structure as
+ // defined in collection.hh
+ // copy it and determine cardinality
+ CNode* nptr;
+ CNode* optr;
+
+ if( coll )
+ remove_all();
+ else
+ coll = new CNode;
+
+ card = 0;
+ nptr = coll;
+ optr = (CNode*)node1;
+
+ while ( optr->next != NULL )
+ {
+ nptr->next = new CNode;
+ nptr->elem = new T;
+ card++;
+ *(nptr->elem) = *(optr->elem);
+ nptr = nptr->next;
+ optr = optr->next;
+ }
+ if ( optr->elem != NULL )
+ {
+ nptr->elem = new T;
+ card++;
+ *(nptr->elem) = *(optr->elem);
+ }
+
+ nptr->next = NULL;
+}
+
+
+template<class T>
+r_Iterator<T>
+r_Collection<T>::create_removed_iterator()
+{
+ return r_Iterator<T>( *this, 1 );
+}
+
+
+template<class T>
+r_Iterator<T>
+r_Collection<T>::create_iterator()
+{
+ return r_Iterator<T>( *this );
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::insert_obj_into_db()
+{
+ // Insert myself in database only if I have an object name. If the
+ // collection doesn't have a name an exception is thrown.
+ if( !object_name || !strlen( object_name ) )
+ {
+ r_Error err = r_Error( r_Error::r_Error_ObjectUnknown );
+ throw err;
+ }
+
+ // Insert myself in database only if I have a type name, otherwise
+ // an exception is thrown.
+ if( !type_name || !strlen( type_name ) )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClassUndefined );
+ throw err;
+ }
+
+ // Insert myself into the database even if i'm empty.
+// r_Database::actual_database->communication->insertColl( object_name, type_name, get_oid() );
+ r_Database::actual_database->insertColl( object_name, type_name, get_oid() );
+ if( !is_empty() )
+ {
+ r_Iterator<T> iter = create_iterator();
+ for ( iter.reset(); iter.not_done(); iter++ )
+ // Search for *1 for an explanation of the following cast.
+ ((r_Object*)((r_Ref<r_Object>)(*iter)).ptr())->insert_obj_into_db( object_name );
+ }
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::update_obj_in_db()
+{
+ // Update myself in database only if I have an object name. If the
+ // collection doesn't have a name an exception is thrown.
+ if( !object_name || !strlen( object_name ) )
+ {
+ r_Error err = r_Error( r_Error::r_Error_ObjectUnknown );
+ throw err;
+ }
+
+ // inspect collection elements
+ if( !is_empty() )
+ {
+ r_Iterator<T> iter = create_iterator();
+ for ( iter.reset(); iter.not_done(); iter++ )
+ {
+ // *1
+ //
+ // The following is a very ugly cast, but necessary if collection elements are not restricted
+ // to r_Ref objects. Anyway, if the elements are not of type r_Ref, it is not possible to make
+ // them persistent. A workaround would be to call a global function instead having a template
+ // specification for our case.
+ r_Ref<r_Object> ref = (r_Ref<r_Object>)(*iter);
+
+ RMInit::logOut << " Collection object " << ref.get_oid() << " " << std::flush;
+
+ // check if object is loaded
+ if( ref.get_memory_ptr() != 0 )
+ {
+ // Search for *1 for an explanation of the following cast.
+ switch( ((r_Ref<r_Object>)(*iter))->get_status() )
+ {
+ case r_Object::deleted:
+ RMInit::logOut << "state DELETED, not implemented" << endl;
+ RMInit::logOut << "OK" << endl;
+ break;
+
+ case r_Object::created:
+ RMInit::logOut << "state CREATED, writing ... " << std::flush;
+ // Search for *1 for an explanation of the following cast.
+ ((r_Object*)((r_Ref<r_Object>)(*iter)).ptr())->insert_obj_into_db( object_name );
+ RMInit::logOut << "OK" << endl;
+ break;
+
+ case r_Object::modified:
+ RMInit::logOut << "state MODIFIED, not implemented" << endl;
+ break;
+
+ case r_Object::read:
+ RMInit::logOut << "state READ, OK" << endl;
+ break;
+
+ case r_Object::transient:
+ RMInit::logOut << "state TRANSIENT, OK" << endl;
+ break;
+
+ default:
+ RMInit::logOut << "state UNKNOWN" << endl;
+ break;
+ }
+ }
+ else
+ RMInit::logOut << "state NOT LOADED" << endl;
+ }
+ }
+
+ // inspect removed objects
+ if( removed_objects->elem )
+ {
+ r_Iterator<T> iter = create_removed_iterator();
+ for ( iter.reset( 1 ); iter.not_done(); iter++ )
+ {
+ // *1
+ //
+ // The following is a very ugly cast, but necessary if collection elements are not restricted
+ // to r_Ref objects. Anyway, if the elements are not of type r_Ref, it is not possible to make
+ // them persistent. A workaround would be to call a global function instead of having a template
+ // specification for our case.
+ // The oid could also be got by (*iter)->get_oid() from r_Object but in this case, dereferencing
+ // r_Ref would load the object from the server.
+ r_OId currentOId = ((r_Ref<r_Object>)(*iter)).get_oid();
+
+ RMInit::logOut << " Collection object " << currentOId << " " << std::flush;
+
+ RMInit::logOut << "state REMOVED, removing ... " << std::flush;
+ try
+ {
+// r_Database::actual_database->communication->removeObjFromColl( object_name, currentOId );
+ r_Database::actual_database->removeObjFromColl( object_name, currentOId );
+ RMInit::logOut << "OK" << endl;
+ }
+ catch( r_Error& obj )
+ {
+ RMInit::logOut << "FAILED" << endl;
+ RMInit::logOut << obj.what() << endl;
+ }
+ }
+ }
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::add_node( r_Collection<T>::CNode* &root, const T& element )
+{
+ CNode* ptr = root;
+
+ if ( ptr->elem == NULL )
+ {
+ ptr->elem = new T;
+ *(ptr->elem) = element;
+ }
+ else
+ {
+ while ( ptr->next != NULL )
+ ptr = ptr->next;
+
+ ptr->next = new CNode;
+ ptr = ptr->next;
+ ptr->next = NULL;
+ ptr->elem = new T;
+ *(ptr->elem) = element;
+ }
+}
+
+template<class T>
+int
+r_Collection<T>::remove_node( CNode* &root, const T& element )
+{
+ CNode* ptr = root;
+ CNode* ptrLast = root;
+ int success = 0;
+
+ if( ptr && ptr->elem )
+ {
+ // Look for the element or end of list
+ while ( *(ptr->elem) != element && ptr->next != NULL )
+ {
+ ptrLast = ptr;
+ ptr = ptr->next;
+ }
+
+ // If element is found, destroy the element itself.
+ // After that, there are four cases
+ // case 1: The element was the only element of the list
+ // (if so, don't destroy the node itself, only set the elem field NULL)
+ // case 2: The element had no successor
+ // (if so, the node before the element becomes the last node)
+ // case 3: The element had no predecessor
+ // (if so, the node after the element becomes the first node)
+ // case 4: The element had a successor and a prodecessor
+ // (if so, the node after the element becomes the successor of the
+ // node before the element)
+ if ( *(ptr->elem) == element )
+ {
+ success = 1;
+
+ delete ptr->elem;
+ if ( ptr == ptrLast && ptr->next == NULL ) // case 1
+ ptr->elem = NULL;
+ else
+ if ( ptr->next == NULL ) // case 2
+ {
+ ptrLast->next = NULL;
+ delete ptr;
+ }
+ else
+ if ( ptr == ptrLast ) // case 3
+ {
+ root = ptr->next;
+ delete ptr;
+ }
+ else // case 4
+ {
+ ptrLast->next = ptr->next;
+ delete ptr;
+ }
+ }
+ }
+
+ return success;
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::remove_all_nodes( CNode* &root )
+{
+ if( root )
+ {
+ CNode* ptr = root;
+ CNode* ptrLast = root;
+
+ while ( ptr->next != NULL )
+ {
+ delete ptr->elem;
+ ptrLast = ptr;
+ ptr = ptr->next;
+ delete ptrLast;
+ }
+ delete ptr->elem;
+ delete ptr;
+ }
+
+ root = 0;
+}
+
+
+template<class T>
+void
+r_Collection<T>::init_node_list( CNode* &root )
+{
+ root = new CNode;
+ root->next = NULL;
+ root->elem = NULL;
+}
+
+
+
+template<class T>
+const r_Type*
+r_Collection<T>::get_element_type_schema()
+{
+ const r_Type* typePtr = r_Object::get_type_schema();
+ const r_Type* elementTypePtr = 0;
+
+ if( typePtr )
+ {
+ if( typePtr->type_id() == r_Type::COLLECTIONTYPE )
+ {
+ const r_Collection_Type* collectionTypePtr = (const r_Collection_Type*)typePtr;
+ elementTypePtr = &(collectionTypePtr->element_type());
+ }
+ }
+
+ return elementTypePtr;
+}
+
+
+
+
+
+
+
+
+
diff --git a/rasodmg/collection.hh b/rasodmg/collection.hh
new file mode 100644
index 0000000..d90eb39
--- /dev/null
+++ b/rasodmg/collection.hh
@@ -0,0 +1,224 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: collection.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Collection
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_COLLECTION_
+#define _D_COLLECTION_
+
+#include "raslib/error.hh"
+#include "rasodmg/object.hh"
+
+template <class T>
+class r_Iterator;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ Basic class of a collection. Possible subclasses are \Ref{r_Set},
+ \Ref{r_Bag} and \Ref{r_List}. The protected members isOrdered and
+ allowsDuplicates are not initialized here, they have to be initialized
+ in the respective subclasses.
+
+*/
+
+template <class T>
+class r_Collection : public r_Object
+{
+ friend class r_Iterator<T>;
+
+ public:
+ /// default constructor
+ r_Collection() throw(r_Error);
+ /// copy constructor
+ r_Collection( const r_Collection<T>& collection ) throw(r_Error);
+ /// virtual destructor
+ virtual ~r_Collection();
+
+ /// it is called when an object leaves transient memory
+ virtual void r_deactivate();
+
+ /// get number of elements
+ inline unsigned long cardinality() const;
+
+ /// tells if the collection is empty or not
+ inline int is_empty() const;
+ /// tells if the collection is ordered or not
+ inline int is_ordered() const;
+ /// tells if the collections allowes duplicates or not
+ inline int allows_duplicates() const;
+
+ /// asks about the containment of a specific element
+ int contains_element( const T& element ) const;
+ /// inserts an alement at the beginning
+ virtual void insert_element( const T& element, int no_modification = 0 );
+ /**
+ The method inserts an element into the collection. If {\tt no_modification}
+ is set, the {\tt mark_modified()} method of r_Object is not invoked and, therefore,
+ a modification will not be recognized at the commit point.
+ */
+ /// removes an element
+ virtual void remove_element( const T& element );
+ /// removes all elements
+ void remove_all();
+
+ /// assignment operator
+ const r_Collection<T>& operator=( const r_Collection<T>& collection );
+
+ /// create an iterator pointing at the first element in the collection
+ r_Iterator<T> create_iterator();
+
+ /// get base type schema
+ const r_Type* get_element_type_schema();
+
+ //@Man: Methods for database communication (internal use only):
+ //@{
+ ///
+
+ /// insert myself into the database
+ virtual void insert_obj_into_db();
+
+ /// inserts an object into a specific collection in the database
+ virtual void insert_obj_into_db( const char* ){;};
+ /**
+ The method has no functionality in this class. It supposed to be removed in
+ future.
+ */
+
+ /// update myself
+ virtual void update_obj_in_db();
+
+ ///
+ //@}
+
+ //@Man: Constructors/Methods for internal use only:
+ //@{
+ ///
+
+ /// constructor getting an internal collection representation
+ r_Collection( const void* node1 );
+ ///
+ inline void* get_internal_representation() const;
+ ///
+ void set_internal_representation( const void* node1 );
+
+ ///
+ //@}
+
+ protected:
+ ///
+ typedef struct CNode
+ {
+ CNode* next;
+ T* elem;
+ };
+
+ //@Man: Methods/Attributes for maintainance of removed objects
+ //@{
+ ///
+
+ /// create an iterator for removed objects
+ r_Iterator<T> create_removed_iterator();
+
+ ///
+ /// pointer to list of removed elements
+ CNode* removed_objects;
+
+ ///
+ //@}
+
+ //@Man: Attributes storing some state information
+ //@{
+ ///
+ ///
+ int isOrdered;
+ ///
+ int allowsDuplicates;
+ ///
+ unsigned long card;
+ ///
+ //@}
+
+ // Normally, we would have used the following class to implement the
+ // internal structure of a r_Collection. But for RPC's sake, we use
+ // a simple structure. (RPC is not able to transfer C++ objects.)
+ //
+ // template <class T>
+ // class CNode
+ // {
+ // public:
+ // CNode();
+ // CNode( const CNode& cnode );
+ // ~CNode();
+ //
+ // inline CNode* get_next() const;
+ // inline void set_next( const CNode& cnode );
+ // inline T* get_elem() const;
+ // inline void set_elem( const T& element);
+ //
+ // private:
+ // CNode* next;
+ // T* elem;
+ // }
+
+ //@Man: Methods for manipulating CNode lists
+ //@{
+ ///
+
+ ///
+ void add_node( CNode* &root, const T& element );
+ ///
+ int remove_node( CNode* &root, const T& element );
+ ///
+ void remove_all_nodes( CNode* &root );
+ ///
+ void init_node_list( CNode* &root );
+
+ ///
+ //@}
+
+ /// pointer to collection elements
+ CNode* coll;
+};
+
+#include "rasodmg/collection.icc"
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#ifdef __VISUALC__
+#include "collection.cpp"
+#else
+#include "collection.cc"
+#endif
+#endif
+#endif
+
+#endif
diff --git a/rasodmg/collection.icc b/rasodmg/collection.icc
new file mode 100644
index 0000000..59b11ab
--- /dev/null
+++ b/rasodmg/collection.icc
@@ -0,0 +1,73 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: collection.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Collection
+ *
+ * COMMENTS:
+ * None
+*/
+
+template<class T>
+inline unsigned long
+r_Collection<T>::cardinality() const
+{
+ return card;
+}
+
+
+template<class T>
+inline int
+r_Collection<T>::is_empty() const
+{
+ if ( coll->elem )
+ return false;
+ else
+ return true;
+}
+
+
+template<class T>
+inline int
+r_Collection<T>::is_ordered() const
+{
+ return isOrdered;
+}
+
+
+template<class T>
+inline int
+r_Collection<T>::allows_duplicates() const
+{
+ return allowsDuplicates;
+}
+
+
+template<class T>
+inline void*
+r_Collection<T>::get_internal_representation() const
+{
+ return (void*)coll;
+}
diff --git a/rasodmg/database.cc b/rasodmg/database.cc
new file mode 100644
index 0000000..bdf11b0
--- /dev/null
+++ b/rasodmg/database.cc
@@ -0,0 +1,475 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: database.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Database
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg, r_Database: $Id: database.cc,v 1.47 2005/09/03 20:39:35 rasdev Exp $";
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define DATABASE_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/database.hh"
+#include "rasodmg/transaction.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef DATABASE_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+#include <string.h>
+
+// At the beginning, no database is actually opened.
+r_Database* r_Database::actual_database = 0;
+
+
+r_Database::r_Database()
+ : db_status( not_open ),
+ rasmgrName(0),
+ userName(0),
+ plainPass(0),
+ communication(0)
+{
+}
+
+r_Database::r_Database( const char* name ) throw(r_Error)
+ : db_status( not_open ),
+ userName(0),
+ plainPass(0),
+ communication(0)
+{
+ if(!name)
+ {
+ RMInit::logOut << "Error: null database name." << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+ this->rasmgrName = strdup( name );
+}
+
+r_Type*
+r_Database::get_type_schema(const char* typeName, type_schema typeType) throw (r_Error)
+{
+ r_Type* retval = 0;
+
+ if ((typeName == NULL) || (strlen(typeName) == 0))
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ else if ((typeType != COLLECTION ) && (typeType != MARRAY))
+ throw r_Error(r_Error::r_Error_TypeInvalid);
+ else if (r_Database::actual_database != NULL)
+ throw r_Error(r_Error::r_Error_DatabaseClosed);
+ else if (r_Database::actual_database->get_status() != r_Database::not_open)
+ throw r_Error(r_Error::r_Error_DatabaseClosed);
+ else if (r_Transaction::actual_transaction != NULL)
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ else if (r_Transaction::actual_transaction->get_status() == r_Transaction::active)
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ else
+ {
+ ClientComm::r_Type_Type type;
+ if (typeType == COLLECTION)
+ type = ClientComm::r_SetType_Type;
+ else
+ type = ClientComm::r_MDDType_Type;
+ char* temp = r_Database::actual_database->communication->getTypeStructure( typeName, type );
+ retval = r_Type::get_any_type(temp);
+ delete [] temp;
+ temp = 0;
+ }
+ return retval;
+}
+
+r_Database::~r_Database()
+{
+ if( db_status != not_open )
+ close();
+
+ if( rasmgrName )
+ free( rasmgrName );
+ if( userName )
+ free( userName );
+ if( plainPass )
+ free( plainPass );
+}
+
+void
+r_Database::open( const char* database_name, access_status new_status )
+ throw( r_Error )
+{
+ if( db_status != not_open || actual_database )
+ {
+ r_Error err = r_Error(r_Error::r_Error_DatabaseOpen);
+ throw err;
+ }
+
+ if(!database_name)
+ {
+ RMInit::logOut << "r_Database::open(name, new_status) name is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+
+ // While instantiating the communication object, the first connection to
+ // the server is established. Any exception is given through to the caller
+ // of open(...).
+ try
+ {
+ communication = ClientComm::createObject( rasmgrName, rasmgrPort );
+ if( userName && plainPass )
+ communication->setUserIdentification( userName, plainPass );
+ }
+ catch( ... )
+ {
+ if(communication)
+ delete communication;
+ throw; // re-throw the exception (r_Error_HostInvalid, r_Error_ServerInvalid)
+ }
+
+ // open database
+ unsigned int status=0;
+ try
+ {
+ status = communication->openDB( (char*)database_name );
+ }
+ catch( ... )
+ {
+ if(communication)
+ delete communication;
+ throw;
+ }
+
+ if( status )
+ {
+ // translate error values into exceptions
+ r_Error err;
+
+ switch( status )
+ {
+ case 1:
+ err = r_Error( r_Error::r_Error_ClientUnknown );
+ break;
+
+ case 2:
+ err = r_Error( r_Error::r_Error_DatabaseUnknown );
+ break;
+
+ case 3:
+ err = r_Error( r_Error::r_Error_DatabaseOpen );
+ break;
+
+ case 4:
+ err = r_Error( r_Error::r_Error_RpcInterfaceIncompatible );
+ break;
+ case CONNECTIONCLOSED:
+ err = r_Error(CONNECTIONCLOSED);
+ break;
+ default:
+ err = r_Error( r_Error::r_Error_General );
+ }
+
+ if(communication)
+ delete communication;
+
+ throw err;
+ }
+
+ actual_database = this;
+ db_status = new_status;
+}
+
+void
+r_Database::close()
+{
+ if( db_status != not_open )
+ {
+ // if a communication object exists, close and delete it
+ if( communication )
+ {
+ // abort any open TA -- PB 2005-sep-02
+ // This is quite a hack (borrowed from fastscale.cc):
+ // Actual transaction is a pointer to this in a TA.
+ // Since the TA was allocated by the application program
+ // it should be save to use it like this.
+ if (r_Transaction::actual_transaction != 0)
+ { // make _very_ sure we have sequential evaluation -> nested ifs
+ if (r_Transaction::actual_transaction->get_status() == r_Transaction::active)
+ r_Transaction::actual_transaction->abort();
+ }
+
+ communication->closeDB();
+ delete communication;
+ communication = 0;
+ }
+
+ db_status = not_open;
+ actual_database = 0;
+ }
+}
+
+void
+r_Database::create( const char* name ) throw( r_Error )
+{
+ // this operation is not supported through this interface; use rasdl
+ throw( r_Error(803)); // Access denied, no permission
+}
+
+void
+r_Database::destroy( const char* name ) throw( r_Error )
+{
+ // this operation is not supported through this interface; use rasdl
+ throw( r_Error(803)); // Access denied, no permission
+}
+
+
+void
+r_Database::set_servername( const char* name, int port ) throw (r_Error)
+{
+ //We let the name of the function as it is, but it's about the rasmgr name
+
+ if(!name)
+ {
+ RMInit::logOut << "r_Database::set_servername(name, port) name is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+
+ if( rasmgrName)
+ free( rasmgrName );
+
+ rasmgrName = strdup( name );
+ rasmgrPort = port;
+}
+void
+r_Database::set_useridentification( const char* name, const char *plain_pass ) throw(r_Error)
+{
+ if(!name)
+ {
+ RMInit::logOut << "r_Database::set_useridentification(name, plain_pass) name is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+ if(!plain_pass)
+ {
+ RMInit::logOut << "r_Database::set_useridentification(name, plain_pass) plain_pass is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+
+ if (userName)
+ free(userName);
+ if (plainPass)
+ free(plainPass);
+ userName = strdup( name );
+ plainPass = strdup( plain_pass );
+}
+
+void
+r_Database::set_object_name( r_Object &obj, const char* name ) throw(r_Error)
+{
+ obj.set_object_name( name );
+}
+
+r_Ref_Any
+r_Database::lookup_object( const char* name ) const throw( r_Error )
+{
+ r_Ref_Any returnValue;
+
+ if( db_status == not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if(!name)
+ {
+ RMInit::logOut << "r_Database::lookup_object(name) name is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+
+ if( !r_Transaction::actual_transaction
+ || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ // get collection
+ returnValue = communication->getCollOIdsByName( name );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ return returnValue;
+}
+
+
+
+r_Ref_Any
+r_Database::lookup_object( const r_OId& oid ) const throw( r_Error )
+{
+ r_Ref_Any returnValue;
+
+ if( db_status == not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( !r_Transaction::actual_transaction
+ || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ // determine type of object and get it
+ if( communication->getObjectType( oid ) == 1 )
+ returnValue = communication->getMDDByOId( oid );
+ else
+ returnValue = communication->getCollOIdsByOId( oid );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ return returnValue;
+}
+
+
+void
+r_Database::set_transfer_format( r_Data_Format format, const char *formatParams ) throw( r_Error )
+{
+ unsigned short result;
+
+ if ( db_status == not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw (err);
+ }
+ //keeps from crashing in rpc on linux
+ if (formatParams == 0)
+ formatParams = "";
+ result = communication->setTransferFormat(format, formatParams);
+
+ switch (result)
+ {
+ case 1:
+ {
+ r_Error err = r_Error( r_Error::r_Error_ClientUnknown );
+ throw(err);
+ }
+ break;
+ case 2:
+ {
+ r_Error err = r_Error( r_Error::r_Error_FeatureNotSupported );
+ throw(err);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void
+r_Database::set_storage_format( r_Data_Format format, const char *formatParams ) throw( r_Error )
+{
+ unsigned short result;
+
+ if ( db_status == not_open )
+ {
+ r_Error err( r_Error::r_Error_DatabaseClosed );
+ throw(err);
+ }
+
+ //keeps from crashing in rpc on linux
+ if (formatParams == 0)
+ formatParams = "";
+
+ result = communication->setStorageFormat(format, formatParams);
+
+ switch (result)
+ {
+ case 1:
+ {
+ r_Error err( r_Error::r_Error_ClientUnknown );
+ throw(err);
+ }
+ break;
+ case 2:
+ {
+ r_Error err( r_Error::r_Error_FeatureNotSupported );
+ throw(err);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+const r_OId
+r_Database::get_new_oid( unsigned short objType ) const throw(r_Error)
+{
+ return communication->getNewOId( objType );
+}
+
+
+void r_Database::insertColl( const char* collName, const char* typeName, const r_OId& oid ) throw( r_Error )
+{
+ communication->insertColl(collName,typeName,oid );
+}
+
+void r_Database::removeObjFromColl( const char* name, const r_OId& oid ) throw ( r_Error )
+{
+ communication->removeObjFromColl(name,oid);
+}
+
+ClientComm* r_Database::getComm()
+{
+ return communication;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rasodmg/database.hh b/rasodmg/database.hh
new file mode 100644
index 0000000..7491eb0
--- /dev/null
+++ b/rasodmg/database.hh
@@ -0,0 +1,270 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: database.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Database
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_DATABASE_
+#define _D_DATABASE_
+
+#include "raslib/rminit.hh"
+#include "raslib/error.hh"
+#include "rasodmg/object.hh"
+#include "raslib/mddtypes.hh"
+
+// forward declarations
+class r_Object;
+class r_Transaction;
+class ClientComm;
+class r_Ref_Any;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ A database object must be instantiated and opened before
+ starting any transaction which uses the database, and closed
+ after ending these transactions.
+
+*/
+
+class r_Database
+{
+ public:
+ /// possible database states
+ enum access_status { not_open, read_write, read_only, exclusive };
+
+ /// possible types define by symbolic names
+ enum type_schema {
+ CELL = 3,
+ MARRAY = 2,
+ COLLECTION = 1
+ };
+
+ /// default constructor
+ r_Database();
+
+ /// constructor getting the rasmgr name
+ r_Database( const char* name ) throw(r_Error);
+ /**
+ One error situations can occur which raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// destructor
+ ~r_Database();
+
+ /// open a database
+ void open( const char* database_name, access_status status = read_write )
+ throw( r_Error );
+ /**
+ The method opens the database specified with {\tt database_name}. Several error
+ situations can occur which raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+
+ \begin{tabular}{lll}
+ r_Error_HostInvalid && Host can not be found.\\
+ r_Error_ServerInvalid && Server can not be found.\\
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseUnknown && Database does not exist.\\
+ r_Error_DatabaseOpen && Database is already open.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_NameInvalid && Name is NULL.\\
+ \end{tabular}
+ */
+
+ /// close a database
+ void close();
+
+ /// create a database with fixed schema RasDaSchema
+ void create( const char* name ) throw( r_Error );
+ /**
+ This method works only if a server host name has been specified with
+ {\tt set_servername()}.
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// destroy a database
+ void destroy( const char* name ) throw( r_Error );
+ /**
+ This method works only if a server host name has been specified with
+ {\tt set_servername()}.
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// set the server name
+ void set_servername( const char* name, int port = RASMGRPORT) throw(r_Error);
+ /**
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+ /// set the user name and password
+ void set_useridentification( const char* name, const char *plain_pass ) throw(r_Error);
+ /**
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// get the actual status
+ inline access_status get_status() const;
+
+ /// give a name to an object (signature is not ODMG conformant because of compiler bug)
+ void set_object_name( r_Object& obj, const char* name ) throw(r_Error);
+ /**
+ The method gives the {\tt name} to the object {\tt obj}. The name is used for
+ further retrieval of the object. Right now, names can just be given to sets
+ of type {\tt r_Set}.
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// lookup named objects in a database (must be called within open database and running transaction)
+ r_Ref_Any lookup_object( const char* name ) const
+ throw( r_Error );
+ /**
+ The method looks up an object with {\tt name}. Right now, just objects of type \Ref{r_Set} are
+ allowed. Error kinds:
+
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && Database is not open. \\
+ r_Error_TransactionNotOpen && No transaction is active. \\
+ r_Error_ObjectUnknown && The object with {\tt name} is not in the database.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_NameInvalid && Name is NULL.\\
+ \end{tabular}
+ */
+
+ /// lookup objects by oids in a database (must be called within open database and running transaction)
+ r_Ref_Any lookup_object( const r_OId& oid ) const
+ throw( r_Error );
+ /**
+ The method looks up an object with {\tt oid}. Right now, just objects of type \Ref{r_Set} and
+ \Ref{r_GMarray} are allowed.
+
+ Error kinds:
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && Database is not open. \\
+ r_Error_TransactionNotOpen && No transaction is active. \\
+ r_Error_ObjectUnknown && The object with {\tt oid} is not in the database.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ \end{tabular}
+ */
+
+ r_Type* get_type_schema(const char* typeName, type_schema typetype) throw (r_Error);
+ /**
+ The method looks up the type structure with {\tt typeName} as its name. typetype is 1 for marray and 2 for collection.
+
+ Error kinds:
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && Database is not open. \\
+ r_Error_TransactionNotOpen && No transaction is active. \\
+ r_Error_ObjectUnknown && The object with {\tt typeName} is not in the database.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_TypeInvalid && The typetype is neither 1 nor 2. \\
+ r_Error_NameInvalid && The typeName is neither NULL or is a "\0". \\
+ \end{tabular}
+ */
+
+
+ /// set the transfer compression format, both for data sent from the server
+ /// to the client and the other way around.
+ void set_transfer_format( r_Data_Format format, const char *formatParams=NULL ) throw( r_Error );
+ /**
+ The method sets the transfer compression used for the communications of
+ this client with the server.
+
+ Error kinds:
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server\\
+ r_Error_DatabaseClosed && Database is not open\\
+ r_Error_FeatureNotSupported && Unsupported transfer format\\
+ \end{tabular}
+ */
+
+ /// set the storage format for newly created MDD for this client
+ void set_storage_format( r_Data_Format format, const char *formatParams=NULL) throw( r_Error );
+ /**
+ This method sets the storage format to use for MDD created by this client
+ in the RasDaMan database. The return values are identical to set_transfer_format()
+ */
+
+ /// stores a pointer to the actually opened database
+ static r_Database* actual_database;
+
+
+ //@Man: Methods for internal use only:
+ //@{
+ ///
+ const r_OId get_new_oid( unsigned short objType ) const throw(r_Error);
+ ///
+ //@}
+
+
+ // creates an empty MDD collection on the server
+ void insertColl( const char* collName, const char* typeName, const r_OId& oid ) throw( r_Error );
+
+ /// removes an object from a collection
+ void removeObjFromColl( const char* name, const r_OId& oid ) throw ( r_Error );
+
+ ClientComm* getComm();
+ private:
+ /// stores a pointer to a communication object, which is valid while a database is opened
+ ClientComm* communication;
+
+ /// database status
+ access_status db_status;
+
+ /// stores the RasMGR name
+ char* rasmgrName;
+
+ /// stores the RasMGR port
+ int rasmgrPort;
+
+ /// stores the user name
+ char* userName;
+
+ /// stores the user password (this will change!)
+ char* plainPass;
+};
+
+#include "rasodmg/database.icc"
+#include "rasodmg/ref.hh"
+
+#endif
diff --git a/rasodmg/database.icc b/rasodmg/database.icc
new file mode 100644
index 0000000..fb75479
--- /dev/null
+++ b/rasodmg/database.icc
@@ -0,0 +1,38 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: database.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Database
+ *
+ * COMMENTS:
+ * None
+*/
+
+inline
+r_Database::access_status
+r_Database::get_status() const
+{
+ return db_status;
+}
diff --git a/rasodmg/dirdecompose.cc b/rasodmg/dirdecompose.cc
new file mode 100644
index 0000000..d00b9b4
--- /dev/null
+++ b/rasodmg/dirdecompose.cc
@@ -0,0 +1,147 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: dirdecomp.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_DirDecomp
+ *
+ * COMMENTS:
+ * None
+ *
+*/
+
+#include "rasodmg/dirdecompose.hh"
+#include <string.h>
+
+// Default size of the interval buffer for holding intervals
+const r_Dimension r_Dir_Decompose::DEFAULT_INTERVALS = 5;
+
+r_Dir_Decompose::r_Dir_Decompose()
+: num_intervals(0), current_interval(0), intervals(NULL)
+{
+ num_intervals = r_Dir_Decompose::DEFAULT_INTERVALS;
+ intervals = new r_Range[num_intervals];
+}
+
+r_Dir_Decompose::~r_Dir_Decompose()
+{
+ if ( intervals )
+ {
+ delete [] intervals;
+ intervals = NULL;
+ }
+}
+
+r_Dir_Decompose::r_Dir_Decompose(const r_Dir_Decompose& other)
+: num_intervals(0), current_interval(0), intervals(NULL)
+{
+ num_intervals = other.num_intervals;
+ current_interval = other.current_interval;
+
+ if(other.intervals)
+ {
+ intervals = new r_Range[num_intervals];
+ memcpy(intervals, other.intervals, num_intervals*sizeof(r_Range));
+ }
+}
+
+const r_Dir_Decompose& r_Dir_Decompose::operator=(const r_Dir_Decompose& other)
+{
+ if (this != &other)
+ {
+ delete [] intervals;
+
+ num_intervals = other.num_intervals;
+ current_interval = other.current_interval;
+
+ if(other.intervals)
+ {
+ intervals = new r_Range[num_intervals];
+ memcpy(intervals, other.intervals, num_intervals*sizeof(r_Range));
+ }
+ }
+
+ return *this;
+}
+
+r_Dir_Decompose& r_Dir_Decompose::operator<<(r_Range limit)
+{
+ if (current_interval == num_intervals)
+ {
+ r_Range *aux = new r_Range[num_intervals*2];
+
+ for (int i=0; i<num_intervals; i++)
+ aux[i] = intervals[i];
+
+ delete [] intervals;
+ intervals = aux;
+
+ num_intervals*= 2;
+ }
+
+ intervals[current_interval++] = limit;
+
+ return *this;
+}
+
+int r_Dir_Decompose::get_num_intervals() const
+{
+ return current_interval;
+}
+
+r_Range r_Dir_Decompose::get_partition(int number) const
+ throw (r_Eindex_violation)
+{
+ if (number >= current_interval)
+ {
+ r_Eindex_violation err(0, current_interval, number);
+ throw err;
+ }
+
+ return intervals[number];
+}
+
+void r_Dir_Decompose::print_status(std::ostream& os) const
+{
+ os << "r_Dir_Decompose[ num intervals = " << num_intervals << " current interval = " << current_interval << " intervals = {";
+
+ for (int i=0; i<current_interval; i++)
+ os << intervals[i] << " ";
+
+ os << "} ]";
+}
+
+std::ostream& operator<<(std::ostream& os, const r_Dir_Decompose& d)
+{
+ d.print_status(os);
+
+ return os;
+}
+
+r_Sinterval
+r_Dir_Decompose::get_total_interval( )
+{
+ return r_Sinterval( intervals[0], intervals[current_interval - 1]);
+}
+
diff --git a/rasodmg/dirdecompose.hh b/rasodmg/dirdecompose.hh
new file mode 100644
index 0000000..c183fd0
--- /dev/null
+++ b/rasodmg/dirdecompose.hh
@@ -0,0 +1,114 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: dirdecomp.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Dir_Decompose
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_DIRDECOMPOSE_HH_
+#define _R_DIRDECOMPOSE_HH_
+
+// Include statements
+
+#include <iostream>
+using std::cout;
+
+#include "raslib/error.hh"
+#include "raslib/sinterval.hh"
+
+//@ManMemo: Module {\bf rasodmg}
+
+/*@Doc:
+
+ The {\tt r_Dir_Decompose} class is used to specify a decomposition on
+ an n-dimensional cube (for use in {\tt r_Dir_Tiling}). For instance, to
+ specify a tiling restriction on a dimension with the form: [0, 2, 4, 5],
+ the following code would apply:
+
+ r_Dir_Decompose decomp;
+
+ decomp << 0 << 2 << 4 << 5;
+
+ Note that the first and the last elements input into the object must be
+ the origin and limit of that dimension or else a cross-section of the domain
+ will occur (as if the elements outside the specification wouldn't mind).
+
+ If one dimension is considered to be a prefered access direction, then
+ the r_Dir_Decompose should be empty, this is, no restriction should be
+ entered.
+*/
+
+class r_Dir_Decompose
+{
+ public:
+
+ r_Dir_Decompose();
+
+ virtual ~r_Dir_Decompose();
+
+ /// Copy constructor
+ r_Dir_Decompose(const r_Dir_Decompose& other);
+
+ /// Assigment operator
+ const r_Dir_Decompose& operator=(const r_Dir_Decompose& other);
+
+ /// Reads a new limit for the current dimension
+ r_Dir_Decompose& operator<<(r_Range limit);
+
+ /// Gets the number of intervals the dimension is to be split into
+ int get_num_intervals() const;
+
+ /// Gets a restriction
+ r_Range get_partition(int number) const throw (r_Eindex_violation);
+
+ /// Prints the current status of the object
+ virtual void print_status(std::ostream& os = cout ) const;
+
+protected:
+ r_Sinterval get_total_interval( );
+
+ /// Initial number of intervals of the buffer
+ const static r_Dimension DEFAULT_INTERVALS;
+
+ /// The number of intervals that this object can currently suport
+ r_Dimension num_intervals;
+
+ /// The current interval that is being used for input
+ r_Dimension current_interval;
+
+ /// The buffer that holds the information
+ r_Range* intervals;
+};
+
+//@ManMemo: Module: {\bf rasodmg}
+/**
+ Prints the status of an r_Dir_Decompose object to a stream
+*/
+extern std::ostream& operator<<(std::ostream& os, const r_Dir_Decompose& d);
+
+#endif
diff --git a/rasodmg/dirtiling.cc b/rasodmg/dirtiling.cc
new file mode 100644
index 0000000..f0bf682
--- /dev/null
+++ b/rasodmg/dirtiling.cc
@@ -0,0 +1,682 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: dirtiling.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_DirTiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifdef __VISUALC__
+// Diable warning for signed/unsigned mismatch.
+#pragma warning( disable : 4018 )
+#endif
+
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "raslib/rminit.hh"
+
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <cstdlib>
+
+#ifdef AIX
+#include <strings.h>
+#endif
+
+// Uncoment the _VISUALIZE_2D_DECOMP_ line to generate ppm files the
+// visualization of the domain decomposition done by the algoritm
+// #define _VISUALIZE_2D_DECOMP_
+
+// Uncoment the folling line for some debug printfs on this class
+// #define _DEBUG_DIRTILING_
+
+#ifdef _DEBUG_DIRTILING_
+#define DEBUG_DIR(msg) cout << "[" << __LINE__ << "] " << msg;
+#else
+#define DEBUG_DIR(msg)
+#endif
+
+
+#ifdef _VISUALIZE_2D_DECOMP_
+#include "tools/visualtiling2d.hh"
+#endif
+
+const char*
+r_Dir_Tiling::description = "dimensions, decomposision patterns, tile size(in bytes) and subtiling [SUBTILING|NOSUBTILING] (ex: \"3;[0,2,4,5],[*],[0,10,15];100;NOSUBTILING\")";
+
+const char* r_Dir_Tiling::subtiling_name_withoutsubtiling = "NOSUBTILING";
+const char* r_Dir_Tiling::subtiling_name_withsubtiling = "SUBTILING";
+const char* r_Dir_Tiling::all_subtiling_names[r_Dir_Tiling::NUMBER]={
+ subtiling_name_withoutsubtiling,
+ subtiling_name_withsubtiling
+ };
+
+r_Dir_Tiling::SubTiling
+r_Dir_Tiling::get_subtiling_from_name(const char* name)
+{
+ if(!name) {
+ RMInit::logOut << "r_Dir_Tiling::get_subtiling_from_name(" << (name?name:"NULL") << ")." << endl;
+ return r_Dir_Tiling::NUMBER;
+ }
+
+ unsigned int i=r_Dir_Tiling::NUMBER;
+
+ for (i=0; i<(unsigned int)r_Dir_Tiling::NUMBER; i++)
+ {
+ if (strcasecmp(name, all_subtiling_names[i]) == 0)
+ break;
+ }
+
+ return (r_Dir_Tiling::SubTiling)i;
+}
+
+const char*
+r_Dir_Tiling::get_name_from_subtiling(SubTiling tsl)
+{
+ static const char* unknown="UNKNOWN";
+ unsigned int idx = (unsigned int)tsl;
+
+ if (idx >= (unsigned int)r_Dir_Tiling::NUMBER)
+ return unknown;
+
+ return all_subtiling_names[idx];
+}
+
+r_Dir_Tiling::r_Dir_Tiling(const char* encoded) throw (r_Error)
+ : r_Dimension_Tiling(0, 0)
+{
+ if(!encoded)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << (encoded?encoded: "NULL") << ")." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ r_Dimension tileD=0, dirIndex=0;
+ r_Range decomp=0;
+ std::vector<r_Dir_Decompose> vectDirDecomp;
+ r_Bytes tileS=0, lenToConvert=0, lenDirToConvert=0, lenDecomp=0;
+ r_Dir_Tiling::SubTiling subTiling;
+ const char *pStart=NULL, *pEnd=NULL, *pRes=NULL, *pTemp=NULL, *pToConvertEnd=NULL;
+ char* pToConvert=NULL;
+ const char *pDirRes=NULL, *pDirEnd=NULL, *pDirTemp=NULL, *pDirStart=NULL;
+ char* pDirToConvert=NULL;
+ char* pDecomp=NULL;
+
+ //initialisation
+ pStart=encoded;
+ pTemp=pStart;
+ pEnd=pTemp+strlen(pStart);
+
+ //deal with dimension
+ pRes=strstr(pTemp, COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile dimension." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ tileD=strtol(pToConvert, (char**)NULL, DefaultBase);
+ if(!tileD)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile dimension \"" << pToConvert << "\" is not a number." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if(tileD<0)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile dimension \"" << pToConvert << "\" is negative." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ vectDirDecomp=std::vector<r_Dir_Decompose>(tileD);
+
+ delete[] pToConvert;
+ if(pRes==(pEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pRes++;
+ pTemp=pRes;
+
+ //deal with directional decompose
+ pRes=strstr(pTemp, COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+ pToConvertEnd=pToConvert+strlen(pToConvert);
+ pDirTemp=pToConvert;
+
+ while(dirIndex < tileD)
+ {
+ pDirRes=strstr(pDirTemp, LSQRBRA);
+ if(!pDirRes)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ pDirStart=pDirRes;
+ pDirRes=strstr(pDirTemp, RSQRBRA);
+ if(!pDirRes)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ pDirEnd=pDirRes;
+
+ lenDirToConvert=pDirEnd-pDirStart;
+ if(lenDirToConvert == 1)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ pDirToConvert=new char[lenDirToConvert];
+ memcpy(pDirToConvert, pDirStart+1, lenDirToConvert-1);
+ pDirToConvert[lenDirToConvert-1]='\0';
+ pDirTemp=pDirToConvert;
+ pDirStart=pDirEnd;
+ pDirEnd=pDirToConvert+strlen(pDirToConvert);
+
+ if(*pDirToConvert != *ASTERIX)
+ {
+ pDirRes=strstr(pDirToConvert, COMMA);
+ if(!pDirRes)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\"." << endl;
+ delete[] pDirToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ while(pDirRes)
+ {
+ lenDecomp=pDirRes-pDirTemp;
+ pDecomp=new char[lenDecomp+1];
+ memcpy(pDecomp, pDirTemp, lenDecomp);
+ pDecomp[lenDecomp]='\0';
+
+ decomp=strtoul(pDecomp, (char**)&pDirTemp, DefaultBase);
+
+ if(*pDirTemp !='\0')
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding decompose \"" << pDecomp << "\" from directional decompose \"" << pDirToConvert << "\", is not a number." << endl;
+ delete[] pDecomp;
+ delete[] pDirToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ vectDirDecomp[dirIndex] << decomp;
+
+ //skip COMMA & free buffer
+ delete[] pDecomp;
+ if(pDirRes==(pDirEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose \"" << pDirToConvert << "\", end of stream." << endl;
+ delete[] pDirToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pDirRes++;
+ pDirTemp=pDirRes;
+
+ //next decomp
+ pDirRes=strstr(pDirTemp, COMMA);
+ if(!pDirRes)
+ {
+ decomp=strtoul(pDirTemp, (char**)&pDirRes, DefaultBase);
+ if(*pDirRes !='\0')
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding decompose \"" << pDirTemp << "\" from directional decompose \"" << pDirToConvert << "\", is not a number." << endl;
+ delete[] pDirToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ vectDirDecomp[dirIndex]<<decomp;
+ break;
+ }//end if
+ }//end while
+ } //end if
+
+ delete[] pDirToConvert;
+ dirIndex++;
+ if(dirIndex < tileD)
+ {
+ if(pDirStart == (pToConvertEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex << " from \"" << pToConvert << "\", end of stream." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pDirStart++;
+
+ pDirRes=strstr(pDirStart, COMMA);
+ if(!pDirRes)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\", end of stream." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ if(pDirRes == (pToConvertEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex << " from \"" << pToConvert << "\", end of stream." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pDirRes++;
+
+ pDirTemp=pDirRes;
+ }//end if(dirIndex<tileD)
+ }//end while
+
+ //skip COLON & free buffer
+ delete[] pToConvert;
+ if(pRes==(pEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile size from \"" << pStart << "\", end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pRes++;
+ pTemp=pRes;
+
+ //deal with tilesize
+ pRes=strstr(pTemp, COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile size from \"" << pTemp << "\", end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ tileS=strtol(pToConvert, (char**)NULL, DefaultBase);
+
+ if(!tileS)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile size from \"" << pToConvert << "\", is not a number." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if(tileS<0)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile size from \"" << pToConvert << "\", is negative." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON & free buffer
+ delete[] pToConvert;
+ if(pRes==(pEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding subtiling from \"" << pStart << "\", end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pRes++;
+ pTemp=pRes;
+ //deal with subtilig
+ subTiling=r_Dir_Tiling::get_subtiling_from_name(pTemp);
+ if(subTiling==r_Dir_Tiling::NUMBER)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding subtiling from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ dimension = tileD;
+ dim_decomp = vectDirDecomp;
+ sub_tile = subTiling;
+ tile_size = tileS;
+}
+
+r_Dir_Tiling::r_Dir_Tiling(r_Dimension dims, const std::vector<r_Dir_Decompose>& decomp, r_Bytes ts, SubTiling sub) throw (r_Error)
+ : r_Dimension_Tiling(dims, ts),
+ dim_decomp(decomp),
+ sub_tile(sub)
+{
+ if (dim_decomp.size() != dimension)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << dims << ", " << decomp << ", " << ts << ", " << sub << ") number of dimensions (" << dimension << ") does not match number of decomposition entries (" << decomp.size() << ")" << endl;
+ throw r_Edim_mismatch(dimension, dim_decomp.size());
+ }
+}
+
+r_Dir_Tiling::~r_Dir_Tiling()
+{
+}
+
+r_Tiling_Scheme
+r_Dir_Tiling::get_tiling_scheme() const
+{
+ return r_DirectionalTiling;
+}
+
+r_Tiling* r_Dir_Tiling::clone() const
+{
+ r_Tiling* copy = new r_Dir_Tiling(dimension, dim_decomp, tile_size, sub_tile);
+ return copy;
+}
+
+void r_Dir_Tiling::print_status(std::ostream& os) const
+{
+ os << "r_Dir_Tiling[ ";
+ r_Dimension_Tiling::print_status(os);
+ os << " sub tiling = " << sub_tile << " decompose = { ";
+
+ for (r_Dimension i = 0; i < dim_decomp.size(); i++)
+ os << "dim #" << i << " : " << dim_decomp[i] << " ";
+ os << "} ";
+
+}
+
+std::vector<r_Minterval>*
+r_Dir_Tiling::compute_tiles(const r_Minterval& domain, r_Bytes typelen) const throw (r_Error)
+{
+ // Aux variable
+ r_Dimension i = 0;
+ // The result
+ std::vector<r_Minterval>* decomp_result = new std::vector<r_Minterval>();
+ // An alias to result
+ std::vector<r_Minterval>& result = *decomp_result;
+ std::vector<r_Dir_Decompose> temp_dim_decomp = dim_decomp;
+
+
+ // Check dims
+ if (dimension != domain.dimension())
+ {
+
+ delete decomp_result;
+
+ RMInit::logOut << "r_Dir_Tiling::compute_tiles(" << domain << ", " << typelen << ") dimensions of domain (" << domain.dimension() << ") do not match dimensions of tiling strategy (" << dimension << ")" << endl;
+ throw r_Edim_mismatch(dimension, domain.dimension());
+ }
+
+ // Undefined dims
+ bool* undef_dim = new bool[dimension];
+ // Count of undef dims
+ r_Dimension total_undef = 0;
+
+ // Check if limits ok
+ for (i = 0; i < dimension; i++)
+ {
+ // Restric defined
+ if (temp_dim_decomp[i].get_num_intervals() > 0)
+ {
+ undef_dim[i] = false;
+ r_Range lim1 = 0;
+ r_Range lim2 = 0;
+
+ lim1 = domain[i].high();
+ lim2 = temp_dim_decomp[i].get_partition(temp_dim_decomp[i].get_num_intervals() - 1);
+ if (lim1 != lim2)
+ {
+ delete[] undef_dim;
+ delete decomp_result;
+
+ RMInit::logOut << "r_Dir_Tiling::compute_tiles(" << domain << ", " << typelen << ") upper limit of domain (" << domain.dimension() << ") at dimension " << i << " (" << domain[i] << ") does not partition " << temp_dim_decomp[i].get_partition(temp_dim_decomp[i].get_num_intervals() - 1) << endl;
+ throw r_Elimits_mismatch(lim1, lim2);
+ }
+
+ lim1 = domain[i].low();
+ lim2 = temp_dim_decomp[i].get_partition(0);
+ if (lim1 != lim2)
+ {
+ delete[] undef_dim;
+ delete decomp_result;
+
+ RMInit::logOut << "r_Dir_Tiling::compute_tiles(" << domain << ", " << typelen << ") lower limit of domain (" << domain.dimension() << ") at dimension " << i << " (" << domain[i] << ") does not partition " << temp_dim_decomp[i].get_partition(0) << endl;
+ throw r_Elimits_mismatch(lim1, lim2);
+ }
+ }
+ else // Restric not defined
+ {
+ // Dim unspecified
+ undef_dim[i] = true;
+ total_undef++;
+ temp_dim_decomp[i] << domain[i].low() << domain[i].high();
+ }
+ }
+
+ // Create a counter for each dimension
+ r_Dimension* dim_counter = new r_Dimension[dimension];
+ memset(dim_counter, 0, sizeof(r_Dimension) * dimension);
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ // User wants a visual of the 2D decomp.
+ // Number of times a decomp has been made
+ static int count;
+ ++count; // Update decomp count
+
+ Visual_Tiling_2D* vis;
+ if (dimension == 2)
+ {
+ // Create an object for visualization
+ char fname[80];
+ sprintf(fname, "2D_decomp_dir_%d.ppm", count);
+ vis = new Visual_Tiling_2D(domain, fname);
+ }
+#endif
+
+ // Iterate over the all space
+
+ bool done = false;
+ while (!done)
+ {
+ // Determine tile coordinates
+
+ r_Minterval tile(dimension);
+
+ for (i = 0; i < dimension; i++)
+ {
+ r_Range origin = temp_dim_decomp[i].get_partition(dim_counter[i]);
+ if (dim_counter[i] != 0)
+ origin++;
+
+ r_Range limit = temp_dim_decomp[i].get_partition(dim_counter[i]+1);
+
+ tile << r_Sinterval(origin, limit);
+ }
+
+ // Do something with tile coordinates (decompose big object)
+
+#ifdef _DEBUG_DIRTILING_
+ cout << "(DirTiling::compute_tiles(): Tile: " << tile << endl;
+#endif
+
+ // Check if sub-tiling should be done and calculate edgesize
+
+ if ((tile.cell_count() * typelen > tile_size) && (sub_tile == WITH_SUBTILING))
+ {
+ // Create a specification for the partition
+
+ r_Minterval partition(dimension);
+
+ if (total_undef == 0)
+ {
+ // No unspecified dimensions --- create block cross sections
+
+ for (i=0; i<dimension; i++)
+ partition << r_Sinterval((r_Range) 0, tile[i].high()-tile[i].low());
+ }
+ else
+ {
+ // Some unspecified dimensions
+
+ // Compute edgesize
+ r_Range edgesize = tile_size;
+
+ for (i = 0; i < dimension; i++)
+ {
+ if (!undef_dim[i])
+ edgesize/= (tile[i].high()-tile[i].low()+1) * typelen;
+ }
+
+ edgesize = floor(pow(((double)edgesize)/((double)typelen), (1.0/((double)total_undef))));
+
+ // Create specification
+
+ for (i = 0; i < dimension; i++)
+ {
+ if (undef_dim[i])
+ partition << r_Sinterval((r_Range) 0, (edgesize-1));
+ else
+ partition << r_Sinterval((r_Range) 0, tile[i].high()-tile[i].low());
+ }
+ }
+
+#ifdef _DEBUG_DIRTILING_
+ cout << "(DirTiling::compute_tiles(): Tile size = " << get_tile_size()
+ << " Specs = " << partition << endl;
+#endif
+
+ // Create subtiles and insert them in the result
+
+ r_Aligned_Tiling subtiling(partition, get_tile_size());
+ std::vector<r_Minterval>* subtiles = subtiling.compute_tiles(tile, typelen);
+ std::vector<r_Minterval>::iterator it = subtiles->begin();
+ for (; it != subtiles->end(); it++)
+ {
+ result.push_back(*it);
+
+#ifdef _VISUALIZE_2D_DECOMP_ // If we are visualizing
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(0, 255, 0);
+ if (dimension == 2)
+ (*vis) << (*it);
+ }
+#endif
+ }
+ delete subtiles;
+ }
+ else
+ result.push_back(tile);
+
+#ifdef _VISUALIZE_2D_DECOMP_ // If we are visualizing
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(255, 255, 0);
+ if (dimension == 2)
+ (*vis) << tile;
+ }
+#endif
+
+ // Update dimension counters
+
+ for (i=0; i < dimension; i++)
+ {
+ dim_counter[i]++;
+ if (dim_counter[i] == (temp_dim_decomp[i].get_num_intervals()-1))
+ dim_counter[i] = 0;
+ else
+ break;
+ }
+
+ // See if we are done
+ done = 1;
+ for (i=0; i<dimension; i++)
+ if (dim_counter[i] != 0)
+ {
+ done = 0;
+ break;
+ }
+ }
+
+ delete [] dim_counter;
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (dimension == 2)
+ delete vis;
+#endif
+
+ delete [] undef_dim;
+ return &result;
+}
+
+bool
+r_Dir_Tiling::is_compatible(const r_Minterval& domain, r_Bytes type_len) const
+{
+ bool retval = true;
+ if (!r_Dimension_Tiling::is_compatible(domain, type_len))
+ retval = false;
+ else {
+
+ // Aux variable
+ r_Dimension i = 0;
+
+ for (i = 0; i < dimension; i++) // Check if limits ok
+ {
+ if (dim_decomp[i].get_num_intervals() > 0) // Restric defined
+ {
+ r_Range lim1, lim2;
+
+ lim1 = domain[i].high();
+ lim2 = dim_decomp[i].get_partition(dim_decomp[i].get_num_intervals()-1);
+ if (lim1 != lim2)
+ {
+ retval = false;
+ break;
+ }
+
+ lim1 = domain[i].low();
+ lim2 = dim_decomp[i].get_partition(0);
+ if (lim1 != lim2)
+ {
+ retval = false;
+ break;
+ }
+ }
+ }
+ }
+ return retval;
+}
+
diff --git a/rasodmg/dirtiling.hh b/rasodmg/dirtiling.hh
new file mode 100644
index 0000000..9495571
--- /dev/null
+++ b/rasodmg/dirtiling.hh
@@ -0,0 +1,133 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: dirtiling.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Dir_Tiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_DIRTILING_HH_
+#define _R_DIRTILING_HH_
+
+// Include statements
+class r_Dir_Decompose;
+class r_Dir_Tiling;
+
+#include "rasodmg/tiling.hh"
+
+// Class definition
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ This class implements the "Directional Tiling" tiling method. In this
+ method the decomposition is done along certain directions of the
+ multi-dimensional cube. The user uses {\tt r_Dir_Decompose} to inform
+ the system on how the decomposition is done in each dimension.
+*/
+
+class r_Dir_Tiling : public r_Dimension_Tiling
+{
+ // ******************* PUBLIC SECTION *******************
+
+ public:
+
+ /// Constants that specify if subtiling will occur inside the blocks
+ enum SubTiling {
+ WITHOUT_SUBTILING = 0,
+ WITH_SUBTILING = 1,
+ NUMBER = 2
+ };
+ /// read everything from encoded string
+ /// e.g. "3;[0,2,4,5],[*],[0,10,15];100;NOSUBTILING"
+ r_Dir_Tiling(const char* encoded) throw (r_Error);
+
+ /// Class constructor
+ r_Dir_Tiling(r_Dimension dims,
+ const std::vector<r_Dir_Decompose>& decomp,
+ r_Bytes ts = RMInit::clientTileSize,
+ SubTiling sub = WITH_SUBTILING) throw (r_Error);
+ /**
+ The user has to give the number of dimensions of the space and the
+ decomposition wanted for that space. Note that the number of elements of
+ decomp must be the same as the number of dimensions of the space.
+ See {\tt r_Dir_Decompose} for details on how to indicate a decomposition.
+ SubTiling indicates if subtiling should occur inside the blocks specified
+ by the user.
+ Throws an exception when the decomp.size is not equal to the specified
+ dimension.
+ */
+
+ virtual ~r_Dir_Tiling();
+
+ virtual std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error);
+
+ virtual bool is_compatible(const r_Minterval& obj_domain, r_Bytes type_len) const;
+
+ virtual void print_status(std::ostream& os) const;
+
+ virtual r_Tiling* clone() const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ Get a tilesize limit for a tilisize limit name
+ */
+ static r_Dir_Tiling::SubTiling get_subtiling_from_name(const char* name);
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ Get a tilisize limit name for a tilesize limit
+ */
+ static const char* get_name_from_subtiling(SubTiling st);
+
+ static const char* description;
+
+ protected: // data
+
+ /// The decomposition to be used
+ std::vector<r_Dir_Decompose> dim_decomp;
+
+ /// If sub-tiling should occour
+ SubTiling sub_tile;
+
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ The names of all subtiling types, to avoid redundant storage and inconsistencies.
+ The variable name convention is the prefix subtiling_name_ followed by the name
+ of the data format in lower case, i.e. for WITH_SUBTILING subtiling_name_withsubtiling.
+ In addition there's an array of names all_subtiling_names where the subtiling
+ can be used as index to get the name.
+ */
+ static const char* subtiling_name_withoutsubtiling;
+ static const char* subtiling_name_withsubtiling;
+
+ static const char* all_subtiling_names[r_Dir_Tiling::NUMBER];
+};
+
+#endif
+
diff --git a/rasodmg/gmarray.cc b/rasodmg/gmarray.cc
new file mode 100644
index 0000000..89fa919
--- /dev/null
+++ b/rasodmg/gmarray.cc
@@ -0,0 +1,484 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: gmarray.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_GMarray
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsidgarray[] = "@(#)rasodmg, r_GMarray: $Id: gmarray.cc,v 1.45 2003/12/27 23:02:56 rasdev Exp $";
+
+#include <vector>
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define GMARRAY_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/marray.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef GMARRAY_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+#include "raslib/rmdebug.hh"
+#include "raslib/type.hh"
+#include "raslib/marraytype.hh"
+#include "raslib/structuretype.hh"
+
+#include <string.h> // for memcpy()
+#include <iostream>
+#include <iomanip>
+
+
+
+r_GMarray::r_GMarray() throw(r_Error)
+ : r_Object(1),
+ data(0),
+ data_size(0),
+ type_length(0),
+ current_format(r_Array),
+ storage_layout(0)
+{
+ storage_layout = new r_Storage_Layout();
+}
+
+
+
+r_GMarray::r_GMarray(const r_Minterval& initDomain, r_Bytes initLength, r_Storage_Layout* stl) throw (r_Error)
+ : r_Object(1),
+ data(0),
+ data_size(0),
+ domain(initDomain),
+ type_length(initLength),
+ current_format(r_Array),
+ storage_layout(stl)
+{
+ int error = 0;
+ if (domain.dimension() == 0)
+ {
+ error = 1;
+ }
+ else {
+ if (storage_layout == NULL)
+ {
+ storage_layout = new r_Storage_Layout(new r_Aligned_Tiling(initDomain.dimension()));
+ }
+ if (!storage_layout->is_compatible(initDomain, initLength))
+ {
+ error = 2;
+ }
+ }
+ if (error != 0)
+ {
+ RMInit::logOut << "r_GMarray::r_GMarray(" << initDomain << ", " << initLength << ", ";
+ if (storage_layout == NULL)
+ RMInit::logOut << "no storage layout";
+ else
+ RMInit::logOut << *storage_layout;
+ RMInit::logOut << ") ";
+ if (error == 1)
+ {
+ RMInit::logOut << "domain is not initialised";
+ throw r_Error(DOMAINUNINITIALISED);
+ }
+ else {
+ RMInit::logOut << "storage layout is not compatible";
+ throw r_Error(STORAGERLAYOUTINCOMPATIBLEWITHGMARRAY);
+ }
+ }
+ data_size = domain.cell_count() * initLength;
+ data = new char[ data_size ];
+ memset(data, 0, data_size);
+}
+
+
+
+r_GMarray::r_GMarray(const r_GMarray &obj) throw(r_Error)
+ : r_Object(obj, 1),
+ data(0),
+ data_size(0),
+ domain(obj.spatial_domain()),
+ type_length(obj.type_length),
+ current_format(obj.current_format),
+ storage_layout(0)
+{
+ RMDBCLASS("r_GMarray", "r_GMarray(const r_GMarray)", "rasodmg", __FILE__, __LINE__)
+
+ if (obj.data)
+ {
+ data_size = obj.data_size;
+ data = new char[ data_size ];
+
+ memcpy(data, obj.data, (unsigned int)data_size);
+ }
+
+ // clone the storage layout object
+ if (obj.storage_layout)
+ storage_layout = obj.storage_layout->clone();
+ else
+ RMInit::logOut << "copy constructor no storage layout" << endl;
+}
+
+
+
+r_GMarray::r_GMarray(r_GMarray &obj) throw(r_Error)
+ : r_Object(obj, 1),
+ data(obj.data),
+ data_size(obj.data_size),
+ domain(obj.spatial_domain()),
+ type_length(obj.type_length),
+ current_format(obj.current_format),
+ storage_layout(0)
+{
+ RMDBCLASS("r_GMarray", "r_GMarray(r_GMarray)", "rasodmg", __FILE__, __LINE__)
+
+ obj.data_size = 0;
+ obj.data = 0;
+ obj.domain = r_Minterval();
+ obj.type_length = 0;
+
+ // clone the storage layout object
+ if (obj.storage_layout)
+ storage_layout = obj.storage_layout->clone();
+ else
+ RMInit::logOut << "copy constructor (no data) no storage layout" << endl;
+}
+
+
+
+r_GMarray::~r_GMarray()
+{
+ r_deactivate();
+}
+
+
+
+void
+r_GMarray::r_deactivate()
+{
+ RMDBGENTER(2, RMDebug::module_rasodmg, "r_GMarray", "r_deactivate()");
+
+ if (data)
+ {
+ delete[] data;
+ data = 0;
+ }
+
+ // invoke deactivate of members with dynamic memory
+ domain.r_deactivate();
+
+ // delete dynamic members
+ if (storage_layout)
+ {
+ delete storage_layout;
+ storage_layout = 0;
+ }
+
+ RMDBGEXIT(2, RMDebug::module_rasodmg, "r_GMarray", "r_deactivate()");
+}
+
+
+
+const char*
+r_GMarray::operator[] (const r_Point& point) const
+ throw(r_Edim_mismatch, r_Eindex_violation)
+{
+ return &(data[ domain.cell_offset(point)*type_length ]);
+}
+
+
+
+const r_Storage_Layout*
+r_GMarray::get_storage_layout() const
+{
+ return storage_layout;
+}
+
+
+void
+r_GMarray::set_storage_layout(r_Storage_Layout *stl) throw(r_Error)
+{
+ if (!stl->is_compatible(domain, type_length))
+ {
+ RMInit::logOut << "r_GMarray::set_storage_layout(" << *stl << ") gmarray is not compatible with tiling" << endl;
+ RMInit::logOut << "\tgmarray domain : " << spatial_domain() << endl;
+ RMInit::logOut << "\tgmarray type size: " << get_type_length() << endl;
+ throw r_Error(STORAGERLAYOUTINCOMPATIBLEWITHGMARRAY);
+ }
+
+ if (storage_layout != NULL)
+ delete storage_layout;
+
+ storage_layout = stl;
+}
+
+
+
+const r_GMarray&
+r_GMarray::operator=(const r_GMarray& marray)
+{
+ if (this != &marray)
+ {
+ if (data)
+ {
+ delete[] data;
+ data = 0;
+ }
+
+ if (marray.data)
+ {
+ data_size = marray.data_size;
+ data = new char[ data_size ];
+
+ memcpy(data, marray.data, (unsigned int)data_size);
+ }
+
+ if (storage_layout)
+ {
+ delete storage_layout;
+ storage_layout = 0;
+ }
+
+ // this has to be changed to a clone() function in future
+ if (marray.storage_layout)
+ // storage_layout = new r_Storage_Layout(*marray.storage_layout);
+ storage_layout = marray.storage_layout->clone();
+
+ domain = marray.domain;
+ type_length = marray.type_length;
+ current_format = marray.current_format;
+ }
+
+ return *this;
+}
+
+
+
+void
+r_GMarray::insert_obj_into_db()
+{
+ // Nothing is done in that case. r_Marray objects can just be inserted as elements
+ // of a collection which invokes r_GMarray::insert_obj_into_db(const char* collName)
+ // of the r_Marray objects.
+
+ // r_Database::actual_database->communication->insertSingleMDDObj(this);
+ RMInit::logOut << " do nothing " << std::flush;
+}
+
+
+
+void
+r_GMarray::insert_obj_into_db(const char* collName)
+{
+ // Insert myself in database only if I have a type name, otherwise
+ // an exception is thrown.
+ if (!type_name)
+ {
+ r_Error err = r_Error(r_Error::r_Error_DatabaseClassUndefined);
+ throw err;
+ }
+
+ r_Database::actual_database->getComm()->insertMDD(collName, this);
+}
+
+
+
+
+void
+r_GMarray::print_status(std::ostream& s) const
+{
+ const r_Type* typeSchema = (r_Base_Type*)((r_GMarray*)this)->get_type_schema();
+ const r_Base_Type* baseTypeSchema = (r_Base_Type*)((r_GMarray*)this)->get_base_type_schema();
+
+ s << "GMarray" << endl;
+ s << " Oid...................: " << get_oid() << endl;
+ s << " Type Structure........: " << (get_type_structure() ? get_type_structure() : "<nn>") << endl;
+ s << " Type Schema...........: " << std::flush;
+ if (typeSchema)
+ typeSchema->print_status(s);
+ else
+ s << "<nn>" << std::flush;
+ s << endl;
+ s << " Domain................: " << domain << endl;
+ s << " Base Type Schema......: " << std::flush;
+ if (baseTypeSchema)
+ baseTypeSchema->print_status(s);
+ else
+ s << "<nn>" << std::flush;
+ s << endl;
+ s << " Base Type Length......: " << type_length << endl;
+ s << " Data format.......... : " << current_format << endl;
+ s << " Data size (bytes).... : " << data_size << endl;
+}
+
+
+
+void
+r_GMarray::print_status(std::ostream& s, int hexoutput) const
+{
+ print_status(s);
+
+ const r_Type* typeSchema = (r_Base_Type*)((r_GMarray*)this)->get_type_schema();
+ const r_Base_Type* baseTypeSchema = (r_Base_Type*)((r_GMarray*)this)->get_base_type_schema();
+
+ if (domain.dimension())
+ {
+ r_Point p(domain.dimension());
+ bool done = false;
+ r_Dimension i = 0;
+
+ // initialize point
+ for (i = 0; i < domain.dimension(); i++)
+ p << domain[i].low();
+
+ // iterate over all cells
+ while(!done)
+ {
+ //
+ // print cell
+ //
+
+ // get cell address
+ char* cell = data + domain.cell_offset(p) * type_length;
+
+ if (hexoutput)
+ {
+ for (r_Bytes j = 0; j < type_length; j++)
+ s << std::hex << (unsigned int)(unsigned char)(cell[j]);
+ }
+ else {
+ if(baseTypeSchema) baseTypeSchema->print_value(cell, s );
+ else s << "<nn>" << std::flush;
+ }
+
+ s << " ";
+
+ // increment coordinate
+ i = 0;
+ while(++p[i] > domain[i].high())
+ {
+ s << endl;
+ p[i] = domain[i].low();
+ i++;
+ if (i >= domain.dimension())
+ {
+ done = true;
+ break;
+ }
+ }
+ if (i > 1) s << endl;
+ }
+ }
+ else
+ {
+ s << "Cell value " << std::flush;
+
+ // print cell
+ if ((hexoutput) || (!baseTypeSchema))
+ {
+ for (unsigned int j=0; j<type_length; j++)
+ s << std::hex << (unsigned int)(unsigned char)(data[j]);
+ }
+ else {
+ if(baseTypeSchema) baseTypeSchema->print_value(data, s );
+ else s << "<nn>" << std::flush;
+ }
+ s << endl;
+ }
+
+ // turn off hex mode again
+ s << std::dec << std::flush;
+}
+
+
+
+
+r_GMarray* r_GMarray::intersect(r_Minterval where) const
+{
+ r_GMarray* tile = new r_GMarray();
+
+ r_Minterval obj_domain = spatial_domain();
+ r_Dimension num_dims = obj_domain.dimension();
+ r_Bytes tlength = get_type_length();
+
+ char* obj_data = new char[where.cell_count() * tlength];
+ tile->set_spatial_domain(where);
+ tile->set_type_length(tlength);
+ tile->set_array(obj_data);
+ tile->set_array_size(where.cell_count() * tlength);
+
+ r_Bytes block_length = where[num_dims-1].high() - where[num_dims-1].low() + 1;
+ r_Bytes total = where.cell_count()/block_length;
+
+ for (r_Area cell = 0; cell < total; cell++)
+ {
+ r_Point p = where.cell_point(cell*block_length);
+
+ char* dest_off = obj_data;
+ const char* source_off = get_array();
+
+ memcpy((void*) (dest_off + where.cell_offset(p)*tlength),
+ (void*) (source_off + obj_domain.cell_offset(p)*tlength),
+ (size_t) (block_length * tlength));
+ }
+
+ return tile;
+}
+
+
+
+const r_Base_Type*
+r_GMarray::get_base_type_schema()
+{
+ const r_Type* typePtr = r_Object::get_type_schema();
+ const r_Base_Type* baseTypePtr = 0;
+
+ if (typePtr)
+ {
+ if (typePtr->type_id() == r_Type::MARRAYTYPE)
+ {
+ const r_Marray_Type* marrayTypePtr = (const r_Marray_Type*)typePtr;
+ baseTypePtr = &(marrayTypePtr->base_type());
+ }
+ else
+ {
+ //whenever this module is done correctly, it should be checked first, what kind of type we are dealing with. therefore i do not declare a throw clause.
+ RMInit::logOut << "r_GMarray::get_base_type_schema() the type retrieved (" << typePtr->name() << ") was not a marray type" << endl;
+ throw r_Error(NOTANMARRAYTYPE);
+ }
+ }
+
+ return baseTypePtr;
+}
+
diff --git a/rasodmg/gmarray.hh b/rasodmg/gmarray.hh
new file mode 100644
index 0000000..2274e74
--- /dev/null
+++ b/rasodmg/gmarray.hh
@@ -0,0 +1,185 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: gmarray.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_GMarray
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_GMARRAY_
+#define _D_GMARRAY_
+
+#include "rasodmg/object.hh"
+
+#include "raslib/error.hh"
+#include "raslib/minterval.hh"
+#include "raslib/point.hh"
+#include "raslib/type.hh"
+#include "raslib/mddtypes.hh"
+
+#include <iostream>
+
+// forward declarations
+class r_Storage_Layout;
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The class represents a generic MDD in the sense that it
+ is independent of the cell base type. The only information
+ available is the length in bytes of the base type.
+ More specific MDDs including base type information for more
+ type safety are represented by the template subclass \Ref{r_Marray}.
+ Class \Ref{r_Marray} provides a constructor to convert to the base
+ type specific class.
+*/
+
+class r_GMarray : public r_Object
+{
+ public:
+ /// default constructor (no memory is allocated!)
+ r_GMarray() throw(r_Error);
+
+ /// constructor for uninitialized MDD objects
+ r_GMarray(const r_Minterval& init_domain, r_Bytes type_length, r_Storage_Layout* stl = 0) throw (r_Error);
+ /**
+ If a storage layout pointer is provided, the object refered to is
+ taken and memory control moves to the \Ref{r_GMarray} class.
+ The user has to take care, that each creation of \Ref{r_GMarray}
+ objects get a new storage layout object.
+ r_Error is throw if the storage layout does not fit the type length or the dimension of the init domain and when the dimension of the domain is 0 (uninitialised).
+ */
+
+ /// copy constructor
+ r_GMarray(const r_GMarray&) throw(r_Error);
+
+ /// constructor which doesn't copy the data
+ r_GMarray(r_GMarray&) throw(r_Error);
+
+ /// destructor
+ virtual ~r_GMarray();
+
+ /// it is called when an object leaves transient memory (internal use only)
+ virtual void r_deactivate();
+
+ /// assignment: cleanup + copy
+ const r_GMarray& operator= (const r_GMarray&);
+
+ /// subscript operator for read access of a cell
+ const char* operator[](const r_Point&) const
+ throw(r_Edim_mismatch, r_Eindex_violation);
+
+ /// Returns a r_GMarray that is the intersection of the current domain with the specified interval
+ r_GMarray* intersect(r_Minterval where) const;
+
+ //@Man: Read methods
+ //@{
+ ///
+
+ /// gets a pointer to the storage layout object
+ const r_Storage_Layout* get_storage_layout() const;
+ /// getting the spatial domain
+ inline const r_Minterval& spatial_domain() const;
+ /// get the internal representation of the array
+ inline char* get_array();
+ /// get the internal representation of the array for reading
+ inline const char* get_array() const;
+ /// get size of internal array representation in byets
+ inline r_Bytes get_array_size() const;
+ /// get length of cell type in bytes
+ inline r_Bytes get_type_length() const;
+ /// get current data format
+ inline r_Data_Format get_current_format() const;
+
+ /// get base type schema
+ const r_Base_Type* get_base_type_schema();
+
+ ///
+ //@}
+
+ //@Man: Write methods
+ //@{
+ ///
+ /// sets the storage layout object and checks compatibility with the domain
+ void set_storage_layout(r_Storage_Layout *) throw (r_Error);
+ /// set spatial domain
+ inline void set_spatial_domain(const r_Minterval& domain);
+ /// set the internal representation of the array
+ inline void set_array(char*);
+ /// set size of internal memory representation in bytes
+ inline void set_array_size(r_Bytes);
+ /// set length of cell type in bytes
+ inline void set_type_length(r_Bytes);
+ /// set current data format
+ inline void set_current_format(r_Data_Format);
+
+ ///
+ //@}
+
+ //@Man: Methods for database communication (internal use only)
+ //@{
+ ///
+
+ /// inserts an object into the database
+ virtual void insert_obj_into_db();
+ /// insert myself into a specific collection in the database
+ void insert_obj_into_db(const char* collName);
+
+ ///
+ //@}
+
+ /// writes the state of the object to the specified stream
+ virtual void print_status(std::ostream& s = std::cout) const;
+
+ /// writes the state of the object to the specified stream
+ void print_status(std::ostream& s, int hexoutput) const;
+
+ protected:
+ /// spatial domain
+ r_Minterval domain;
+
+ /// pointer to the internal array representation
+ char* data;
+
+ /// size of internal array representation in bytes
+ r_Bytes data_size;
+
+ /// length of the cell base type in bytes
+ r_Bytes type_length;
+
+ /// store current data format
+ r_Data_Format current_format;
+
+ /// pointer to storage layout object
+ r_Storage_Layout* storage_layout;
+};
+
+#include "rasodmg/gmarray.icc"
+
+#endif
diff --git a/rasodmg/gmarray.icc b/rasodmg/gmarray.icc
new file mode 100644
index 0000000..f6453b2
--- /dev/null
+++ b/rasodmg/gmarray.icc
@@ -0,0 +1,119 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: gmarray.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_GMarray
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+
+inline const r_Minterval&
+r_GMarray::spatial_domain() const
+{
+ return domain;
+};
+
+
+
+inline char*
+r_GMarray::get_array()
+{
+ return data;
+};
+
+
+inline const char*
+r_GMarray::get_array() const
+{
+ return data;
+}
+
+
+inline void
+r_GMarray::set_array( char* newData )
+{
+ // In case the array already has an array allocated, free it first.
+// if (data != NULL) delete [] data;
+ data = newData;
+};
+
+
+
+inline void
+r_GMarray::set_current_format( r_Data_Format newFormat )
+{
+ current_format = newFormat;
+};
+
+
+
+inline r_Bytes
+r_GMarray::get_type_length() const
+{
+ return type_length;
+};
+
+
+
+inline r_Bytes
+r_GMarray::get_array_size() const
+{
+ return data_size;
+};
+
+
+
+inline r_Data_Format
+r_GMarray::get_current_format() const
+{
+ return current_format;
+};
+
+
+
+inline void
+r_GMarray::set_spatial_domain( const r_Minterval& dom )
+{
+ domain = dom;
+};
+
+
+
+inline void
+r_GMarray::set_type_length( r_Bytes newValue )
+{
+ type_length = newValue;
+}
+
+
+
+inline void
+r_GMarray::set_array_size( r_Bytes newValue )
+{
+ data_size = newValue;
+}
diff --git a/rasodmg/interesttiling.cc b/rasodmg/interesttiling.cc
new file mode 100644
index 0000000..aad8841
--- /dev/null
+++ b/rasodmg/interesttiling.cc
@@ -0,0 +1,809 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: interesttiling.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Interest_Tiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include "rasodmg/interesttiling.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/dirtiling.hh"
+#include "raslib/rminit.hh"
+
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <cstdlib>
+
+#ifdef AIX
+#include <strings.h>
+#endif
+
+// Uncoment the _VISUALIZE_2D_DECOMP_ line to generate ppm files the
+// visualization of the domain decomposition done by the algoritm
+// #define _VISUALIZE_2D_DECOMP_
+
+// Uncoment the folling line for some debug printfs on this class
+// #define _DEBUG_INTERESTTILING_
+
+#ifdef _VISUALIZE_2D_DECOMP_
+#include "tools/visualtiling2d.hh"
+#endif
+
+// This is a data structure for internal use within interesttiling.cc.
+// It is defined here because of problems with ptrepository.
+// -------------
+// This structure consists of a r_Minterval and a counter. Also, it has
+// some auxiliary constructors.
+
+class Classified_Block
+ {
+ public:
+ int intersection_count; // Intersection count
+ r_Minterval block; // The actual block
+
+ // Default constructor
+ Classified_Block(int count = 0);
+
+ // Constructor with the actual block and the counter
+ Classified_Block(const r_Minterval& b, int count = 0);
+
+ // Same data structure (this operator is needed because of dlist)
+ bool operator==(const Classified_Block& other) const;
+
+ // Different data structure (this operator is needed because of dlist)
+ bool operator!=(const Classified_Block& other) const;
+
+ // Friend of std::ostream (this operator is needed because of dlist)
+ friend std::ostream& operator<<(std::ostream& os, const Classified_Block& block);
+ };
+
+const char*
+r_Interest_Tiling::description = "dimensions, areas of interest, tile size (in bytes) and tile size limit [NOLIMIT|REGROUP|SUBTILING|REGROUPSUBTILING] (ex: \"2;[0:9,0:9];[100:109,0:9];100;REGROUPSUBTILING\")";
+
+const char* r_Interest_Tiling::tilesizelimit_name_nolimit ="NOLIMIT";
+const char* r_Interest_Tiling::tilesizelimit_name_regroup ="REGROUP";
+const char* r_Interest_Tiling::tilesizelimit_name_subtiling ="SUBTILING";
+const char* r_Interest_Tiling::tilesizelimit_name_regroupandsubtiling ="REGROUPSUBTILING";
+const char* r_Interest_Tiling::all_tilesizelimit_names[r_Interest_Tiling::NUMBER]={
+ tilesizelimit_name_nolimit,
+ tilesizelimit_name_regroup,
+ tilesizelimit_name_subtiling,
+ tilesizelimit_name_regroupandsubtiling
+ };
+
+r_Interest_Tiling::Tilesize_Limit
+r_Interest_Tiling::get_tilesize_limit_from_name(const char* name)
+{
+
+ if(!name) {
+ RMInit::logOut << "r_Interest_Tiling::get_tilesize_limit_from_name(" << (name?name: "NULL") << ")" << endl;
+ return r_Interest_Tiling::NUMBER;
+ }
+
+ unsigned int i=r_Interest_Tiling::NUMBER;
+
+ for (i=0; i<(unsigned int)r_Interest_Tiling::NUMBER; i++)
+ {
+ if (strcasecmp(name, all_tilesizelimit_names[i]) == 0)
+ break;
+ }
+ return (r_Interest_Tiling::Tilesize_Limit)i;
+}
+
+const char*
+r_Interest_Tiling::get_name_from_tilesize_limit(Tilesize_Limit tsl)
+{
+ static const char* unknown="UNKNOWN";
+ unsigned int idx = (unsigned int)tsl;
+
+ if (idx >= (unsigned int)r_Interest_Tiling::NUMBER)
+ return unknown;
+
+ return all_tilesizelimit_names[idx];
+}
+
+r_Interest_Tiling::r_Interest_Tiling(const char* encoded) throw (r_Error)
+ : r_Dimension_Tiling(0,0)
+{
+ if(!encoded)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << (encoded?encoded: "NULL") << ")" << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ std::vector<r_Minterval> vectInterestAreas;
+ r_Interest_Tiling::Tilesize_Limit tileSizeLimit;
+ r_Dimension tileD=0;
+ r_Bytes tileS=0, lenToConvert=0;
+ const char *pStart=NULL, *pRes=NULL, *pTemp=NULL, *pEnd=NULL;
+ char *pToConvert=NULL;
+
+
+ pStart=encoded;
+ pEnd=pStart+strlen(pStart);
+ pTemp=pStart;
+ pRes=strstr(pTemp,COLON);
+
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with dimension
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert,pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ tileD=strtol(pToConvert, (char**)NULL, DefaultBase);
+ if (!tileD)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileD < 0)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pToConvert << "\", is negative." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest areas, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //parse interest areas
+ pTemp=pRes;
+ pRes=strstr(pTemp,COLON);
+
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest areas." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ while(pRes)
+ {
+ //is interest areas?
+ if(*pTemp != *LSQRBRA)
+ break;
+
+ //copy parsed interest area
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ //add to vector
+ try
+ {
+ r_Minterval a(pToConvert);
+ vectInterestAreas.push_back(a);
+ }
+ catch(r_Error& err)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest area from \"" << pToConvert << "\"." << endl;
+ RMInit::logOut << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ delete [] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest areas, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //try next item
+ pTemp=pRes;
+ pRes=strstr(pTemp, COLON);
+ }
+
+ if(vectInterestAreas.empty())
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest areas, no interest areas specified." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with tile size
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ tileS=strtol(pToConvert, (char**)NULL, DefaultBase);
+ if (!tileS)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile size from \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileS < 0)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile size from \"" << pToConvert << "\", is negative." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile size limit, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ pTemp=pRes;
+
+ tileSizeLimit=r_Interest_Tiling::get_tilesize_limit_from_name(pTemp);
+ if(tileSizeLimit==r_Interest_Tiling::NUMBER)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile size limit from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ iareas = vectInterestAreas;
+ ts_strat = tileSizeLimit;
+ dimension = tileD;
+ tile_size = tileS;
+}
+
+r_Interest_Tiling::r_Interest_Tiling(r_Dimension dim, const std::vector<r_Minterval>& interest_areas, r_Bytes ts, Tilesize_Limit strat) throw (r_Error)
+ : r_Dimension_Tiling(dim, ts),
+ iareas(interest_areas),
+ ts_strat(strat)
+{
+ for (std::vector<r_Minterval>::iterator it = iareas.begin(); it != iareas.end(); it++)
+ if (it->dimension() != dimension)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << dim << ", " << interest_areas << ", " << ts << ", " << strat << ") the interest area domain " << *it << " does not match the dimension of this tiling scheme (" << dimension << ")" << endl;
+ throw r_Edim_mismatch(dimension, it->dimension());
+ }
+}
+
+r_Interest_Tiling::~r_Interest_Tiling()
+{
+}
+
+r_Tiling* r_Interest_Tiling::clone() const
+{
+ r_Tiling* copy = new r_Interest_Tiling(dimension, iareas, tile_size, ts_strat);
+ return copy;
+}
+
+void r_Interest_Tiling::print_status(std::ostream& os) const
+{
+ os << "r_Interest_Tiling[ ";
+ r_Dimension_Tiling::print_status(os);
+ os << " interest areas = " << iareas << ", tiling strategy = " << ts_strat << " ]";
+}
+
+r_Tiling_Scheme
+r_Interest_Tiling::get_tiling_scheme() const
+ {
+ return r_InterestTiling;
+ }
+
+static int r_Range_comp(const void *elem1, const void *elem2)
+{
+ r_Range e1 = *((r_Range*) elem1);
+ r_Range e2 = *((r_Range*) elem2);
+
+ if (e1 == e2)
+ return 0;
+
+ if (e1 < e2)
+ return -1;
+ else
+ return +1;
+}
+
+std::vector<r_Dir_Decompose>*
+r_Interest_Tiling::make_partition(const r_Minterval& domain) const
+{
+ r_Dimension dim = domain.dimension();
+ int total = 2 * iareas.size();
+
+ // We need one decomp from each dimension
+ std::vector<r_Dir_Decompose>* part = new std::vector<r_Dir_Decompose>(dim);
+
+ // We have at most (number of interest areas + 2) intervals
+ r_Range* intervals = new r_Range[total + 2];
+
+ // Create iterator for interest areas
+ std::vector<r_Minterval>::const_iterator it = iareas.begin();
+ int total_iareas = iareas.size();
+
+
+ // For all dimensions
+ for (r_Dimension i = 0; i < dim; i++)
+ {
+ it = iareas.begin(); // Reset iterator
+ intervals[0] = domain[i].low(); // Input lower domain limit
+ intervals[total+1] = domain[i].high(); // Input higher domain limit
+
+
+ for (int j = 1; j < total + 1; j += 2, ++it) // For all possible intervals
+ {
+ if ((*it)[i].low()-1 <= domain[i].low()) // Input low iarea limit
+ intervals[j] = domain[i].low();
+ else
+ intervals[j] = (*it)[i].low()-1;
+
+ intervals[j+1] = (*it)[i].high(); // Input higher iarea limit
+ }
+
+ // Sort the table
+ qsort((void*) intervals, total+2, sizeof(r_Range), r_Range_comp);
+
+ // Create partition using the limits table
+ for (int k=0; k<total+2; k++) // all limits must be checked
+ {
+ if (k == total+1) // if on the last limit...
+ ((*part)[i]) << intervals[k]; // input it
+ else // else
+ if (intervals[k] != intervals[k+1]) // if it is unique
+ ((*part)[i]) << intervals[k]; // input it
+ }
+ }
+
+ // Free memory
+ delete [] intervals;
+
+ // Return result
+ return part;
+}
+
+std::vector<r_Minterval>*
+r_Interest_Tiling::group(std::vector<r_Minterval>& blocks, r_Bytes typelen, Blocks_Type btype) const
+{
+ r_Bytes tilesize = get_tile_size();
+ int joins = 0;
+ bool group_blocks = true;
+
+ // The list of threated blocks
+ std::vector<r_Minterval>* treated = new std::vector<r_Minterval>;
+
+ // An iterator for the blocks list
+ std::vector<r_Minterval>::iterator blocks_it = blocks.begin();
+
+ // The current block
+ r_Minterval current_block;
+
+ // For all the blocks in list
+ while (!blocks.empty())
+ {
+ // Get first block from list
+ current_block = blocks.back();
+ blocks.pop_back();
+
+ //this is neccessary when the compiler optimizes out the .end() check
+ unsigned int numberOfLevels = blocks.size();
+ for (blocks_it = blocks.begin(); blocks_it != blocks.end(); blocks_it++)
+ {
+ if (numberOfLevels == 0)
+ {
+ RMInit::logOut << "r_Interest_Tiling::group() the for loop was incorrectly optimized. breaking the loop." << endl;
+ break;
+ }
+ r_Minterval aux = *blocks_it;
+
+ // In principle two blocks can't be merged
+ group_blocks = false;
+
+ // If they can be merged
+ if (current_block.is_mergeable(aux))
+ {
+ std::vector<r_Minterval>::iterator ia_it = blocks.begin();
+
+ switch (btype)
+ {
+ case BLOCKS_A:
+
+ group_blocks = true;
+
+ // Check if the two blocks belong exaclty to the same iareas
+ for (; ia_it != blocks.end(); ia_it++)
+ {
+ if (aux.intersects_with(*ia_it) != current_block.intersects_with(*ia_it))
+ {
+ group_blocks = false;
+ break;
+ }
+ }
+
+ break;
+
+ case BLOCKS_B:
+
+ for (; ia_it != blocks.end(); ia_it++) // For all iareas
+ {
+ // Find the one this block intersects
+ if (current_block.intersects_with(*ia_it))
+ {
+ // Check if the other area intersects it
+ if (!aux.intersects_with(*ia_it))
+ group_blocks = false;
+ else
+ group_blocks = true;
+
+ break;
+ }
+ }
+
+ if (!group_blocks)
+ break;
+
+ group_blocks = false;
+
+ case BLOCKS_C: // Falls in (this is, also applies to B);
+
+ // Only on this two strategies, tilesize should be looked at
+ if ((ts_strat == REGROUP) || (ts_strat == REGROUP_AND_SUBTILING))
+ {
+ // If the resulting size isn't larger than tilesize
+ if ((current_block.cell_count()+aux.cell_count()) * typelen
+ < get_tile_size())
+ group_blocks = true;
+ }
+ else
+ group_blocks = true;
+
+ break;
+ }
+ }
+
+ // take care of the iterator advance, if is possible
+ if (group_blocks)
+ {
+ // Merge them
+ blocks.erase(blocks_it); // Automatically advances to next block
+ // take care of the size of the blocks
+ numberOfLevels--;
+ current_block.closure_with(aux);
+ ++joins;
+ }
+ else
+ numberOfLevels--;
+ }
+
+ // Update the treated list with the current block
+ treated->push_back(current_block);
+ }
+
+ std::vector<r_Minterval>* result = 0;
+
+ // If there was joins, the algoritm must be repeted
+ if (joins != 0)
+ {
+ result = group(*treated, typelen, btype);
+ delete treated;
+ }
+ else
+ {
+ result = treated;
+ }
+
+ // Return the result
+ return result;
+}
+
+std::vector<r_Minterval>*
+r_Interest_Tiling::compute_tiles(const r_Minterval& domain, r_Bytes typelen) const throw (r_Error)
+{
+ r_Dimension num_dims = domain.dimension(); // Dimensionality of dom
+if (domain.dimension() != dimension)
+ {
+ RMInit::logOut << "r_Interest_Tiling::compute_tiles(" << domain << ", " << typelen << ") dimension (" << dimension << ") does not match dimension of object to tile (" << num_dims << ")" << endl;
+ throw r_Edim_mismatch(dimension, num_dims);
+ }
+if (typelen > tile_size)
+ {
+ RMInit::logOut << "r_Interest_Tiling::compute_tiles(" << domain << ", " << typelen << ") tile size (" << tile_size << ") is smaller than type length (" << typelen << ")" << endl;
+ throw r_Error(TILESIZETOOSMALL);
+ }
+
+#ifdef _VISUALIZE_2D_DECOMP_ // User wants a visual
+ static int count; // Number of decomps
+ ++count; // Update num decomps
+ // of the 2D decomp.
+ Visual_Tiling_2D* vis;
+ if (domain.dimension() == 2)
+ {
+ // Create an object for visualization
+ char fname[80];
+ sprintf(fname, "2D_decomp_int_%d.ppm", count);
+ vis = new Visual_Tiling_2D(domain, fname);
+ }
+
+#endif
+
+
+ // *** Main algoritm ***
+
+ // The result
+ std::vector<r_Minterval>* result = new std::vector<r_Minterval>;
+
+ // Create a partition for dir tiling
+ std::vector<r_Dir_Decompose>* part = make_partition(domain);
+
+ // Perform dirtiling
+ r_Dir_Tiling *dir_tiling= NULL;
+ std::vector<r_Minterval>* dir_domain=NULL;
+
+ try
+ {
+ dir_tiling=new r_Dir_Tiling(num_dims, *part, tile_size, r_Dir_Tiling::WITHOUT_SUBTILING);
+
+ // Compute all tiles (directional tiles)
+ dir_domain = dir_tiling->compute_tiles(domain, typelen);
+
+ delete dir_tiling;
+ }
+ catch(r_Error& err)
+ {
+ delete result;
+ delete part;
+ if(dir_tiling)
+ delete dir_tiling;
+ throw;
+ }
+
+ // Get an interator for interest areas
+ //std::vector<r_Minterval>::iterator interest_area;
+
+ // Create a list for holding the classifed blocks
+ std::vector<Classified_Block> part_domain;
+
+ // Finds how many intersections exist between a block an the interest areas
+ for (std::vector<r_Minterval>::iterator dir_block = dir_domain->begin(); dir_block != dir_domain->end(); dir_block++)
+ {
+ Classified_Block b(*dir_block, 0);
+
+ for (std::vector<r_Minterval>::const_iterator interest_area = iareas.begin(); interest_area != iareas.end(); interest_area++)
+ {
+ if (b.block.intersects_with(*interest_area))
+ ++b.intersection_count;
+ }
+
+ part_domain.push_back(b);
+ }
+
+ // Lists used for grouping blocks
+ std::vector<r_Minterval> Out;
+ std::vector<r_Minterval> In_Unique;
+ std::vector<r_Minterval> In_Common;
+
+ // Divide blocks into lists according to their number of intersections
+ for (std::vector<Classified_Block>::iterator class_block = part_domain.begin(); class_block != part_domain.end(); class_block++)
+ {
+ switch ((*class_block).intersection_count)
+ {
+ case 0:
+ Out.push_back((*class_block).block);
+ break;
+ case 1:
+ In_Unique.push_back((*class_block).block);
+ break;
+ default:
+ In_Common.push_back((*class_block).block);
+ break;
+ }
+ }
+
+
+ // Group blocks
+ std::vector<r_Minterval>* Blocks_A = group(In_Common, typelen, BLOCKS_A);
+ std::vector<r_Minterval>* Blocks_B = group(In_Unique, typelen, BLOCKS_B);
+ std::vector<r_Minterval>* Blocks_C = group(Out, typelen, BLOCKS_C);
+
+
+ std::vector<r_Minterval>::iterator it_A = Blocks_A->begin();
+ std::vector<r_Minterval>::iterator it_B = Blocks_B->begin();
+ std::vector<r_Minterval>::iterator it_C = Blocks_C->begin();
+
+ // If may be necessary to perform sub-tiling
+ if ((ts_strat == SUB_TILING) || (ts_strat == REGROUP_AND_SUBTILING))
+ {
+ // Variable to hold result of sub-tiling
+ std::vector<r_Minterval>* subtiles = 0;
+
+ // We need an array to hold the 3 iterators of the resulting blocks
+ std::vector<r_Minterval>::iterator* blocks_it[3];
+ std::vector<r_Minterval>* blocks_vec[3];
+
+ // Put iterators on the list
+ blocks_it[0] = &it_A;
+ blocks_it[1] = &it_B;
+ blocks_it[2] = &it_C;
+
+ blocks_vec[0] = Blocks_A;
+ blocks_vec[1] = Blocks_B;
+ blocks_vec[2] = Blocks_C;
+
+ // For all the lists (Blocs_A, Blocks_B and Blocks_C)
+ for (int j=0; j<3; j++)
+ {
+ // Reset iterator to the begin
+ (*blocks_it[j]) = blocks_vec[j]->begin();
+
+ // Tile each block if necessary
+ for (; *blocks_it[j] != blocks_vec[j]->end(); (*blocks_it[j])++)
+ {
+ if ((**blocks_it[j]).cell_count()*typelen > get_tile_size())
+ {
+ // Create a specification of a regular n-dim cube grid
+ r_Minterval specs(num_dims);
+ for (r_Dimension i=0; i<num_dims; i++)
+ {
+ specs << r_Sinterval((r_Range)0, (**blocks_it[j])[i].high() - (**blocks_it[j])[i].low());
+ }
+
+ // Class for performing sub-tiling
+ r_Aligned_Tiling subtiling(specs, get_tile_size());
+
+ subtiles = subtiling.compute_tiles(**blocks_it[j], typelen);
+ for (std::vector<r_Minterval>::iterator it = subtiles->begin(); it != subtiles->end(); it++)
+ {
+ result->push_back(*it);
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ (*vis) << (*it);
+#endif
+ }
+
+ delete subtiles;
+ }
+ else // No subtiling needed
+ {
+ // Insert block as it is
+ result->push_back(**blocks_it[j]);
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ (*vis) << (**blocks_it[j]);
+#endif
+ }
+ }
+ }
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(255, 255, 0);
+
+ interest_area.seek_begin();
+ while (interest_area.not_done())
+ {
+ (*vis) << (*interest_area);
+ ++interest_area;
+ }
+ }
+#endif
+
+ }
+ else
+ {
+ // The result is just the sum of all blocks
+
+ result->insert(result->end(), Blocks_A->begin(), Blocks_A->end());
+ result->insert(result->end(), Blocks_B->begin(), Blocks_B->end());
+ result->insert(result->end(), Blocks_C->begin(), Blocks_C->end());
+
+ // Visualization
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(255, 255, 0);
+ for (it_A.seek_begin(); it_A.not_done(); it_A++)
+ (*vis) << *it_A;
+
+ vis->set_pen(0, 255, 0);
+ for (it_B.seek_begin(); it_B.not_done(); it_B++)
+ (*vis) << *it_B;
+
+ vis->set_pen(0, 0, 255);
+ for (it_C.seek_begin(); it_C.not_done(); it_C++)
+ (*vis) << *it_C;
+ }
+#endif
+ }
+
+ // *** End of the main algorithm ***
+
+ // *** Clean up ***
+
+ delete part;
+ delete dir_domain;
+ delete Blocks_A;
+ delete Blocks_B;
+ delete Blocks_C;
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ delete vis;
+#endif
+
+ // Return result
+
+ return result;
+}
+
+
+
+std::ostream& operator<<(std::ostream& os, const Classified_Block block);
+
+
+Classified_Block::Classified_Block(int count)
+ : intersection_count(count)
+ {
+ }
+
+Classified_Block::Classified_Block(const r_Minterval& b, int count)
+ : intersection_count(count),
+ block(b)
+ {
+ }
+
+
+bool Classified_Block::operator==(const Classified_Block& other) const
+{
+ return (this->block == other.block)
+ && (this->intersection_count == other.intersection_count);
+}
+
+bool Classified_Block::operator!=(const Classified_Block& other) const
+{
+ return !(*this == other);
+}
+
+
+std::ostream& operator<<(std::ostream& os, const Classified_Block block)
+{
+ os << "CBlock(" << block.intersection_count << "x: " << block.block << ")";
+
+ return os;
+}
diff --git a/rasodmg/interesttiling.hh b/rasodmg/interesttiling.hh
new file mode 100644
index 0000000..944ada8
--- /dev/null
+++ b/rasodmg/interesttiling.hh
@@ -0,0 +1,183 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: dirtiling.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Interest_Tiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_INTERESTTILING_HH_
+#define _R_INTERESTTILING_HH_
+
+class r_Dir_Decompose;
+class r_Interest_Tiling;
+#include "rasodmg/tiling.hh"
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ This class implements the "Interesting Areas" tiling algorithm.
+ The user specifies which areas are of interest to him and tiling is
+ performed accordingly.
+
+ Example of usage:
+ The user says that [10:20, 50:60] and [18:50, 65:70] are of interest
+ to him in the [0:1000, 0:1000] domain. Tiling should be done according
+ to this setting. To specify this with this class the following code
+ would work:
+
+ ...
+
+ r_Minterval domain(2);
+ domain << r_Sinterval(0L, 1000L) << r_Sinterval(0L, 1000L);
+
+ r_Minteval interest1(2);
+ interest1 << r_Sinterval(10L, 20L) << r_Sinterval(50L, 60L);
+
+ r_Minterval interest2(2);
+ interest2 << r_Sinterval(18L, 50L) << r_Sinterval(65L, 70L);
+
+ std::vector<r_Minterval> interest_areas;
+ interest_areas.insert_element(interest1);
+ interest_areas.insert_element(interest2);
+
+ r_Interest_Tiling(interest_areas);
+
+ ...
+*/
+
+class r_Interest_Tiling : public r_Dimension_Tiling
+{
+ public:
+
+ /// Possible strategies to limit the tilesize
+ enum Tilesize_Limit {NO_LIMIT, REGROUP, SUB_TILING, REGROUP_AND_SUBTILING, NUMBER};
+
+ /// read everything from an encoded string
+ /// e.g. "2;[0:9,0:9];[100:109,0:9];100;REGROUPSUBTILING"
+ r_Interest_Tiling(const char* encoded) throw (r_Error);
+
+ r_Interest_Tiling(r_Dimension dim,
+ const std::vector<r_Minterval>& interest_areas,
+ r_Bytes ts = RMInit::clientTileSize,
+ Tilesize_Limit strat = SUB_TILING) throw (r_Error);
+ /**
+ It takes as parameter a list containing the areas of interest to
+ the user and also the tilesize to be used.
+ The constructor also takes as parameter the tilesize limitation
+ strategy, that can be the following:
+
+ NO_LIMIT: The generated blocks can have any size.
+ REGROUP: Only when performing grouping/merging of blocks, the
+ size of the resulting block of two merges is checked
+ against tilesize. If it's bigger, they are not merged.
+ Blocks larger than tilesize may exist (for instance,
+ if the user specifies an interest area larger then
+ tilesize).
+ SUB_TILING: In this strategie, regrouping is done regardless of the
+ size of the generated blocks. After all the blocks are
+ created, sub-tiling is performed on those whose size is
+ larger than tilesize.
+ REGROUP_AND_SUBTILING: This combines the last two strategies. When
+ merging blocks, blocks larger than tilesize are never
+ created and, when the final blocks are all created,
+ sub-tiling is performed on those whose size is larger
+ then tilesize.
+ An exception is thrown when the dimensions of the domains does not match the
+ specified dimension.
+ */
+
+ virtual ~r_Interest_Tiling();
+
+ std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error);
+
+ virtual void print_status(std::ostream& os) const;
+
+ virtual r_Tiling* clone() const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ Get a tilesize limit for a tilisize limit name
+ */
+ static r_Interest_Tiling::Tilesize_Limit get_tilesize_limit_from_name(const char* name);
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ Get a tilisize limit name for a tilesize limit
+ */
+ static const char* get_name_from_tilesize_limit(Tilesize_Limit tsl);
+
+ static const char* description;
+
+ protected: // methods.
+
+ /// Given a domain and a set of interest areas (internal) gener. partition
+ std::vector<r_Dir_Decompose>* make_partition(const r_Minterval& domain) const;
+
+ /// The Block types (A, B or C)
+ enum Blocks_Type {BLOCKS_A, BLOCKS_B, BLOCKS_C };
+ /**
+ A Blocks ---> Blocks that belong to two or more interest zones
+ (non-groupable)
+ B Blocks ---> Blocks within the same interest zone
+ (groupable by interest zone)
+ C Blocks ---> Blocks outside interest zones
+ (groupable)
+ */
+
+ /// Merge as many blocks together in a list as possible
+ std::vector<r_Minterval>* group(std::vector<r_Minterval>& blocks, r_Bytes typelen, Blocks_Type btype) const;
+ /**
+ Parameters: the block list, the lenght of the base cells and
+ the type of the block (A, B or C)
+ */
+
+ /// Tilesize limitation strategie
+ Tilesize_Limit ts_strat;
+
+ /// Interest areas
+ std::vector<r_Minterval> iareas;
+
+
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ The names of all tilesizelimit types, to avoid redundant storage and inconsistencies.
+ The variable name convention is the prefix tilisizelimit_name_ followed by the name
+ of the data format in lower case, i.e. for NOLIMIT tilisizelimit_name_nolimit.
+ In addition there's an array of names all_tilesizelimit_names where the tilesize limit
+ can be used as index to get the name.
+ */
+ static const char* tilesizelimit_name_nolimit;
+ static const char* tilesizelimit_name_regroup;
+ static const char* tilesizelimit_name_subtiling;
+ static const char* tilesizelimit_name_regroupandsubtiling;
+
+ static const char* all_tilesizelimit_names[r_Interest_Tiling::NUMBER];
+};
+
+#endif
diff --git a/rasodmg/iterator.cc b/rasodmg/iterator.cc
new file mode 100644
index 0000000..cd9e167
--- /dev/null
+++ b/rasodmg/iterator.cc
@@ -0,0 +1,216 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: iterator.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Iterator
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsiditerator[] = "@(#)rasodmg, r_Iterator: $Id: iterator.cc,v 1.18 2002/08/23 11:18:44 schatz Exp $";
+
+#include <iostream>
+using namespace std;
+
+#include "rasodmg/iterator.hh"
+
+#ifdef EARLY_TEMPLATE
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define ITERATOR_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/collection.hh"
+
+#ifdef ITERATOR_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+template<class T>
+r_Iterator<T>::r_Iterator()
+{
+ // use default constructor only with assignment operator!
+ collection = 0;
+ ptr = 0;
+ ndone = 0;
+}
+
+template<class T>
+r_Iterator<T>::r_Iterator( const r_Iterator<T>& iter )
+{
+ collection = iter.collection;
+ ptr = iter.ptr;
+ ndone = iter.ndone;
+}
+
+template<class T>
+r_Iterator<T>::r_Iterator( r_Collection<T>& source, int removed_objects )
+{
+ collection = &source;
+ // sorry for this awful cast but there is
+ // no standard conversion of r_Collection<T>::CNode* to r_Collection::CNode*
+ if( removed_objects )
+ ptr = (typename r_Collection<T>::CNode*)source.removed_objects;
+ else
+ ptr = (typename r_Collection<T>::CNode*)source.coll;
+
+ ndone = (ptr->elem != 0);
+}
+
+template<class T>
+r_Iterator<T>::~r_Iterator()
+{
+}
+
+template<class T>
+r_Iterator<T>&
+r_Iterator<T>::operator=( const r_Iterator<T>& iter )
+{
+ if( this != &iter )
+ {
+ collection = iter.collection;
+ ptr = iter.ptr;
+ ndone = iter.ndone;
+ }
+
+ return *this;
+}
+
+template<class T>
+int
+r_Iterator<T>::is_equal(const r_Iterator<T>& iter) const
+{
+ if ( collection == iter.collection)
+ if ( ptr == iter.ptr )
+ return 1;
+ return 0;
+}
+
+
+template<class T>
+int
+operator==( const r_Iterator<T>& iter1, const r_Iterator<T>& iter2 )
+{
+ return iter1.is_equal(iter2);
+}
+
+template<class T>
+int
+operator!=( const r_Iterator<T>& iter1, const r_Iterator<T>& iter2 )
+{
+ return !iter1.is_equal(iter2);
+}
+
+template<class T>
+r_Iterator<T>&
+r_Iterator<T>::operator++()
+{
+ // ++prefix operator
+
+ if ( !ndone )
+ throw r_Error( r_Error::r_Error_IteratorExhausted );
+ if ( ptr->next != 0 )
+ ptr = ptr->next;
+ else
+ ndone = 0;
+
+ return *this;
+}
+
+template<class T>
+r_Iterator<T>
+r_Iterator<T>::operator++( int )
+{
+ // postfix++ operator
+ // create a copy of this, increment the original and return the copy
+ r_Iterator<T> result( *this );
+
+ operator++();
+
+ return result;
+}
+
+template<class T>
+T
+r_Iterator<T>::operator*()
+ throw( r_Error )
+{
+ if ( !ndone || ptr->elem == 0 )
+ {
+ r_Error err = r_Error( r_Error::r_Error_IteratorExhausted );
+ throw err;
+ }
+
+ // The following line was return *(ptr->elem) but the HP compiler had problems
+ // while instantiating the code. CNode::elem was of a different type than T.
+ return *((T*)ptr->elem);
+}
+
+template<class T>
+T
+r_Iterator<T>::get_element() const
+ throw( r_Error )
+{
+ if ( !ndone || ptr->elem == 0 )
+ throw r_Error( r_Error::r_Error_IteratorExhausted );
+ else
+ return *(ptr->elem);
+}
+
+template<class T>
+int
+r_Iterator<T>::next( T& element )
+{
+ if ( !ndone || ptr->elem == 0 ) return 0;
+ element = *(ptr->elem);
+ advance();
+ return 1;
+}
+
+template<class T>
+void
+r_Iterator<T>::reset( int removed_objects )
+{
+ if( removed_objects )
+ ptr = (typename r_Collection<T>::CNode*)collection->removed_objects;
+ else
+ ptr = (typename r_Collection<T>::CNode*)collection->coll;
+
+ ndone = (ptr->elem != 0);
+}
+
+template<class T>
+void
+r_Iterator<T>::advance()
+{
+ if ( !ndone )
+ throw r_Error( r_Error::r_Error_IteratorExhausted );
+ if ( ptr->next != 0 )
+ ptr = ptr->next;
+ else
+ ndone = 0;
+}
diff --git a/rasodmg/iterator.hh b/rasodmg/iterator.hh
new file mode 100644
index 0000000..995e7b6
--- /dev/null
+++ b/rasodmg/iterator.hh
@@ -0,0 +1,137 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: iterator.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Iterator
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_ITERATOR_
+#define _D_ITERATOR_
+
+#include "raslib/error.hh"
+
+#ifdef __VISUALC__
+template <class T> class r_Collection;
+#else
+#include "rasodmg/collection.hh"
+#endif
+
+//@ManMemo: Module: {\bf rasodmg}
+
+
+
+/*@Doc:
+
+ The template class \Ref{r_Iterator} defines the generic
+ behavior for iteration. All iterators use a consistent protocol
+ for sequentially returning each element from the collection over
+ which the iteration is defined.
+ When an iterator is constructed, it is either initialized with
+ another iterator or is set to null. When an iterator is constructed
+ via the {\tt create_iterator()} method defined in \Ref{r_Collection},
+ the iterator is initailized to point to the first element, if there
+ is one.
+*/
+
+template <class T>
+class r_Iterator
+{
+ public:
+ /// default constructor
+ r_Iterator();
+ /// copy constructor
+ r_Iterator( const r_Iterator<T>& iter );
+ /// constructor getting the collection on which to iterate (used for {\tt r_Collection::create_iterator()})
+ r_Iterator( r_Collection<T>& source, int removed_objects=0 );
+ /**
+ Creates an iterator which points to the first element of the element collection. If
+ {\tt removed_objects} ist set to 1, the iterator points to the first element of
+ the list containing the removed objects (for internal use).
+ */
+
+ /// destructor
+ ~r_Iterator();
+
+ /// assignment operator
+ r_Iterator<T>& operator=( const r_Iterator<T>& iter );
+ /// comparisons: equal if they point to the same element in the same collection,
+ /// not equal if they point to different collections or elements
+ int is_equal( const r_Iterator<T>& iter ) const;
+
+ /// prefix incrementor
+ r_Iterator<T>& operator++();
+ /// postfix incrementor
+ r_Iterator<T> operator++( int );
+
+ /// re-initialize the iterator to the start of iteration for the same collection
+ void reset( int removed_objects=0 );
+ /**
+ Resets the iterator to point to the first element of the element collection. If
+ {\tt removed_objects} ist set to 1, the iterator points to the first element of
+ the list containing the removed objects (for internal use).
+ */
+
+ /// returns 1 if there are more elements to be visited in the iteration and 0 if iteration is complete
+ inline int not_done() const;
+ /// advances one element
+ void advance();
+
+ /// the dereference operator gets the actual element
+ T operator*() throw( r_Error );
+ /// gets the actual element
+ T get_element() const throw( r_Error );
+
+ /// gets the actual element, advances one element, and returns whether iteration is complete or not
+ int next( T& element );
+
+ /// replaces the actual element (can only be used with r_List)
+ void replace_element( const T& element );
+
+ private:
+ /// flag for end of iteration
+ int ndone;
+ /// pointer to the collection on which is iterated
+ r_Collection<T>* collection;
+ /// pointer to the actual element
+ typename r_Collection<T>::CNode* ptr;
+
+};
+
+#include "iterator.icc"
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#ifdef __VISUALC__
+#include "iterator.cpp"
+#else
+#include "iterator.cc"
+#endif
+#endif
+#endif
+
+#endif
diff --git a/rasodmg/iterator.icc b/rasodmg/iterator.icc
new file mode 100644
index 0000000..5bd4974
--- /dev/null
+++ b/rasodmg/iterator.icc
@@ -0,0 +1,39 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: iterator.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Iterator
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+template<class T>
+inline int
+r_Iterator<T>::not_done() const
+{
+ return ndone;
+}
diff --git a/rasodmg/marray.cc b/rasodmg/marray.cc
new file mode 100644
index 0000000..403c91f
--- /dev/null
+++ b/rasodmg/marray.cc
@@ -0,0 +1,354 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: marray.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Marray
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsidmarray[] = "@(#)rasodmg, r_Marray: $Id: marray.cc,v 1.36 2002/08/23 11:18:44 schatz Exp $";
+
+#include "rasodmg/marray.hh"
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define MARRAY_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/database.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef COLLECTION_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+#include "raslib/rmdebug.hh"
+
+#include <string.h> // for memcpy()
+#include <iostream>
+#include <iomanip>
+
+
+
+template<class T>
+r_Marray<T>::r_Marray() throw(r_Error)
+ : r_GMarray()
+{
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( const r_Minterval& initDomain, r_Storage_Layout* stl ) throw(r_Error)
+ : r_GMarray( initDomain, sizeof(T), stl )
+{
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( const r_Minterval& initDomain, const T& value, r_Storage_Layout* stl ) throw(r_Error)
+ : r_GMarray( initDomain, sizeof(T), stl )
+{
+ T* dataPtr = (T*)data;
+
+ for( unsigned long i=0; i<domain.cell_count(); i++ )
+ dataPtr[i] = value;
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( const r_Minterval& initDomain, r_InitFunction function, r_Storage_Layout* stl ) throw(r_Error)
+ : r_GMarray( initDomain, sizeof(T), stl )
+{
+ r_Dimension d;
+ int done = 0;
+ r_Point pt( domain.dimension() );
+
+ // memory pointer of type T
+ T* dataPtr = (T*)data;
+
+ // initialize the iterating point to the lowest values in each dimension
+ for( d=0; d<pt.dimension(); d++ )
+ pt[d] = domain[d].low();
+
+ // iterate point pt through the spatial domain and apply the
+ // initializing function for each point
+ while(!done)
+ {
+ // execute function on cell
+ dataPtr[domain.cell_offset( pt )] = (*function)( pt );
+
+ // increment coordinate
+ d = 0;
+ while( ++pt[d] > domain[d].high() )
+ {
+ pt[d] = domain[d].low();
+ d++;
+ if(d >= domain.dimension())
+ {
+ done = 1;
+ break;
+ }
+ }
+ }
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( const r_Marray<T> &obj ) throw(r_Error)
+ : r_GMarray( obj )
+{
+ RMDBCLASS( "r_Marray<T>", "r_Marray<T>( const r_Marray<T>& )", "rasodmg", __FILE__, __LINE__ )
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( r_GMarray &obj ) throw(r_Error)
+ : r_GMarray( obj )
+{
+}
+
+
+
+template<class T>
+r_Marray<T>::~r_Marray()
+{
+}
+
+
+
+template<class T>
+const r_Marray<T> &r_Marray<T>::operator=( const r_Marray<T> &marray )
+{
+ return (r_Marray<T> &) r_GMarray::operator=( marray );
+}
+
+
+
+template<class T>
+r_Marray<T>
+r_Marray<T>::operator[] ( long cordnt ) const
+ throw( r_Eindex_violation )
+{
+ // check if self does not just represent a cell
+ if( domain.dimension() == 0 )
+ throw( r_Eindex_violation( cordnt, 0, 0 ) );
+
+ // check if the index is valid
+ if( cordnt < domain[0].low() || cordnt > domain[0].high() )
+ throw( r_Eindex_violation( cordnt, domain[0].low(), domain[0].high() ) );
+
+ // build a new spatial domain
+ r_Minterval newDomain( domain.dimension()-1 );
+
+ // and initialize it
+ for( int i=0; i<newDomain.dimension(); i++ )
+ newDomain[i] = domain[i+1];
+
+ // build a new Marray
+ r_Marray<T> newMDD( newDomain );
+
+ // and fill it with data
+ unsigned long newCellCount = newDomain.cell_count();
+ unsigned long byteCount = ( newDomain.dimension() ? newDomain.cell_count() : 1 ) * type_length;
+ T* dataPtr = (T*)data; // typed pointer to the data
+
+ memcpy( newMDD.data, &(dataPtr[(cordnt-domain[0].low())*newCellCount]), (unsigned int)byteCount );
+
+ return newMDD;
+}
+
+
+
+template<class T>
+r_Marray<T>
+r_Marray<T>::operator[] ( const r_Minterval& mint ) const
+ throw( r_Edim_mismatch )
+{
+ unsigned long offset;
+ r_Point pt;
+ int pt_valid;
+
+ // first test dimensionality
+ if( domain.dimension() != mint.dimension() )
+ throw( r_Edim_mismatch( domain.dimension(), mint.dimension() ) );
+
+ // build a new Marray with undefined cells
+ r_Marray<T> newMDD( mint );
+ T* typedDataPtr = (T*)newMDD.data;
+
+ // iterate through the domain and fill the values where available
+ for( offset=0; offset<mint.cell_count(); offset++ )
+ {
+ pt = mint.cell_point(offset);
+
+ // Test if pt is a valid index in the spatial domain of the
+ // self object.
+ pt_valid = 1;
+ for( int dim=0; dim<domain.dimension() && pt_valid; dim++ )
+ pt_valid &= pt[dim] >= domain[dim].low() && pt[dim] <= domain[dim].high();
+
+ if( pt_valid )
+ typedDataPtr[offset] = operator[](pt);
+
+ // The points where pt_valid is not true are undefined, so nothing has to be
+ // done in the catch clause.
+ // Attention: Purify is reporting that unitialized memory is read when accessing
+ // these points.
+ }
+
+ return newMDD;
+}
+
+
+
+template<class T>
+const T&
+r_Marray<T>::operator[] ( const r_Point& point ) const
+ throw( r_Edim_mismatch, r_Eindex_violation )
+{
+ // first test dimensionality
+ if( point.dimension() != domain.dimension() )
+ throw( r_Edim_mismatch( point.dimension(), domain.dimension() ) );
+
+ T* typedDataPtr = (T*)data;
+
+ try
+ {
+ return typedDataPtr[ domain.cell_offset( point ) ];
+ }
+ catch( ... ) // exception can be r_Eindex_violation
+ {
+ throw; // rethrow it
+ }
+}
+
+
+
+template<class T>
+T&
+r_Marray<T>::operator[] ( const r_Point& point )
+ throw( r_Edim_mismatch, r_Eindex_violation )
+{
+ // first test dimensionality
+ if( point.dimension() != domain.dimension() )
+ throw( r_Edim_mismatch( point.dimension(), domain.dimension() ) );
+
+ T* typedDataPtr = (T*)data;
+
+ try
+ {
+ return typedDataPtr[ domain.cell_offset( point ) ];
+ }
+ catch( ... ) // exception can be r_Eindex_violation
+ {
+ throw; // rethrow it
+ }
+}
+
+
+
+template<class T>
+r_Marray<T>::operator T()
+ throw( r_Eno_cell )
+{
+ // check if the spatial domain of self is really zero
+ if( domain.dimension() > 0 || data == 0 )
+ throw r_Eno_cell();
+
+ return *((T*)data);
+}
+
+
+
+template<class T>
+void
+r_Marray<T>::print_status( std::ostream& s ) const
+{
+ r_GMarray::print_status( s );
+
+ /*
+
+ The following code part prints the content of the array by piping
+ each cell into the specified output stream. This implementation needs
+ the stream operator to be defined for each template type T.
+
+ if( domain.dimension() )
+ {
+ r_Point p(domain.dimension());
+ int done = 0;
+ r_Dimension i = 0;
+
+ // initialize point
+ for(i = 0; i < domain.dimension(); i++)
+ p << domain[i].low();
+
+ s << "Domain: " << domain << endl;
+
+ // iterate over all cells
+ while(!done)
+ {
+ // print cell
+ // if( hex_output )
+ // s << setw(8) << hex << (int)operator[]( p );
+ // else
+ s << setw(8) << operator[]( p );
+
+
+ // increment coordinate
+ i = 0;
+ while( ++p[i] > domain[i].high() )
+ {
+ s << endl;
+ p[i] = domain[i].low();
+ i++;
+ if(i >= domain.dimension())
+ {
+ done = 1;
+ break;
+ }
+ }
+ if(i > 1) s << endl;
+ }
+ }
+ else
+ // print cell
+ // if( hex_output )
+ // s << "Cell value " << setw(8) << hex << (int)*((T*)data) << endl;
+ // else
+ s << "Cell value " << setw(8) << *((T*)data) << endl;
+ */
+}
+
+
+
diff --git a/rasodmg/marray.hh b/rasodmg/marray.hh
new file mode 100644
index 0000000..8b5e5ea
--- /dev/null
+++ b/rasodmg/marray.hh
@@ -0,0 +1,145 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: marray.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Marray
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_MARRAY_
+#define _D_MARRAY_
+
+#include "rasodmg/gmarray.hh"
+
+#include <iostream>
+
+using namespace std;
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The central class of the library for representing an MDD
+ object is named r_Marray. Through overloading operators,
+ the handling of an MDD object is similar to the usage of
+ a normal C or C++ array from the programmers point of view.
+
+*/
+
+template<class T>
+class r_Marray : public r_GMarray
+{
+ public:
+ /// function type for initialization function
+ typedef T (*r_InitFunction)(const r_Point&);
+
+ /// default constructor (no memory is allocated!)
+ r_Marray() throw(r_Error);
+
+ /// constructor for uninitialized MDD objects
+ r_Marray( const r_Minterval&, r_Storage_Layout* stl = 0 ) throw(r_Error);
+ /**
+ If a storage layout pointer is provided, the object refered to is
+ taken and memory control moves to the \Ref{r_Marray} class.
+ The user has to take care, that each creation of \Ref{r_Marray}
+ objects get a new storage layout object.
+ */
+
+ /// constructor for constant MDD objects
+ r_Marray( const r_Minterval&, const T&, r_Storage_Layout* stl = 0 ) throw(r_Error);
+ /**
+ If a storage layout pointer is provided, the object refered to is
+ taken and memory control moves to the \Ref{r_Marray} class.
+ The user has to take care, that each creation of \Ref{r_Marray}
+ objects get a new storage layout object.
+ */
+
+ /// constructor with initializing function
+ r_Marray( const r_Minterval&, r_InitFunction, r_Storage_Layout* stl = 0 ) throw(r_Error);
+ /**
+ If a storage layout pointer is provided, the object refered to is
+ taken and memory control moves to the \Ref{r_Marray} class.
+ The user has to take care, that each creation of \Ref{r_Marray}
+ objects get a new storage layout object.
+ */
+
+ /// copy constructor
+ r_Marray( const r_Marray<T>& ) throw(r_Error);
+
+ /// constructor getting an object of type r_GMarray
+ r_Marray( r_GMarray& ) throw(r_Error);
+ /*
+ This constructor is used for converting general \Ref{r_GMarray} objects
+ to cell type safe \Ref{r_Marray} objects. Care has to be taken because
+ the memory of the \Ref{r_GMarray} can not be used anymore; it is passed
+ to the \Ref{r_Marray<T>} object.
+ */
+
+ /// destructor
+ virtual ~r_Marray();
+
+ /// assignment: cleanup + copy
+ const r_Marray& operator= ( const r_Marray& );
+
+ /// subscript operator for projection in the 1st dimension
+ r_Marray<T> operator[]( long ) const
+ throw(r_Eindex_violation);
+
+ /// subscript operator for restriction/extension combination
+ r_Marray<T> operator[]( const r_Minterval& ) const
+ throw( r_Edim_mismatch );
+
+ /// subscript operator for read access of a cell
+ const T& operator[]( const r_Point& ) const
+ throw(r_Edim_mismatch, r_Eindex_violation);
+
+ /// subscript operator for write access of a cell
+ T& operator[]( const r_Point& )
+ throw(r_Edim_mismatch, r_Eindex_violation);
+
+ /// cast operator for converting to base type for cell access
+ operator T()
+ throw( r_Eno_cell );
+
+ /// writes the state of the object to the specified stream
+ virtual void print_status( std::ostream& s = cout ) const;
+};
+
+#include "rasodmg/marray.icc"
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#ifdef __VISUALC__
+#include "rasodmg/marray.cpp"
+#else
+#include "rasodmg/marray.cc"
+#endif
+#endif
+#endif
+
+#endif
diff --git a/rasodmg/marray.icc b/rasodmg/marray.icc
new file mode 100644
index 0000000..98796a3
--- /dev/null
+++ b/rasodmg/marray.icc
@@ -0,0 +1,31 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: marray.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Marray
+ *
+ * COMMENTS:
+ * None
+*/
diff --git a/rasodmg/object.cc b/rasodmg/object.cc
new file mode 100644
index 0000000..8b047dd
--- /dev/null
+++ b/rasodmg/object.cc
@@ -0,0 +1,603 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: object.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Object
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include "mymalloc/mymalloc.h"
+
+static const char rcsid[] = "@(#)rasodmg, r_Object: $Id: object.cc,v 1.37 2002/08/19 14:09:32 schatz Exp $";
+
+#include "raslib/rmdebug.hh"
+#include "raslib/type.hh"
+#include "raslib/error.hh"
+
+#include "rasodmg/object.hh"
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define OBJECT_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef OBJECT_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+#include <iostream>
+
+
+// At the beginning, next and last object types/status are not specified.
+r_Object::ObjectStatus r_Object::next_object_status = r_Object::no_status;
+r_Object::ObjectType r_Object::next_object_type = r_Object::no_object;
+char* r_Object::next_object_type_name = 0;
+r_OId r_Object::next_object_oid = r_OId();
+r_Object::ObjectType r_Object::last_object_type = r_Object::no_object;
+
+
+
+r_Object::r_Object()
+ : object_status( next_object_status ),
+ object_name(0),
+ type_name(0),
+ type_structure(0),
+ type_schema(0),
+ oid()
+{
+ RMDBCLASS( "r_Object", "r_Object()", "rasodmg", __FILE__, __LINE__ )
+
+ if( next_object_type_name ) type_name = strdup( next_object_type_name );
+
+ if( next_object_type == persistent_object )
+ RMInit::logOut << "Error: A peristent object is constructed with default constructor." << std::endl;
+ else
+ object_type = transient_object;
+
+ internal_obj_type = 0;
+
+ // reset next object type/status
+ r_Object::next_object_type = no_object;
+ r_Object::next_object_status = no_status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+}
+
+
+
+r_Object::r_Object( unsigned short objType ) throw(r_Error)
+ : object_status( next_object_status ),
+ object_name(0),
+ type_name(0),
+ type_structure(0),
+ type_schema(0),
+ oid()
+{
+ RMDBCLASS( "r_Object", "r_Object( unsigned short )", "rasodmg", __FILE__, __LINE__ )
+
+ if( next_object_type_name ) type_name = strdup( next_object_type_name );
+
+ if( next_object_type == persistent_object )
+ {
+ if( r_Transaction::actual_transaction == 0 )
+ {
+ RMInit::logOut << "Error: Tried to create a persistent object outside a transaction." << std::endl;
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ }
+
+ object_type = persistent_object;
+
+ switch( object_status )
+ {
+ case created:
+ // In case the object is newly created, get a new oid and assign it to the object.
+ oid = r_Database::actual_database->get_new_oid( objType );
+ break;
+ case read:
+ case transient:
+ // In case the object is read from db, use the oid stored in next_object_oid.
+ oid = next_object_oid;
+ break;
+ default:
+ RMDBGONCE(0, RMDebug::module_raslib, "r_Object", "r_Object(objType) bad object_status " << object_status);
+ break;
+ }
+
+ // Add the object to the list of persistent objects in the current transaction.
+ if( oid.is_valid() )
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( oid, this ) );
+ else
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( this ) );
+
+ }
+ else
+ object_type = transient_object;
+
+ internal_obj_type = objType;
+
+ // reset next object type/status
+ r_Object::next_object_type = no_object;
+ r_Object::next_object_status = no_status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+}
+
+
+
+/* OBSOLETE
+r_Object::r_Object( unsigned short objType, const char* name ) throw(r_Error)
+ : object_status( next_object_status ),
+ object_name( strdup(name) ),
+ type_name(0),
+ type_structure(0),
+ type_schema(0),
+ oid()
+{
+ RMANDEBUGOUT( "r_Object::r_Object( const char* name)" )
+
+ if( next_object_type_name ) type_name = strdup( next_object_type_name );
+
+ if( next_object_type == persistent_object )
+ {
+ if( r_Transaction::actual_transaction == 0 )
+ {
+ RMInit::logOut << "Error: Tried to create a persistent object outside a transaction." << std::endl;
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ }
+
+ object_type = persistent_object;
+
+ // get a new oid and assign it to the object
+ // oid = r_Database::actual_database->get_new_oid( objType );
+
+ // add the object to the list of persistent objects in the actual transaction
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( this ) );
+ }
+ else
+ object_type = transient_object;
+
+ // reset next object type/status
+ r_Object::next_object_type = no_object;
+ r_Object::next_object_status = no_status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+}
+*/
+
+
+r_Object::r_Object( const r_Object& obj, unsigned short objType ) throw(r_Error)
+ : object_status( next_object_status ),
+ object_name(0),
+ type_name(0),
+ type_structure(0),
+ type_schema(0),
+ oid()
+{
+ RMDBCLASS( "r_Object", "r_Object( const r_Object& )", "rasodmg", __FILE__, __LINE__ )
+
+ if( next_object_type_name ) type_name = strdup( next_object_type_name );
+
+ if( next_object_type == persistent_object )
+ {
+ if( r_Transaction::actual_transaction == 0 )
+ {
+ RMInit::logOut << "Error: Tried to create a persistent object outside a transaction." << std::endl;
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ }
+
+ object_type = persistent_object;
+
+ switch( object_status )
+ {
+ case created:
+ // In case the object is newly created, get a new oid and assign it to the object.
+ oid = r_Database::actual_database->get_new_oid( objType );
+ break;
+ case read:
+ case transient:
+ // In case the object is read from db, use the oid stored in next_object_oid.
+ oid = next_object_oid;
+ break;
+ default:
+ RMDBGONCE(0, RMDebug::module_raslib, "r_Object", "r_Object(obj, objType) bad object_status " << object_status);
+ break;
+ }
+
+ // Add the object to the list of persistent objects in the actual transaction.
+ if( oid.is_valid() )
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( oid, this ) );
+ else
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( this ) );
+ }
+ else
+ object_type = transient_object;
+
+ internal_obj_type = objType;
+
+ // reset next object type/status
+ r_Object::next_object_type = no_object;
+ r_Object::next_object_status = no_status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+
+ if( obj.object_name )
+ object_name = strdup( obj.object_name );
+
+ if( obj.type_name && !type_name )
+ type_name = strdup( obj.type_name );
+
+ if( obj.type_structure )
+ type_structure = strdup( obj.type_structure );
+}
+
+void
+r_Object::set_type_schema(const r_Type* tyy) throw (r_Error)
+ {
+ if (type_schema)
+ {
+ RMInit::logOut << "r_Object::set_type_schema(" << tyy->name() << ") this object has already a type" << std::endl;
+ throw r_Error(ILLEGALARGUMENT);
+ }
+ type_schema = tyy->clone();
+ }
+
+
+/*************************************************************
+ * Method name...: ~r_Object()
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: Destructor.
+ ************************************************************/
+
+r_Object::~r_Object()
+{
+ RMDBCLASS( "r_Object", "~r_Object()", "rasodmg", __FILE__, __LINE__ )
+
+ // Free memory in the transient case. In the persistent case, r_deactivate()
+ // is invoked at the commit/abort point.
+ if( test_type( transient_object ) )
+ r_deactivate();
+
+ object_status = deleted;
+
+ // store the object type for the delete operator
+ r_Object::last_object_type = object_type;
+}
+
+
+
+/*************************************************************
+ * Method name...: r_deactivate()
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: This method is called when the object leaves
+ * the application cache. It frees all dynamic
+ * memory allocated within the class.
+ ************************************************************/
+void
+r_Object::r_deactivate()
+{
+ RMDBCLASS( "r_Object", "r_deactivate()", "rasodmg", __FILE__, __LINE__ )
+
+ if( type_schema )
+ {
+ delete type_schema;
+ type_schema = 0;
+ }
+
+ if( object_name )
+ {
+ free( object_name );
+ object_name = 0;
+ }
+
+ if( type_name )
+ {
+ free( type_name );
+ type_name = 0;
+ }
+
+ if( type_structure )
+ {
+ delete [] type_structure;
+ type_structure = 0;
+ }
+
+ oid.r_deactivate();
+}
+
+
+
+/*************************************************************
+ * Method name...: operator new( size_t size )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: New operator set the next_object_type and
+ * allocates memory for the object.
+ ************************************************************/
+void*
+r_Object::operator new( size_t size )
+{
+ RMDBCLASS( "r_Object", "operator new( size_t )", "rasodmg", __FILE__, __LINE__ )
+
+ r_Object::next_object_type = transient_object;
+ r_Object::next_object_status = created;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+
+ void* a = mymalloc( size );
+ return a;
+}
+
+
+
+/*************************************************************
+ * Method name...: operator new( size_t size,
+ * r_Database *database,
+ * const char* type_name )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: New operator set the next_object_type and
+ * allocates memory for the object.
+ ************************************************************/
+void*
+r_Object::operator new( size_t size, r_Database* /*database*/, const char* type_name )
+{
+ RMDBCLASS( "r_Object", "operator new( size_t, r_Database, const char* )", "rasodmg", __FILE__, __LINE__ )
+
+ r_Object::next_object_type = persistent_object;
+ r_Object::next_object_status = created;
+ r_Object::next_object_type_name = (char*)type_name;
+ r_Object::next_object_oid = r_OId();
+
+ void* a = mymalloc( size );
+ return a;
+}
+
+
+
+void*
+r_Object::operator new( size_t size, const char* type_name )
+{
+ RMDBCLASS( "r_Object", "operator new( size_t, const char* )", "rasodmg", __FILE__, __LINE__ )
+
+ r_Object::next_object_type = transient_object;
+ r_Object::next_object_status = created;
+ r_Object::next_object_type_name = (char*)type_name;
+ r_Object::next_object_oid = r_OId();
+
+ void* a = mymalloc( size );
+ return a;
+}
+
+
+
+/*************************************************************
+ * Method name...: operator delete( void* obj_ptr )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: Delete operator.
+ * Transient objects are deleted immediately from
+ * main memory.
+ * Persistent objects have been marked as deleted in
+ * the destructor. Further accesses through a r_Ref raise
+ * an exception. Main memory is freed after the transaction
+ * commits.
+ ************************************************************/
+void
+r_Object::operator delete( void* obj_ptr )
+{
+ RMDBCLASS( "r_Object", "operator delete()", "rasodmg", __FILE__, __LINE__ )
+
+ if( r_Object::last_object_type == transient_object )
+ free( obj_ptr );
+
+ r_Object::last_object_type = no_object;
+}
+
+
+
+/*************************************************************
+ * Method name...: test_status( ObjectStatus status )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: Tests if status matches the object status. If so
+ * in returns 1, otherwise 0.
+ ************************************************************/
+int
+r_Object::test_status( ObjectStatus status )
+{
+ return ( status == object_status );
+}
+
+
+
+/*************************************************************
+ * Method name...: test_type( ObjectType type )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: Tests if type matches the object type. If so
+ * in returns 1, otherwise 0.
+ ************************************************************/
+int
+r_Object::test_type( ObjectType type )
+{
+ return ( type == object_type );
+}
+
+
+
+/*************************************************************
+ * Method name...: operator new( size_t size,
+ * r_Database *database,
+ * ObjectStatus status )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: New operator set the next_object_type to
+ * persistent object and the next_object_status to the
+ * given status. Memory for the object is allocated.
+ ************************************************************/
+void*
+r_Object::operator new( size_t size, r_Database* /*database*/, ObjectStatus status, const r_OId& oid )
+{
+ RMDBCLASS( "r_Object", "operator new( size_t, r_Database, ObjectStatus )", "rasodmg", __FILE__, __LINE__ )
+
+ r_Object::next_object_type = persistent_object;
+ r_Object::next_object_status = status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = oid;
+
+ void* a = mymalloc( size );
+ return a;
+}
+
+
+
+const r_Type*
+r_Object::get_type_schema()
+{
+ if( !type_schema )
+ {
+ // If type structure not known then try to get it from the server
+ if ( (type_structure == NULL) || (strlen(type_structure) == 0) )
+ {
+ ClientComm::r_Type_Type typeType = (ClientComm::r_Type_Type)0;
+
+ // we need an open database and an active transaction
+ if ( r_Database::actual_database == NULL ) return NULL;
+ else
+ {
+ if ( r_Database::actual_database->get_status() == r_Database::not_open )
+ return NULL;
+ }
+ if ( r_Transaction::actual_transaction == NULL) return NULL;
+ else
+ {
+ if ( r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ return NULL;
+ }
+
+ // set the object type and contact the database if the type name is defined.
+ if ( internal_obj_type == 1 ) typeType = ClientComm::r_MDDType_Type;
+ else if ( internal_obj_type == 2 ) typeType = ClientComm::r_SetType_Type;
+ if ( (type_name == NULL) || (strlen(type_name) == 0) || (typeType == 0) )
+ return NULL;
+
+ try {
+ type_structure = r_Database::actual_database->getComm()->getTypeStructure( type_name, typeType );
+ }
+ catch(r_Error& errObj) {
+ RMInit::logOut << "r_Object::get_type_schema() failed retriving typestructure" << std::endl;
+ RMInit::logOut << "Error " << errObj.get_errorno() << " : " << errObj.what() << std::endl;
+ return NULL;
+ }
+ }
+
+ type_schema = r_Type::get_any_type( type_structure );
+ }
+ return type_schema;
+}
+
+
+
+void
+r_Object::update_obj_in_db()
+{
+ RMInit::logOut << " dummy implementation " << std::flush;
+}
+
+
+
+void
+r_Object::load_obj_from_db()
+{
+ RMInit::logOut << " dummy implementation " << std::flush;
+}
+
+
+
+void
+r_Object::delete_obj_from_db()
+{
+ RMDBCLASS( "r_Object", "delete_obj_from_db()", "rasodmg", __FILE__, __LINE__ )
+
+ if( object_name && strlen( object_name ) )
+ {
+ RMInit::logOut << object_name << "... " << std::flush;
+
+ // delete myself from the database
+ r_Database::actual_database->getComm()->deleteCollByName( object_name );
+ }
+ else
+ {
+ RMInit::logOut << "no name - take oid ... " << std::flush;
+
+ if( oid.get_local_oid() )
+ // delete myself from the database
+ r_Database::actual_database->getComm()->deleteObjByOId( oid );
+ else
+ RMInit::logOut << " no oid ... FAILED" << std::flush;
+ }
+}
+
+
+void
+r_Object::initialize_oid( const r_OId& initOId )
+{
+ oid = initOId;
+}
+
diff --git a/rasodmg/object.hh b/rasodmg/object.hh
new file mode 100644
index 0000000..d5fcbeb
--- /dev/null
+++ b/rasodmg/object.hh
@@ -0,0 +1,240 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: object.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Object
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_OBJECT_
+#define _D_OBJECT_
+
+#include "raslib/error.hh"
+#include "raslib/oid.hh"
+#include "raslib/rminit.hh"
+
+#include <stdlib.h>
+
+// forward declarations
+class r_Database;
+class r_Type;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ Through inheritance of this class, the type definer specifies that
+ the subclass is capable of having persistent as well as transient
+ instances.
+
+ {\bf Attention: }Right now, just the classes \Ref{r_Set} and \Ref{r_Marray}
+ inherit from \Ref{r_Object} which, therefore, are the only persistent
+ capable classes. In fact, just objects of type {\tt r_Set<r_Ref<r_Marray<...>>>}
+ can be made persitent right now.
+
+*/
+
+class r_Object
+{
+ public:
+ /// default constructor
+ r_Object();
+
+ /// constructor getting objType
+ r_Object( unsigned short objType ) throw(r_Error);
+ /**
+ {\tt objType} specifies the type of the object (1=Marray, 2=Collection).
+ This is needed for oid allocation and propably dropped in future.
+ */
+
+ /// copy constructor
+ r_Object( const r_Object&, unsigned short objType=0 ) throw(r_Error);
+ /**
+ {\tt objType} specifies the type of the object (1=Marray, 2=Collection).
+ This is needed for oid allocation and propably dropped in future.
+ */
+
+ /// virtual destructor
+ virtual ~r_Object();
+
+ /// mark the object as modified
+ inline void mark_modified();
+
+ /// new operator for transient objects
+ void* operator new( size_t size );
+
+ /// new operator for persistent objects
+ void* operator new( size_t size, r_Database *database, const char* type_name = 0 );
+
+ /// new operator for transient objects carrying type information
+ void* operator new( size_t size, const char* type_name );
+
+ /// delete operator
+ void operator delete( void* obj_ptr );
+
+ /// set object type by name
+ inline void set_type_by_name( const char* name ) throw(r_Error);
+ /**
+ With this method a type name has to be given by the user for each
+ object which he wants to make persistent. The type name is the name
+ introduced in the RasDL file. If an object without a valid type
+ name is made persistent, an error occurs while committing the
+ transaction.
+
+ NOTE: This method is updated. Use {\tt void* operator new( size_t size,
+ r_Database *database, const char* type_name )} instead.
+ */
+
+ /// set object type by name
+ inline void set_type_structure( const char* name ) throw(r_Error);
+
+ /// get object type name
+ inline const char* get_type_name() const;
+
+ /// get object type structure
+ inline const char* get_type_structure() const;
+
+ /// get oid
+ inline const r_OId& get_oid() const;
+
+ /// get type schema
+ const r_Type* get_type_schema();
+
+ void set_type_schema(const r_Type* type) throw (r_Error);
+
+ //@Man: Methods and types for internal use only:
+ //@{
+ ///
+
+ /// object life status
+ enum ObjectStatus { no_status, deleted, created, modified, read, transient };
+ /**
+ created - The object was created in the current transaction and has to be stored in the database.
+ deleted - The object was deleted. It is still in main memory and in the database. It is going to
+ be removed at the end of the transaction.
+ modified - Object was modified and has to be updated in the database.
+ read - The object was read from the database without modifying it afterwards.
+ transient - The object belongs to a declarative query result. In most cases, it has no persistent
+ counterpart in the db. It is NOT considered in the update phase.
+ */
+
+ /// object types
+ enum ObjectType { no_object, persistent_object, transient_object };
+
+ ///
+ /// inserts an object into the database
+ virtual void insert_obj_into_db()=0;
+ /// inserts an object into a specific collection in the database
+ virtual void insert_obj_into_db( const char* )=0;
+ /// updates an object in database
+ virtual void update_obj_in_db();
+ /// load an object from the database
+ virtual void load_obj_from_db();
+ /// deletes an object from the database
+ void delete_obj_from_db();
+
+ ///
+ /// initialize oid of the object
+ void initialize_oid( const r_OId& initOId );
+
+ ///
+ /// it is called when an object comes into transient memory
+ virtual void r_activate() {;};
+ /// it is called when an object leaves transient memory
+ virtual void r_deactivate();
+
+ ///
+ /// test object status returns 1 if it matches
+ int test_status( ObjectStatus status );
+ /// gets the status of the object
+ inline ObjectStatus get_status() const;
+
+ ///
+ /// set object name. object name should contain only [a-zA-Z0-9_]
+ inline void set_object_name( const char* name ) throw(r_Error);
+ /// get object name
+ inline const char* get_object_name() const;
+
+ ///
+ /// new operator for activating an object (status = read)
+ void* operator new( size_t size, r_Database *database, ObjectStatus status, const r_OId& oid );
+
+ ///
+ //@}
+
+ protected:
+ /// test object type returns 1 if it matches
+ int test_type( ObjectType type );
+
+ /// stores object name if it has one
+ char* object_name;
+
+ /// stores object type name if it has one
+ char* type_name;
+
+ /// store type structure as string if it has one
+ char* type_structure;
+
+ /// pointer to type schema (built on request)
+ r_Type* type_schema;
+
+ /// internal object type (1 marray, 2 collection)
+ unsigned short internal_obj_type;
+
+ private:
+ /// right now, the object life status is either deleted, created, or read
+ ObjectStatus object_status;
+
+ /// persistent_object or transient_object
+ ObjectType object_type;
+
+ /// object identifier
+ r_OId oid;
+
+ /// holds the next object type between new operation and constructor
+ static ObjectType next_object_type;
+
+ /// holds the next object status between new operation and constructor
+ static ObjectStatus next_object_status;
+
+ /// holds the next object type name between new operation and constructor
+ static char* next_object_type_name;
+
+ /// holds the next object oid between new operation and constructor
+ static r_OId next_object_oid;
+
+ /// holds the last object type between destructor and delete operator
+ static ObjectType last_object_type;
+};
+
+#include "rasodmg/object.icc"
+
+#endif
+
+
+
+
diff --git a/rasodmg/object.icc b/rasodmg/object.icc
new file mode 100644
index 0000000..b210d95
--- /dev/null
+++ b/rasodmg/object.icc
@@ -0,0 +1,151 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: object.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Object
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <string.h>
+
+
+inline void
+r_Object::mark_modified()
+{
+ if( object_status == no_status ||
+ object_status == read )
+ object_status = modified;
+};
+
+
+
+inline void
+r_Object::set_object_name( const char* name ) throw(r_Error)
+{
+ if(!name) {
+ //null pointer
+ RMInit::logOut << "r_Object::set_object_name(name) name is null!" << std::endl;
+ throw r_Error(INVALIDOBJECTNAME);
+ }
+
+ const char* cptr=name;
+
+ //check if the name contains only [a-zA-Z0-9_]
+ while(*cptr) {
+ if( ((*cptr >= 'a') && (*cptr <='z')) ||
+ ((*cptr >= 'A') && (*cptr <='Z')) ||
+ ((*cptr >= '0') && (*cptr <='9')) ||
+ (*cptr == '_') )
+ cptr++;
+ else
+ break;
+ }
+
+ if(*cptr) {
+ //invalid character in object name
+ RMInit::logOut << "r_Object::set_object_name(" << name << ") invalid name!" << std::endl;
+ throw r_Error(INVALIDOBJECTNAME);
+ }
+
+ if( object_name )
+ free( object_name );
+
+ object_name = strdup( name );
+};
+
+
+inline void
+r_Object::set_type_by_name( const char* name ) throw(r_Error)
+{
+ if(!name) {
+ //null pointer
+ RMInit::logOut << "r_Object::set_type_by_name(name) name is null!" << std::endl;
+ throw r_Error(r_Error:: r_Error_NameInvalid);
+ }
+
+ if( type_name )
+ free( type_name );
+
+ type_name = strdup( name );
+};
+
+
+inline void
+r_Object::set_type_structure( const char* name ) throw(r_Error)
+{
+ if(!name) {
+ //null pointer
+ RMInit::logOut << "r_Object::type_structure(name) name is null!" << std::endl;
+ throw r_Error(r_Error:: r_Error_NameInvalid);
+ }
+
+ if( type_structure )
+ delete [] type_structure;
+
+ type_structure = new char[strlen(name) + 1];
+ strcpy(type_structure, name);
+};
+
+
+inline const char*
+r_Object::get_type_name() const
+{
+ return type_name;
+};
+
+
+inline const char*
+r_Object::get_object_name() const
+{
+ return object_name;
+}
+
+
+inline const char*
+r_Object::get_type_structure() const
+{
+ if (type_structure != NULL)
+ return type_structure;
+ else
+ return "";
+};
+
+
+inline r_Object::ObjectStatus
+r_Object::get_status() const
+{
+ return object_status;
+};
+
+
+inline const r_OId&
+r_Object::get_oid() const
+{
+ return oid;
+}
+
+
diff --git a/rasodmg/oqlquery.cc b/rasodmg/oqlquery.cc
new file mode 100644
index 0000000..4b1a3f1
--- /dev/null
+++ b/rasodmg/oqlquery.cc
@@ -0,0 +1,628 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: oqlquery.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_OQL_Query
+ * FUNCTION: r_oql_execute()
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg, r_OQL_Query and r_oql_execute(): $Id: oqlquery.cc,v 1.25 2002/08/28 12:21:57 coman Exp $";
+
+#include "rasodmg/oqlquery.hh"
+
+#include <string.h>
+#include <ctype.h> // isdigit()
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream>
+#endif
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define OQLQUERY_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/database.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/gmarray.hh"
+
+#include "raslib/rmdebug.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef OQLQUERY_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+r_OQL_Query::r_OQL_Query()
+ : queryString(0),
+ parameterizedQueryString(0),
+ mddConstants(0)
+{
+}
+
+
+r_OQL_Query::r_OQL_Query( const char* s )
+ : queryString(0),
+ mddConstants(0)
+{
+ parameterizedQueryString = new char[strlen(s)+1];
+ strcpy( parameterizedQueryString, s );
+
+ reset_query();
+}
+
+
+r_OQL_Query::r_OQL_Query( const r_OQL_Query& q )
+ : queryString(0),
+ parameterizedQueryString(0),
+ mddConstants(0)
+{
+ // copy the query string
+ if(q.queryString) {
+ queryString = new char[strlen(q.queryString)+1];
+ strcpy( queryString, q.queryString);
+ }
+
+ // copy the parameterized query string
+ if(q.parameterizedQueryString) {
+ parameterizedQueryString = new char[strlen(q.parameterizedQueryString)+1];
+ strcpy( parameterizedQueryString, q.parameterizedQueryString );
+ }
+
+ if( q.mddConstants ) {
+ mddConstants = new r_Set< r_GMarray* >( *(q.mddConstants) );
+ }
+}
+
+
+r_OQL_Query::~r_OQL_Query()
+{
+ if( queryString )
+ delete[] queryString;
+ queryString = 0;
+
+ if( parameterizedQueryString )
+ delete[] parameterizedQueryString;
+ parameterizedQueryString = 0;
+
+ if( mddConstants )
+ delete mddConstants;
+ mddConstants = 0;
+}
+
+
+const r_OQL_Query&
+r_OQL_Query::operator=( const r_OQL_Query& q )
+{
+ if( this != &q )
+ {
+ // clean up and copy the query string
+
+ if( queryString )
+ {
+ delete[] queryString;
+ queryString = 0;
+ }
+
+ if( q.queryString )
+ {
+ queryString = new char[strlen(q.queryString)+1];
+ strcpy( queryString, q.queryString );
+ }
+
+ if( mddConstants )
+ {
+ delete mddConstants;
+ mddConstants = 0;
+ }
+
+ if( q.mddConstants )
+ {
+ mddConstants = new r_Set< r_GMarray* >( *(q.mddConstants) );
+ }
+
+ // clean up and copy the parameterized query string
+ if( parameterizedQueryString )
+ {
+ delete[] parameterizedQueryString;
+ parameterizedQueryString = 0;
+ }
+
+ if( q.parameterizedQueryString )
+ {
+ parameterizedQueryString = new char[strlen(q.parameterizedQueryString)+1];
+ strcpy( parameterizedQueryString, q.parameterizedQueryString );
+ }
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( const char* s ) throw( r_Error )
+{
+ try
+ {
+ replaceNextArgument( s );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Char c ) throw( r_Error )
+{
+ char valueString[2];
+
+ valueString[0] = c;
+ valueString[1] = '\0';
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Short s ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << s << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_UShort us ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << us << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Long l ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << l << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_ULong ul ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << ul << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Point pt ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << pt << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Sinterval in ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << in << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Minterval in ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << in << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_GMarray& in ) throw( r_Error )
+{
+ // determine number of next mdd (starting with 0)
+ unsigned long mddNo = 0;
+ if( mddConstants )
+ mddNo = mddConstants->cardinality();
+
+ char valueString[256];
+ std::ostrstream valueStream( valueString, 256 );
+ valueStream << "#MDD" << mddNo << "#" << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ // save reference to in
+ if( !mddConstants )
+ mddConstants = new r_Set< r_GMarray* >();
+
+ mddConstants->insert_element( &in );
+
+ return *this;
+}
+
+
+
+
+int
+r_OQL_Query::is_update_query() const
+{
+ return !is_retrieval_query();
+}
+
+
+
+int
+r_OQL_Query::is_retrieval_query() const
+{
+ int returnValue = 0;
+
+ if( parameterizedQueryString )
+ returnValue = strstr( parameterizedQueryString, "select" ) ||
+ strstr( parameterizedQueryString, "SELECT" );
+
+ return returnValue;
+}
+
+
+
+void
+r_OQL_Query::reset_query()
+{
+ if( queryString )
+ delete[] queryString;
+
+ queryString = new char[strlen(parameterizedQueryString)+1];
+ strcpy( queryString, parameterizedQueryString );
+
+ if( mddConstants )
+ {
+ delete mddConstants;
+ mddConstants = 0;
+ }
+}
+
+
+void
+r_OQL_Query::replaceNextArgument( const char* valueString )
+ throw( r_Error )
+{
+ char* argumentBegin=NULL;
+ char* argumentEnd=NULL;
+ char* argumentVal=NULL;
+ int argumentLength=0;
+ char* tmpString=NULL;
+ int length=0;
+
+ // locate the next argument in the query string
+
+ argumentBegin = argumentEnd = strchr( queryString, '$' );
+
+ if( !argumentBegin )
+ {
+ r_Error err = r_Error( r_Error::r_Error_QueryParameterCountInvalid );
+ throw err;
+ }
+
+ // while( *argumentEnd != ' ' && *argumentEnd != '\0' )
+ argumentEnd++;
+
+ //is digit or invalid argument format
+ if(!isdigit(*argumentEnd))
+ throw r_Error( QUERYPARAMETERINVALID );
+
+ while( isdigit(*argumentEnd) && *argumentEnd != ' ' && *argumentEnd != '\0' )
+ argumentEnd++;
+
+ argumentLength = argumentEnd - argumentBegin;
+ argumentVal = new char[ argumentLength + 1];
+ strncpy(argumentVal, argumentBegin, argumentLength);
+ argumentVal[argumentLength] = '\0';
+
+ while(true)
+ {
+ // allocate a new query string and fill it
+ tmpString = queryString;
+ length = strlen(queryString) - argumentLength + strlen(valueString);
+ queryString = new char[ length + 1 ];
+
+ *argumentBegin = '\0';
+ std::ostrstream queryStream( queryString, length + 1 );
+
+ queryStream << tmpString << valueString << argumentEnd << std::ends;
+
+ //update the reference
+ argumentEnd=queryString+strlen(tmpString)+strlen(valueString);
+
+ //remove buffer
+ delete[] tmpString;
+
+ //search again for this parameter
+ argumentEnd = argumentBegin = strstr( argumentEnd, argumentVal );
+
+ //end string?
+ if(argumentBegin == NULL)
+ break;
+
+ //skip $
+ argumentEnd++;
+
+ //is digit or invalid argument format
+ if(!isdigit(*argumentEnd))
+ {
+ delete [] argumentVal;
+ throw r_Error( QUERYPARAMETERINVALID );
+ }
+
+ //skip digits
+ while( isdigit(*argumentEnd) && *argumentEnd != ' ' && *argumentEnd != '\0' )
+ argumentEnd++;
+ }
+
+ delete[] argumentVal;
+}
+
+
+
+// HP COMPILER BUG
+// The iterator type needs a typedef because otherwise the compiler creates a duplicate
+// definition for each instance of the following template function.
+typedef r_Iterator<r_GMarray*> r_Iterator_r_GMarray;
+
+void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref_Any > &result )
+ throw( r_Error )
+{
+ if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( r_Transaction::actual_transaction == 0 || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ r_Database::actual_database->getComm()->executeQuery( query, result );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ // reset the arguments of the query object
+ query.reset_query();
+}
+
+
+
+void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref< r_GMarray > > &result )
+ throw( r_Error )
+{
+ if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( r_Transaction::actual_transaction == 0 || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ r_Set< r_Ref_Any > genericSet;
+
+
+ r_Database::actual_database->getComm()->executeQuery( query, genericSet );
+
+ const r_Type* typeSchema = genericSet.get_element_type_schema();
+
+ if( !typeSchema || typeSchema->type_id() != r_Type::MARRAYTYPE )
+ {
+ r_Error err( r_Error::r_Error_TypeInvalid );
+ throw err;
+ }
+
+ //
+ // iterate through the generic set and build a specific one
+ //
+ result.set_type_by_name( genericSet.get_type_name() );
+ result.set_type_structure( genericSet.get_type_structure() );
+
+ r_Iterator< r_Ref_Any > iter;
+ for( iter=genericSet.create_iterator(); iter.not_done(); iter++ )
+ result.insert_element( r_Ref<r_GMarray>(*iter) );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ // reset the arguments of the query object
+ query.reset_query();
+}
+
+
+
+void r_oql_execute( r_OQL_Query& query )
+ throw( r_Error )
+{
+ if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( r_Transaction::actual_transaction == 0 || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ r_Database::actual_database->getComm()->executeQuery( query );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ // reset the arguments of the query object
+ query.reset_query();
+}
+
diff --git a/rasodmg/oqlquery.hh b/rasodmg/oqlquery.hh
new file mode 100644
index 0000000..8da0935
--- /dev/null
+++ b/rasodmg/oqlquery.hh
@@ -0,0 +1,251 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: oqlquery.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_OQL_Query
+ * FUNCTION: r_oql_execute()
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_OQL_QUERY_
+#define _D_OQL_QUERY_
+
+#include "raslib/error.hh"
+
+#include "raslib/odmgtypes.hh"
+#include "rasodmg/marray.hh"
+#include "raslib/point.hh"
+#include "raslib/sinterval.hh"
+#include "raslib/minterval.hh"
+
+template <class T> class r_Set;
+template <class T> class r_Ref;
+class r_Ref_Any;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The global function \Ref{r_oql_execute} is used to invoke RasML
+ queries. The query statement is represented through an object
+ of class \Ref{r_OQL_Query} which is the first argument of the function.
+ The constructor gets a parameterized query string where #$i#
+ indicates the i-th parameter. The overloaded stream input
+ operators allows to insert the parameter values to the query, at
+ the same time preserving their respective types. If any of the
+ #$i# are not followed by a right operant construction argument at
+ the point \Ref{r_oql_execute} is called, a \Ref{r_Error} exception object
+ of kind {\tt r_Error_QueryParameterCountInvalid} is thrown.
+ Once a query has been executed via \Ref{r_oql_execute}, the arguments
+ associated with the #$i# parameters are cleared and new arguments
+ must be supplied.
+
+ The copy constructor and assignment operator copy all the underlying
+ data structures associated with the query, based upon the parameters
+ that have been passed to the query at the point the operation is
+ performed.
+
+ The stream operators raise a \Ref{r_Error} exception of type
+ {\tt r_Error_QueryParameterCountInvalid} if the number of arguments is
+ exceeded.
+
+*/
+
+class r_OQL_Query
+{
+ public:
+ /// default constructor
+ r_OQL_Query();
+
+ /// constructor getting the query string
+ r_OQL_Query( const char* s );
+
+ /// copy constructor
+ r_OQL_Query( const r_OQL_Query& q );
+
+ /// destructor
+ ~r_OQL_Query();
+
+ /// assignment operator
+ const r_OQL_Query& operator=( const r_OQL_Query& q );
+
+ //@Man: Stream input operators for every parameter type:
+ //@{
+ ///
+ r_OQL_Query& operator<<( const char* s ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Char c ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Short s ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_UShort us ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Long l ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_ULong ul ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Point pt ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Sinterval in ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Minterval in ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_GMarray& in ) throw( r_Error );
+ ///
+ //@}
+
+ /// returns true if the current query is an update one
+ int is_update_query() const;
+
+ /// returns true if the current query is an update one
+ int is_retrieval_query() const;
+
+ //@Man: Methods for internal use:
+ //@{
+ /// resets the expandation of the query string
+ void reset_query();
+ /// gets the expanded query string
+ inline const char* get_query() const;
+ /// get mdd constants
+ inline const r_Set< r_GMarray* >* get_constants() const;
+ /// gets the parameterized query string
+ inline const char* get_parameterized_query() const;
+ ///
+ //@}
+
+ private:
+ /// method replaces the next argument with the delivered valueString
+ void replaceNextArgument( const char* valueString ) throw( r_Error );
+
+ /// storage for the expanded query string
+ char* queryString;
+
+ /// storage for the parameterized query string
+ char* parameterizedQueryString;
+
+ /// list for MDD constants
+ r_Set< r_GMarray* >* mddConstants;
+};
+
+
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ The free standing function \Ref{r_oql_execute} is called to execute a retrieval query.
+ The first parameter, {\tt query}, is a reference to a \Ref{r_OQL_Query} object specifying
+ the query to execute. The second parameter, {\tt result}, is used for returning the
+ result of the query. The query result is of type {\tt r_Set< r_Ref_Any >}.
+
+ If the function is not called within the scope of an opened database, a \Ref{r_Error}
+ exception of kind {\tt r_Error_DatabaseClosed} is raised. If it is called outside any
+ transaction, the exception is of kind {\tt r_Error_TransactionNotOpen}.
+
+ A complete list of all possible error kinds is given by the following table.
+
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && No database is not opened.\\
+ r_Error_TransactionNotOpen && Call is not within an active transaction.\\
+ r_Error_QueryParameterCountInvalid && At least one of the query parameters is not supplied with a value.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_QueryExecutionFailed && The execution of the query failed (further information is available
+ in an error object of type {\tt r_Equery_execution}).\\
+ r_Error_TypeInvalid && Result base type doesn't match the template type. \\
+ \end{tabular}
+*/
+
+void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref_Any > &result )
+throw( r_Error );
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ The funcetion is used to execute retrieval queries with the result set being
+ of type {\tt r_Set< r_Ref< r_GMarray > >}. The function is supported for
+ compatibility reasons only. We suggest to use the general function
+ \Ref{r_oql_execute} able to maintain query results of any type.
+*/
+void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref< r_GMarray > > &result )
+throw( r_Error );
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ The free standing function \Ref{r_oql_execute} is called to execute an update query.
+ The first parameter, {\tt query}, is a reference to a \Ref{r_OQL_Query} object specifying
+ the query to execute.
+
+ If the function is not called within the scope of an opened database, a \Ref{r_Error}
+ exception of kind {\tt r_Error_DatabaseClosed} is raised. If it is called outside any
+ transaction, the exception is of kind {\tt r_Error_TransactionNotOpen}.
+
+ A complete list of all possible error kinds is given by the following table.
+
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && No database is not opened.\\
+ r_Error_TransactionNotOpen && Call is not within an active transaction.\\
+ r_Error_QueryParameterCountInvalid && At least one of the query parameters is not supplied with a value.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_QueryExecutionFailed && The execution of the query failed (further information is available
+ in an error object of type {\tt r_Equery_execution}).\\
+ \end{tabular}
+*/
+
+void r_oql_execute( r_OQL_Query& query )
+throw( r_Error );
+
+#include "rasodmg/oqlquery.icc"
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rasodmg/oqlquery.icc b/rasodmg/oqlquery.icc
new file mode 100644
index 0000000..6d6b225
--- /dev/null
+++ b/rasodmg/oqlquery.icc
@@ -0,0 +1,52 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: oqlquery.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_OQL_Query
+ *
+ * COMMENTS:
+ *
+*/
+
+
+inline const char*
+r_OQL_Query::get_query() const
+{
+ return (const char*)queryString;
+};
+
+
+inline const r_Set< r_GMarray* >*
+r_OQL_Query::get_constants() const
+{
+ return mddConstants;
+};
+
+
+inline const char*
+r_OQL_Query::get_parameterized_query() const
+{
+ return (const char*)parameterizedQueryString;
+};
diff --git a/rasodmg/partinsert.cc b/rasodmg/partinsert.cc
new file mode 100644
index 0000000..566f287
--- /dev/null
+++ b/rasodmg/partinsert.cc
@@ -0,0 +1,199 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: partinsert.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Partial_Insert
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <vector>
+
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/minterval.hh"
+#include "raslib/error.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/gmarray.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/oqlquery.hh"
+#include "rasodmg/partinsert.hh"
+
+
+
+// format string for creating collections; parameters: collection name, set type
+const char *r_Partial_Insert::format_create = "CREATE COLLECTION %s %s";
+// format string for updating the MDD; parameters: collection name, local oid
+const char *r_Partial_Insert::format_update = "UPDATE %s AS x SET x ASSIGN $1 WHERE OID(x) = %f";
+
+
+r_Partial_Insert::r_Partial_Insert( r_Database &usedb, const char *collname, const char *mddtype, const char *settype, const r_Storage_Layout &stl ) : mydb(usedb)
+{
+ init_share(collname, mddtype, settype);
+ mystl = stl.clone();
+}
+
+
+r_Partial_Insert::r_Partial_Insert( r_Database &usedb, const char *collname, const char *mddtype, const char *settype, const r_Minterval &dom, unsigned int tsize ) : mydb(usedb)
+{
+ init_share(collname, mddtype, settype);
+ r_Aligned_Tiling *tilingObj = new r_Aligned_Tiling(dom, tsize * dom.cell_count());
+ mystl = new r_Storage_Layout(tilingObj);
+}
+
+
+r_Partial_Insert::r_Partial_Insert( const r_Partial_Insert &src ) : mydb(src.mydb)
+{
+ init_share(src.collName, src.mddType, src.setType);
+ mystl = src.mystl->clone();
+}
+
+
+r_Partial_Insert::~r_Partial_Insert( void )
+{
+ if (collName != NULL)
+ delete [] collName;
+ if (mddType != NULL)
+ delete [] mddType;
+ if (setType != NULL)
+ delete [] setType;
+ if (mystl != NULL)
+ delete mystl;
+}
+
+
+void r_Partial_Insert::init_share( const char *collname, const char *mddtype, const char *settype )
+{
+ collName = new char[strlen(collname)+1];
+ strcpy(collName, collname);
+ mddType = new char[strlen(mddtype)+1];
+ strcpy(mddType, mddtype);
+ setType = new char[strlen(settype)+1];
+ strcpy(setType, settype);
+ doUpdate = 0;
+}
+
+int r_Partial_Insert::update( r_GMarray *mddPtr,
+ r_Data_Format transferFormat,
+ const char* transferFormatParams,
+ r_Data_Format storageFormat,
+ const char* storageFormatParams
+ )
+{
+ RMDBGENTER(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update()");
+ try {
+ mddPtr->set_storage_layout(mystl->clone());
+ mddPtr->set_type_by_name(mddType);
+ }
+ catch (r_Error &err) {
+ RMInit::logOut << "r_Partial_Insert::update(): unable to set storage_layout for the currend MDD: "
+ << err.what() << endl;
+ return -1;
+ }
+
+ if (doUpdate == 0)
+ {
+ char *queryBuffer = new char[strlen(format_create) + strlen(collName) + strlen(setType)];
+ sprintf(queryBuffer, format_create, collName, setType);
+ // first try creating the collection
+ try
+ {
+ // this is basically 3 bytes to long, but that doesn't matter
+ myta.begin();
+ mydb.set_transfer_format(transferFormat, transferFormatParams);
+ mydb.set_storage_format(storageFormat, storageFormatParams);
+ r_OQL_Query query(queryBuffer);
+ r_oql_execute(query);
+ myta.commit();
+ RMDBGMIDDLE(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): created new collection " << collName << " with type " << setType );
+ }
+ catch (r_Error &err)
+ {
+ RMDBGMIDDLE(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): can't create collection: " << err.what() );
+ myta.abort();
+ // failure to create the collection is not an error
+ }
+ delete [] queryBuffer;
+
+ // now create the root object
+ try
+ {
+ myta.begin();
+ mydb.set_transfer_format(transferFormat, transferFormatParams);
+ mydb.set_storage_format(storageFormat, storageFormatParams);
+ r_Ref<r_GMarray> mddp = new (&mydb, mddType) r_GMarray(*mddPtr);
+ r_Ref<r_Set<r_Ref<r_GMarray> > > mddCollPtr;
+ mddCollPtr = (r_Ref<r_Set<r_Ref<r_GMarray> > >)(mydb.lookup_object(collName));
+ mddCollPtr->insert_element(mddp);
+ myOId = mddp->get_oid();
+ myta.commit();
+ RMDBGMIDDLE(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): reated root object OK, oid = " << myOId );
+ doUpdate = 1;
+ }
+ catch (r_Error &err)
+ {
+ RMInit::logOut << "r_Partial_Insert::update(): unable to create root object: "
+ << err.what() << endl;
+ myta.abort();
+ return -1;
+ }
+ }
+ else
+ {
+ char *queryBuffer = new char[strlen(format_update) + strlen(collName) + 32];
+ sprintf(queryBuffer, format_update, collName, myOId.get_local_oid());
+
+ // try the update
+ try
+ {
+ myta.begin();
+ mydb.set_transfer_format(transferFormat, transferFormatParams);
+ mydb.set_storage_format(storageFormat, storageFormatParams);
+ RMDBGMIDDLE(1, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): QUERY: " << queryBuffer );
+ r_OQL_Query query(queryBuffer);
+ query << (*mddPtr);
+ r_oql_execute(query);
+ myta.commit();
+ RMDBGMIDDLE(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): update object OK" );
+ }
+ catch (r_Error &err)
+ {
+ RMInit::logOut << "r_Partial_Insert::update(): failed to update marray: "
+ << err.what() << endl;
+ myta.abort();
+ delete [] queryBuffer;
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Partial_Insert", "failed");
+ return -1;
+ }
+ delete [] queryBuffer;
+ }
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): exiting OK" );
+
+ return 0;
+}
diff --git a/rasodmg/partinsert.hh b/rasodmg/partinsert.hh
new file mode 100644
index 0000000..013124c
--- /dev/null
+++ b/rasodmg/partinsert.hh
@@ -0,0 +1,109 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: partinsert.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Partial_Insert
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_PARTIAL_INSERT_
+#define _R_PARTIAL_INSERT_
+
+
+#include "raslib/mddtypes.hh"
+#include "raslib/oid.hh"
+#include "rasodmg/transaction.hh"
+
+
+class r_Minterval;
+class r_Storage_Layout;
+class r_GMarray;
+class r_Database;
+
+
+//@ManMemo: {\bf rasodmg}
+
+/*@Doc:
+ Class for inserting an MDD into the database stripwise, as in most of
+ our insert tools.
+*/
+
+class r_Partial_Insert
+{
+ public:
+ /// constructor receiving all necessary parameters. The storage layout is copied
+ r_Partial_Insert( r_Database &usedb, const char *collname, const char *mddtype,
+ const char *settype, const r_Storage_Layout &stl );
+ /// alternative constructor for regular tiling
+ r_Partial_Insert( r_Database &usedb, const char *collname, const char *mddtype,
+ const char *settype, const r_Minterval &dom, unsigned int tsize );
+ /// copy constructor
+ r_Partial_Insert( const r_Partial_Insert &src );
+ /// destructor
+ ~r_Partial_Insert( void );
+
+ /// update the marray; no transaction should be activated, this is done internally.
+ int update( r_GMarray *mddPtr,
+ r_Data_Format transferFormat = r_Array,
+ const char* transferFormatParams = NULL,
+ r_Data_Format storageFormat = r_Array,
+ const char* storageFormatParams = NULL
+ );
+ /*
+ The marray may be modified in small aspects such as base type name and storage layout.
+ The "transferFormat, transferFormatParams" are used to set the transfer compression used
+ for the communications of client with the server.
+ The "storageFormat, storageFormatParams" are used to set the storage format used for
+ MDD created by the client in the RasDaMan database.
+ */
+
+ protected:
+ /// shared init code
+ void init_share( const char *collname, const char *mddtype, const char *settype );
+
+ /// the marray's OId
+ r_OId myOId;
+ /// the collection name
+ char *collName;
+ /// the MDD type name
+ char *mddType;
+ /// the set type name
+ char *setType;
+ /// the database
+ r_Database &mydb;
+ /// the storage layout
+ r_Storage_Layout *mystl;
+ /// the transaction object
+ r_Transaction myta;
+ /// do we have to do an insert or an update?
+ int doUpdate;
+ /// format strings for queries
+ static const char *format_create;
+ static const char *format_update;
+};
+
+#endif
diff --git a/rasodmg/polycutout.cc b/rasodmg/polycutout.cc
new file mode 100644
index 0000000..78f3d75
--- /dev/null
+++ b/rasodmg/polycutout.cc
@@ -0,0 +1,709 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: polycutout.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_PolygonCutOut
+ *
+ * COMMENTS:
+ *
+ * This class is intended to perform the polygon cut out operation
+ * Except for the r_PolygonCutOut class, everything else is just
+ * for internal use
+ * Attention: this version works good (I hope :-) but has just a tiny geometrical problem:
+ * as usual in discrete space, lines are build up by little horiontal segments.
+ * Edges are considered to be inside, except the first little segment of a line.
+ * This is only for avoiding a bigger problem, I will develop a better algorythm
+*/
+
+/*
+This module is intended to perform polygon cut out operation. It supports the exact ESRI specifications
+regarding "clean" polygons, this means: not self intersecting, closed, if you walk from an point to the
+next of edge the inside is on the right. It also supports multiple rings, but the outer one has to have
+the "inside" inside.
+Don't forget that the rasdaman coordinates are with x left->right and y top->down, or at least
+I have considered them so because of the usual coordinates of tiffs
+*/
+
+static const char rcsid[] = "@(#)rasodmg, r_PolygonCutOut: $Id: polycutout.cc,v 1.11 2002/10/09 09:58:05 hoefner Exp $";
+
+#include "rasodmg/polycutout.hh"
+#include "rasodmg/marray.hh"
+#include "raslib/miter.hh"
+
+#include <math.h>
+
+r_SegmentIterator::r_SegmentIterator(r_Point &s,r_Point &e)
+ {
+ start = s;
+ end = e;
+ reset();
+ }
+
+void r_SegmentIterator::reset()
+ {
+ dx = end[0] - start[0];
+ dy = end[1] - start[1];
+
+ if( dx >= 0)
+ { if( dy >= 0 )
+ { if( dx >= dy ) { cadran = 0;}
+ else { cadran = 1; swap(dx,dy);}
+ }
+ else
+ { dy = -dy;
+ if( dx >= dy ) { cadran = 7;}
+ else { cadran = 6; swap(dx,dy);}
+ }
+ }
+ else
+ { dx = -dx;
+ if( dy >= 0 )
+ { if( dx >= dy ) { cadran = 3;}
+ else { cadran = 2; swap(dx,dy);}
+ }
+ else
+ { dy = -dy;
+ if( dx >= dy ) { cadran = 4;}
+ else { cadran = 5; swap(dx,dy);}
+ }
+ }
+ cx = 0;
+ cy = 0;
+ beta = 0;
+// std::cout<<"reset: ["<<start<<','<<end<<"] cadran="<<cadran<<" dx="<<dx<<" dy="<<dy<<std::endl;
+ }
+
+r_Point r_SegmentIterator::next()
+ {
+ r_Point resultat = createCurrentPoint();
+ //prepare next
+ cx++;
+ beta += dy;
+ if( (beta<<1) > dx ) { beta -= dx; cy++;}
+ return resultat;
+ }
+
+bool r_SegmentIterator::hasMore()
+ {
+// std::cout<<"hasMore: cx="<<cx<<" lim="<<dx+1<<std::endl;
+ return (cx <= dx ) ? true : false;
+ }
+
+int r_SegmentIterator::cosFunc() // limited use,1000 * cos(alfa)
+ { // use local variables
+ double ldx = end[0] - start[0];
+ double ldy = end[1] - start[1];
+
+ double num = ldx*ldx + ldy*ldy;
+ if(num == 0) return 0;
+
+ return (1000 * ldx)/sqrt(num);
+ }
+
+void r_SegmentIterator::swap(r_Range &x, r_Range &y)
+ {
+ r_Range temp = x;
+ x=y;
+ y=temp;
+ }
+
+r_Point r_SegmentIterator::createCurrentPoint()
+ {
+// std::cout<<" cCP: "<<cx<<':'<<cy<<std::endl;
+ r_Range rcx = cx;
+ r_Range rcy = cy;
+ switch(cadran)
+ { case 0: break;
+ case 1: swap(rcx,rcy); break;
+ case 2: swap(rcx,rcy); rcx=-rcx; break;
+ case 3: rcx=-rcx; break;
+ case 4: rcx=-rcx; rcy=-rcy; break;
+ case 5: swap(rcx,rcy); rcx=-rcx; rcy=-rcy; break;
+ case 6: swap(rcx,rcy); rcy=-rcy; break;
+ case 7: rcy=-rcy; break;
+ }
+ //std::cout<<"cCP: cx="<<cx<<" cy="<<cy<<" rx="<<rcx<<" ry="<<rcy<<" cadran="<<cadran<<std::endl;
+ return r_Point(start[0] + rcx, start[1] + rcy);
+ }
+
+
+
+r_Line::r_Line()
+ {
+ a = b = c = 0;
+ }
+
+r_Line::r_Line(double nA,double nB,double nC)
+ {
+ a = nA; b = nB; c = nC;
+ }
+
+r_Line::r_Line(r_Point &s,r_Point &e)
+ {
+ a = e[1] - s[1];
+ b = s[0] - e[0];
+ c = (double)e[0]*(double)s[1] - (double)s[0]*(double)e[1];
+ }
+
+double r_Line::getA() { return a; }
+double r_Line::getB() { return b; }
+double r_Line::getC() { return c; }
+
+float r_Line::ecuatia(r_Point &p)
+ {
+ return a * p[0] + b * p[1] + c;
+ }
+
+ostream& operator<<(ostream& os,r_Line &l)
+ {
+ return os<<"{L"<<l.a<<','<<l.b<<','<<l.c<<'}';
+ }
+
+
+
+
+r_PolygonCutOut::r_PolygonCutOut()
+ {
+ table = 0;
+ usedCount = 0;
+ mArray = 0;
+
+ imgWidth = 0;
+ imgHeight = 0;
+ imgX = 0;
+ imgY = 0;
+ tableWidth = 0;
+ tableHeight = 0;
+ }
+r_PolygonCutOut::~r_PolygonCutOut()
+ {
+ clearTables();
+ }
+
+void r_PolygonCutOut::setMArray(r_GMarray& myArray)
+ {
+ mArray = &myArray;
+
+ r_Minterval currDomain;
+ currDomain = mArray->spatial_domain();
+
+ imgX = currDomain[0].low();
+ imgY = currDomain[1].low();
+
+ imgWidth = currDomain[0].get_extent();
+ imgHeight = currDomain[1].get_extent();
+ }
+
+void r_PolygonCutOut::addPolygon(const r_Polygon &p)
+ {
+ polygons.push_back(p);
+ }
+
+bool r_PolygonCutOut::compute()
+ {
+//std::cout<<"PCO: compute in"<<std::endl;
+ if(!imgWidth || !imgHeight || polygons.size()==0) return false;
+
+//std::cout<<"PCO: initTable - in"<<std::endl;
+ initTable();
+//std::cout<<"PCO: initTable - out"<<std::endl;
+
+ list<r_Polygon>::iterator polyIter = polygons.begin();
+
+ for(int i = 0; i < polygons.size(); i++, polyIter++)
+ {
+ r_Polygon &currPolygon = *polyIter;
+
+ const std::vector<r_Edge>& edges = currPolygon.getEdges();
+ std::vector<r_Edge>::const_iterator edgeIterator = edges.begin();
+
+ for(int j = 0; j < edges.size(); j++,edgeIterator++)
+ {
+ r_Point start = edgeIterator->getStart();
+ r_Point end = edgeIterator->getEnd();
+
+ if(start == end) continue; //avoid such edges, causes problems
+
+ int inside = -computeInside(start,end); // minus because rasdaman coord are flipped
+ // we have to see if this is correct like this or not
+
+ //std::cout<<"compute edge "<<j<<" ["<<start<<"-"<<end<<"] inside="<<inside<<std::endl;
+ if(inside == 0 ) computeOneHorSegment(start,end);
+ else computeOneSegment(start,end,inside);
+ }
+ }
+ for(int line=0;line<tableHeight;line++)
+ { ordonateLine(line);
+ minimizeLine(line);
+ }
+//print();
+// std::cout<<"PCO: compute out"<<std::endl;
+ return true;
+ }
+
+bool r_PolygonCutOut::initTable()
+ {
+ clearTables();
+ tableWidth = computeTableWidth();
+ tableHeight= imgHeight;
+
+//std::cout<<"PCO: initTable: "<<tableWidth<<','<<tableHeight<<std::endl;
+ table = new TablePoint[tableWidth*tableHeight];
+ usedCount = new int[tableHeight];
+
+ // if(table==NULL || usedCount==NULL) std::cout<<"sunt nule"<<std::endl;
+
+ for(int i=0;i<tableWidth*tableHeight;i++)
+ {
+ table[i].x =-1;
+ table[i].inside= 0;
+ table[i].cosFunc= 0;
+ }
+
+ for(int j=0;j<tableHeight;j++)
+ usedCount[j]=0;
+
+ return true;
+ }
+
+void r_PolygonCutOut::clearTables()
+ {
+ if(table) delete[] table;
+ table = NULL;
+ if(usedCount) delete[] usedCount;
+ usedCount =NULL;
+ }
+int r_PolygonCutOut::computeTableWidth()
+ {
+ // once it was: tableWidth = poly->getCountNodes() + poly->countHorizontalEdges() + 2;
+
+ list<r_Polygon>::iterator iter=polygons.begin();
+
+ int nodes = 0;
+ int horizEdges = 0;
+
+ for(int i=0;i<polygons.size();i++, iter++)
+ {
+ r_Polygon &polygon = *iter;
+
+ nodes += polygon.countEdges();
+ horizEdges += polygon.countHorizontalEdges();
+ }
+ return nodes + horizEdges; // niet + 2;
+ }
+
+void r_PolygonCutOut::ordonateLine(int line)
+ {
+ int count=usedCount[line];
+ TablePoint *tLine = &getTP(line,0);
+ bool change=false;
+ do{
+ change=false;
+ for(int i=0;i<count-1;i++)
+ { bool swap=false;
+
+ if(tLine[i].x > tLine[i+1].x) swap=true;
+ if(tLine[i].x == tLine[i+1].x &&
+ tLine[i].inside != tLine[i+1].inside &&
+ tLine[i].cosFunc > tLine[i+1].cosFunc)
+ swap=true;
+ if(swap)
+ { TablePoint temp = tLine[i];
+ tLine[i] = tLine[i+1];
+ tLine[i+1] = temp;
+ change = true;
+ }
+ }
+ }while(change);
+
+ for(int j=0;j<count-1;j++)
+ { if(tLine[j] == tLine[j+1])
+ tLine[j].inside=0;
+ }
+
+ }
+
+void r_PolygonCutOut::minimizeLine(int line)
+ {
+ int count=usedCount[line];
+ if(count <= 2) return; //nothing to do
+
+ int inside = 0;
+ TablePoint *tLine = &getTP(line,0);
+
+ int level=0;
+ for(int i=0;i<count-1;i++)
+ {
+ if(level==0) { inside=tLine[i].inside;
+ level++;
+ continue;
+ }
+
+ if(tLine[i].inside==inside) level++;
+ else level--;
+
+ if(level!=0) tLine[i].inside=0; // means disabled
+ }
+
+ int s,d;
+ for(s=0,d=0;s<count;s++)
+ {
+ if(tLine[s].inside==0) continue;
+ if(s!=d) tLine[d]=tLine[s];
+ d++;
+ }
+ usedCount[line]=d;
+ }
+
+void r_PolygonCutOut::computeOneSegment(r_Point start, r_Point end, int inside)
+ {
+ int lastLine = -1;
+ int lastX = -1;
+ r_SegmentIterator segiter(start,end);
+
+ int cosFunc=segiter.cosFunc();
+ int cosNow = cosFunc; // first point: cosFunc, lastPoint -cosFunc, rest 0
+
+ bool firstLine = true;
+ bool lastPoint = false;
+ // this firstLine-lastPoint are here only top be sure that the first and the last point are in the table
+ // and not replaced by neighbours
+ while(segiter.hasMore())
+ { r_Point cp = segiter.next();
+ if(segiter.hasMore()==false) // last point
+ {
+ cosNow=-cosFunc;
+ lastPoint = true;
+ }
+
+ r_Range coordX = cp[0];
+ r_Range coordY = cp[1];
+
+ int tableLine = coordY - imgY;
+
+ if(tableLine>=0 && tableLine < tableHeight)
+ {
+ if(tableLine != lastLine)
+ { addPoint(tableLine,coordX,inside,cosNow);
+
+ if(lastLine != -1) firstLine = false;
+ }
+ else if(firstLine == false)
+ {
+ if(inside > 0 && coordX < lastX) replacePoint(tableLine,coordX,inside,cosNow);
+ else if(inside < 0 && coordX > lastX) replacePoint(tableLine,coordX,inside,cosNow);
+ else if(lastPoint) replacePoint(tableLine,coordX,inside,cosNow);
+ }
+ }
+
+ cosNow = 0;
+ lastLine = tableLine;
+ lastX = coordX;
+ }
+ }
+
+void r_PolygonCutOut::computeOneHorSegment(r_Point start, r_Point end)
+ {
+ r_SegmentIterator segiter(start,end);
+ int cosFunc=segiter.cosFunc();
+
+ r_Range startX = start[0];
+ r_Range endX = end[0];
+ r_Range commonY = start[1];
+
+ int tableLine = commonY - imgY;
+
+ if(tableLine>=0 && tableLine < tableHeight)
+ {
+ if(startX <= endX)
+ { addPoint(tableLine,startX, 1, cosFunc);
+ addPoint(tableLine,endX, -1,-cosFunc);
+ }
+ else { // in this case cosFunc < 0
+ addPoint(tableLine,endX, 1,-cosFunc);
+ addPoint(tableLine,startX,-1, cosFunc);
+ }
+ }
+ }
+
+int r_PolygonCutOut::computeInside(r_Point start, r_Point end)
+ {
+ r_Line line(start,end);
+ r_Point control(start[0]+1,start[1]);
+ float f = line.ecuatia(control);
+ if(f==0) return 0;
+ if(f<0 ) return -1;
+ return 1;
+ }
+
+
+r_PolygonCutOut::TablePoint& r_PolygonCutOut::getTP(int line, int column)
+ {
+ TablePoint *tp = table + (line * tableWidth + column);
+ return *tp;
+ }
+
+void r_PolygonCutOut::print(int onlyLine)
+ {
+ std::cout<<"r_PolygonCutOut::print: "<<tableWidth<<':'<<tableHeight<<std::endl;
+
+ if(onlyLine==-1) // print all
+ {
+ for(int i=0;i<tableHeight;i++)
+ printLine(i);
+ }
+ else
+ {
+ if(0<=onlyLine && onlyLine <tableHeight) printLine(onlyLine);
+ else std::cout<<"Line "<<onlyLine<<" doesn't exist"<<std::endl;
+ }
+ }
+
+void r_PolygonCutOut::printLine(r_Range line)
+ {
+ int count=usedCount[line];
+ TablePoint *tp = &getTP(line,0);
+
+ std::cout<<"line "<<line<<'('<<count<<") ";
+ for(int i=0;i<count;i++)
+ { char inside='0';
+ if(tp[i].inside==-1) inside='-';
+ if(tp[i].inside==1 ) inside='+';
+
+ std::cout<<'['<<tp[i].x<<','<<inside<<','<<tp[i].cosFunc<<']';
+ }
+ std::cout<<std::endl;
+ }
+
+void r_PolygonCutOut::addPoint(int tableLine,r_Range coordX, int inside,int cosFunc)
+ {
+ int which = usedCount[tableLine];
+ TablePoint *tp = &getTP(tableLine,which);
+
+ tp->x = coordX;
+ tp->inside = inside;
+ tp->cosFunc = cosFunc;
+ usedCount[tableLine]++;
+ }
+
+void r_PolygonCutOut::replacePoint(int tableLine,r_Range coordX,int inside, int cosFunc)
+ {
+ int which = usedCount[tableLine]-1;
+ TablePoint *tp = &getTP(tableLine,which);
+ tp->x = coordX;
+ tp->inside = inside;
+ tp->cosFunc = cosFunc;
+ }
+
+bool r_PolygonCutOut::TablePoint::operator==(r_PolygonCutOut::TablePoint &tp)
+ { return (x==tp.x && inside==tp.inside) ? true: false;
+ }
+
+
+// debug only int lastline = -1;
+void
+r_PolygonCutOut::eraseLine( r_Range x1, r_Range x2, r_Range y, const string& bgr ) throw(r_Error)
+{
+ // can heapen if we are outside the domain of the array
+ if(x2 < x1) return;
+
+ //if(lastline != y && x1 != 0)
+ // std::cout<<"Erasing line: y="<<y<<" ["<<x1<<","<<x2<<"]"<<std::endl;
+ //lastline = y;
+
+ r_Minterval eraseDom(2);
+ eraseDom << r_Sinterval(x1, x2) << r_Sinterval(y, y);
+ r_Minterval arrayDom = mArray->spatial_domain();
+ r_Bytes typeSize = mArray->get_type_length();
+ r_Bytes bgrSize = bgr.size();
+ const char *bgrContent=bgr.c_str();
+ char *currCell=NULL;
+
+
+ // Grrr. In RasDaMan the y are stored close together. So the whole fillPolygon
+ // should have been organised by x instead of y. Well, for now I just use an
+ // r_Miter here.
+
+ r_Miter eraseIter( &eraseDom, &arrayDom, typeSize, mArray->get_array() );
+ while( !eraseIter.isDone() ) {
+ currCell = eraseIter.nextCell();
+ // FIXME This potentially wont work for all types. I just set every byte to 0.
+ if(bgr.empty())
+ memset(currCell, 0, typeSize);
+ else
+ {
+ if( typeSize != bgrSize)
+ throw r_Error( r_Error::r_Error_TypeInvalid );
+ memmove(currCell, bgrContent, bgrSize);
+ }
+ }
+}
+
+
+bool
+r_PolygonCutOut::fillMArrayOutside(const string& bgr ) throw(r_Error)
+{
+ if( compute() == false ) return false;
+
+ r_Minterval currDomain = mArray->spatial_domain();
+
+ r_Range imgMinX = imgX;
+ r_Range imgMaxX = currDomain[0].high();
+
+ for(int lineY = 0; lineY < tableHeight ; lineY++)
+ {
+ r_Range coordY = imgY + lineY;
+
+ int countUsed = usedCount[lineY];
+
+ if(countUsed==0)
+ { // polygon didn't touch this line, so all line is outside
+ eraseLine(imgMinX, imgMaxX, coordY, bgr);
+ continue;
+ }
+
+ TablePoint *tp = &getTP(lineY, 0);
+
+ r_Range xLeft = imgMinX-1;
+ r_Range xRight = imgMaxX+1;
+ bool erase = false;
+
+ if( tp[countUsed-1].x < imgMinX)
+ { // the whole polygon is on the left of this line so we have to erase the whole line
+ eraseLine( imgMinX, imgMaxX, coordY, bgr);
+ continue;
+ }
+
+ if( tp[0].x > imgMaxX)
+ { // the whole polygon is on the right of this line so we have to erase the whole line
+ eraseLine( imgMinX, imgMaxX, coordY, bgr);
+ continue;
+ }
+
+ for(int i=0;i<countUsed; i++, tp++)
+ {
+ if(tp->x < imgMinX) continue;
+
+ if(tp->inside == -1)
+ { // inside is <-, so outside is ->
+ xLeft = tp->x;
+ if(xLeft > imgMaxX) break;
+
+ if(i == countUsed-1)
+ { xRight = imgMaxX+1; erase = true;
+ }
+ }
+
+ if(tp->inside == 1)
+ { // inside is ->, so outside is <-
+ xRight = tp->x > imgMaxX ? imgMaxX+1 : tp->x;
+ erase = true;
+ }
+
+ if(erase)
+ { eraseLine( xLeft+1, xRight-1, coordY, bgr);
+ erase = false;
+ }
+ }
+
+ }
+ clearTables();
+ return true;
+ }
+
+/*
+ Attention, this two functions look very similar, but with have significant differences
+ One of them is the absence of some -1 or +1 in the next function. This is important
+ because we consider the edges to be "inside", and the edges are in the table, so
+ erasing the inside is erase [start,end] and erasing the outside is erase [start+1,end-1]
+*/
+
+bool
+r_PolygonCutOut::fillMArrayInside(const string& bgr ) throw(r_Error)
+{
+ if( compute() == false ) return false;
+
+ r_Minterval currDomain = mArray->spatial_domain();
+
+ r_Range imgMinX = imgX;
+ r_Range imgMaxX = currDomain[0].high();
+
+ for(int lineY = 0; lineY < tableHeight ; lineY++)
+ {
+ r_Range coordY = imgY + lineY;
+
+ int countUsed = usedCount[lineY];
+
+ if(countUsed==0)
+ { // polygon didn't touch this line, so all line is outside
+ continue;
+ }
+
+ TablePoint *tp = &getTP(lineY, 0);
+
+ r_Range xLeft = imgMinX;
+ r_Range xRight = imgMaxX;
+ bool erase = false;
+
+ if( tp[countUsed-1].x < imgMinX)
+ { // the whole polygon is on the left of this line so we have to erase the whole line
+ continue;
+ }
+
+ if( tp[0].x > imgMaxX)
+ { // the whole polygon is on the right of this line so we have to erase the whole line
+ continue;
+ }
+
+ for(int i=0;i<countUsed; i++, tp++)
+ {
+ if(tp->x < imgMinX) continue;
+
+ if(tp->inside == 1)
+ { // inside is ->, so outside is <-
+ xLeft = tp->x;
+ if(xLeft > imgMaxX) break;
+
+ if(i == countUsed-1)
+ { xRight = imgMaxX; erase = true;
+ }
+ }
+
+ if(tp->inside == -1)
+ { // inside is <-, so outside is ->
+ xRight = tp->x > imgMaxX ? imgMaxX : tp->x;
+ erase = true;
+ }
+
+ if(erase)
+ { eraseLine( xLeft, xRight, coordY, bgr);
+ erase = false;
+ }
+ }
+
+ }
+ clearTables();
+ return true;
+ }
diff --git a/rasodmg/polycutout.hh b/rasodmg/polycutout.hh
new file mode 100644
index 0000000..fc2e258
--- /dev/null
+++ b/rasodmg/polycutout.hh
@@ -0,0 +1,162 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: polycutout.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_PolygonCutOut
+ *
+ * COMMENTS:
+ *
+ * This class is intended to perform the polygon cut out operation
+ * Except for the r_PolygonCutOut class, everything else is just
+ * for internal use
+ * Attention: this version works good (I hope :-) but has just a tiny geometrical problem:
+ * as usual in discrete space, lines are build up by little horiontal segments.
+ * Edges are considered to be inside, except the first little segment of a line.
+ * This is only for avoiding a bigger problem, I will develop a better algorythm
+*/
+
+/*
+ This module is intended to perform polygon cut out operation. It supports the exact ESRI specifications
+ regarding "clean" polygons, this means: not self intersecting, closed, if you walk from an point to the
+ next of edge the inside is on the right. It also supports multiple rings, but the outer one has to have
+ the "inside" inside.
+ Don't forget that the rasdaman coordinates are with x left->right and y top->down, or at least
+ I have considered them so because of the usual coordinates of tiffs
+*/
+
+#ifndef _R_POLYGON_CUT_OUT_HH
+#define _R_POLYGON_CUT_OUT_HH
+
+#include <iosfwd>
+#include <vector>
+#include <list>
+#include <string>
+using std::string;
+using std::list;
+using std::vector;
+using std::ostream;
+
+#include "raslib/point.hh"
+#include "raslib/minterval.hh"
+#include "rasodmg/polygon.hh"
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+
+class r_SegmentIterator
+ {
+ public:
+ r_SegmentIterator(r_Point&,r_Point&);
+ void reset();
+ r_Point next();
+ bool hasMore();
+ int cosFunc(); // limited use,1000 * cos(alfa)
+ private:
+ void swap(r_Range&, r_Range&);
+ r_Point createCurrentPoint();
+
+ r_Point start;
+ r_Point end;
+ int cadran;
+
+ r_Range dx,dy;
+ r_Range cx,cy;
+ int beta;
+ };
+
+class r_Line
+ {
+ public:
+ r_Line();
+ r_Line(double,double,double);
+ r_Line(r_Point&,r_Point&);
+ double getA();
+ double getB();
+ double getC();
+ float ecuatia(r_Point&);
+ private:
+ double a,b,c;
+ friend ostream& operator<<(ostream&,r_Line&);
+ };
+
+
+class r_PolygonCutOut
+ {
+ public:
+ r_PolygonCutOut();
+ ~r_PolygonCutOut();
+ void setImageSize(r_Range width, r_Range height);
+
+ void setMArray(r_GMarray& myArray);
+ void addPolygon(const r_Polygon&);
+
+ bool fillMArrayInside(const string& bgr = "") throw(r_Error);
+ bool fillMArrayOutside(const string& bgr = "") throw(r_Error);
+
+ // just for debugging
+ void print(int onlyLine=-1);
+ void printLine(r_Range line);
+
+ private:
+ bool compute();
+ void eraseLine( r_Range, r_Range, r_Range y, const string& bgr ) throw(r_Error);
+
+ r_Range imgWidth,imgHeight;
+ r_Range imgX,imgY; // - the origin of the mdd domain
+
+ r_GMarray *mArray;
+
+ std::list<r_Polygon> polygons;
+
+ struct TablePoint
+ { r_Range x;
+ int inside; // where the inside is, -1 left, +1 right, 0 hor. line
+ int cosFunc;
+ bool operator==(TablePoint&);
+ };
+
+ r_Range tableWidth;
+ r_Range tableHeight;
+ TablePoint *table;
+ int *usedCount;
+ TablePoint& getTP(r_Range line, r_Range column);
+
+ bool initTable();
+ void clearTables();
+ int computeTableWidth();
+
+
+ int computeInside(r_Point start, r_Point end);
+ void computeOneSegment(r_Point start, r_Point end, int inside);
+ void computeOneHorSegment(r_Point start, r_Point end);
+ void ordonateLine(int line);
+ void minimizeLine(int line);
+ void replacePoint(r_Range line,r_Range col,int inside, int cosFunc);
+ void addPoint(r_Range line,r_Range col,int inside, int cosFunc);
+
+ };
+
+#endif
diff --git a/rasodmg/polygon.cc b/rasodmg/polygon.cc
new file mode 100644
index 0000000..755593f
--- /dev/null
+++ b/rasodmg/polygon.cc
@@ -0,0 +1,879 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: polygon.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Polygon
+ *
+ * PURPOSE:
+ * This class maintains 2-D polygon sequences.
+ * It knows about them being closed or not.
+ * Input syntax (see constructor) is:
+ * polygon ::= point+
+ * point ::= '[' int ',' int ']'
+ * int ::= ASCII-integer
+ *
+ * COMMENTS:
+ * - see comment in shrinkPoly() about a potential error source
+ * - r_Error::r_Error_General should be replaced with more specific exception
+ *
+*/
+
+#include "rasodmg/polygon.hh"
+
+#include <set>
+#include <algorithm>
+#include <math.h>
+
+#if defined(SOLARIS)
+#include <strings.h>
+#endif
+
+using std::sort;
+//causes problems compiling on old red hat
+//using std::iterator;
+
+#include "raslib/miter.hh"
+#include "rasodmg/marray.hh"
+
+#include "debug/debug.hh"
+
+static const char rcsid[] = "@(#)rasodmg, r_Polygon: $Header: /home/rasdev/CVS-repository/rasdaman/rasodmg/polygon.cc,v 1.28 2003/12/27 23:02:56 rasdev Exp $";
+
+#ifndef LONG_MAX
+const int LONG_MAX = (1<<31) - 1;
+#endif
+#ifndef LONG_MIN
+const int LONG_MIN = (1<<31); // due to overflow
+#endif
+
+// ------------------------------------------------------------------
+// r_Edge
+// ------------------------------------------------------------------
+
+r_Edge::r_Edge(const r_Point& newStart, const r_Point& newEnd) :
+ start(newStart), end(newEnd)
+{
+}
+
+const r_Point&
+r_Edge::getStart() const
+{
+ return start;
+}
+
+const r_Point&
+r_Edge::getEnd() const
+{
+ return end;
+}
+
+double
+r_Edge::getInvSlope() const
+{
+ return (((double)end[0] - start[0]) / (end[1] - start[1]));
+}
+
+double
+r_Edge::getSlope() const
+{
+ return (((double)end[1] - start[1]) / (end[0] - start[0]));
+}
+
+double
+r_Edge::getCurrX(r_Range y) const
+{
+ double currX=0.0;
+ if(end[1]==start[1])
+ currX=end[0];
+ else
+ currX=getInvSlope()*(y - start[1]) + start[0];
+ return currX;
+}
+
+double
+r_Edge::getCurrY(r_Range x) const
+{
+ double currY=0.0;
+ if(end[0]==start[0])
+ currY=end[1];
+ else
+ currY=getSlope()*(x - start[0]) + start[1];
+ return currY;
+}
+
+void
+r_Edge::print_status( std::ostream& s ) const
+{
+ start.print_status(s);
+ s << "->";
+ end.print_status(s);
+}
+
+
+bool
+r_Edge::isHorizontal() const
+{
+ return start[1] == end[1] ? true:false;
+}
+
+// ------------------------------------------------------------------
+// r_Polygon
+// ------------------------------------------------------------------
+
+const r_Dimension r_Polygon::polyPointDim=2;
+
+r_Polygon::r_Polygon(const char* init) throw (r_Error)
+ : closed(false),
+ firstPointSet(false)
+{
+ ENTER( "r_Polygon::r_Polygon, init=" << init );
+
+ if (init == NULL)
+ {
+ TALK( "r_Polygon::r_Polygon(" << (init?init: "NULL") << ")" );
+ RMInit::logOut << "r_Polygon::r_Polygon(" << (init?init: "NULL") << ")" << std::endl;
+ throw r_Error(POLYGONWRONGINITSTRING);
+ }
+ const int POINTBUFFERLEN=512;
+ const char* endPos = NULL;
+ size_t pointLen = 0;
+ char pointBuffer[POINTBUFFERLEN];
+ const char* startPos = index(init, '[');
+ if (startPos == NULL)
+ {
+ TALK( "r_Polygon::r_Polygon(" << init << ") the init string has to start with a '['" );
+ RMInit::logOut << "r_Polygon::r_Polygon(" << init << ") the init string has to start with a '['" << std::endl;
+ throw r_Error(POLYGONWRONGINITSTRING);
+ }
+
+ // while (true)
+ do
+ {
+ endPos = index(startPos, ']');
+ if (endPos == NULL)
+ {
+ TALK( "r_Polygon::r_Polygon(" << init << ") the init string has to contain valid r_Point definitions" );
+ RMInit::logOut << "r_Polygon::r_Polygon(" << init << ") the init string has to contain valid r_Point definitions" << std::endl;
+ throw r_Error(POLYGONWRONGINITSTRING);
+ }
+ pointLen = endPos - startPos;
+ if (pointLen >= POINTBUFFERLEN)
+ {
+ TALK( "r_Polygon::r_Polygon(" << init << ") the definition of one r_Point is too long, only 2 dimensions are allowed" );
+ RMInit::logOut << "r_Polygon::r_Polygon(" << init << ") the definition of one r_Point is too long, only 2 dimensions are allowed" << std::endl;
+ throw r_Error(POLYGONWRONGINITSTRING);
+ }
+ memset(pointBuffer, 0, POINTBUFFERLEN);
+ strncpy(pointBuffer, startPos, pointLen + 1);
+ addPoint(r_Point(pointBuffer));
+ startPos = index(endPos, '[');
+ // was an endless loop with break, changed it to a 'nice' loop -- PB 2003-sep-12
+ // if (startPos == NULL)
+ // break;
+ } while( startPos != NULL);
+
+ LEAVE( "r_Polygon::r_Polygon" );
+}
+
+r_Polygon::r_Polygon(r_Range x, r_Range y) : closed(false), firstPointSet(true)
+{
+ firstPoint = r_Point(x, y);
+ currPoint = firstPoint;
+}
+
+r_Polygon::r_Polygon() : closed(false), firstPointSet(false)
+{
+}
+
+r_Polygon::r_Polygon(const r_Polygon& old)
+{
+ closed=old.closed;
+ firstPointSet=old.firstPointSet;
+ firstPoint=old.firstPoint;
+ currPoint=old.currPoint;
+
+ edges=old.edges;
+}
+
+r_Polygon&
+r_Polygon::operator=(const r_Polygon& old)
+{
+ if(this!=&old)
+ {
+ closed=old.closed;
+ firstPointSet=old.firstPointSet;
+ firstPoint=old.firstPoint;
+ currPoint=old.currPoint;
+
+ edges=old.edges;
+ }
+ return *this;
+}
+
+void
+r_Polygon::addPoint(const r_Point& newPoint) throw(r_Error)
+{
+ if (newPoint.dimension() != polyPointDim)
+ {
+ RMInit::logOut << "r_Polygon::addPoint(" << newPoint << ") only " << polyPointDim << " dimensional r_Points allowed" << std::endl;
+ throw r_Error(POLYGONWRONGPOINTDIMENSION);
+ }
+
+ if(closed)
+ {
+ RMInit::logOut << "r_Polygon::addPoint(" << newPoint << ") polygon closed" << std::endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ if(firstPointSet)
+ {
+ // add an edge from currentPoint to newPoint
+ edges.push_back(r_Edge(currPoint, newPoint));
+ currPoint = newPoint;
+
+ //check if we have the first point
+ checkFistPoint();
+ }
+ else
+ {
+ firstPoint = newPoint;
+ currPoint = newPoint;
+ firstPointSet = true;
+ }
+}
+
+void
+r_Polygon::addPointXY(r_Range x, r_Range y) throw(r_Error)
+{
+ r_Point newPoint(x, y);
+ addPoint(newPoint);
+}
+
+void
+r_Polygon::close()
+{
+ if (closed)
+ return;
+
+ // add the final edge from currentPoint to firstPoint
+ edges.push_back(r_Edge(currPoint, firstPoint));
+ closed = true;
+}
+
+const std::vector<r_Edge>&
+r_Polygon::getEdges() const throw(r_Error)
+{
+ // if the polygon is not closed we raise an exception.
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ RMInit::logOut << "r_Polygon::getEdges() polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ return edges;
+}
+
+std::vector<r_Point>
+r_Polygon::getPoints() const throw(r_Error)
+{
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ RMInit::logOut << "r_Polygon::getPoints() polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ std::vector<r_Point> retVal;
+ std::vector<r_Edge>::const_iterator iter, iterEnd;
+ for(iter = edges.begin(), iterEnd=edges.end(); iter != iterEnd; ++iter)
+ {
+ retVal.push_back((*iter).getStart());
+ }
+ return retVal;
+}
+
+r_Polygon::r_Polygon_Type
+r_Polygon::detectPolygonType() const throw(r_Error)
+{
+ const unsigned int minNoEdges=3;
+ std::vector<r_Point> points=getPoints();
+ unsigned int i=0,j=0, k=0, n=0;
+ unsigned int flag = 0;
+ double z;
+
+ n=points.size();
+
+ //check if is at least a triangle
+ if (n < minNoEdges)
+ return r_Polygon::UNKNOWN;
+
+ //check if is a polygon in 2D
+ for (i=0; i<n; i++)
+ if (points[i].dimension()!=polyPointDim)
+ return r_Polygon::UNKNOWN;
+
+ //check sign of vertice
+ for (i=0; i<n; i++)
+ {
+ j = (i + 1) % n;
+ k = (i + 2) % n;
+ z = (points[j][1] - points[i][1]) * (points[k][0] - points[j][0]);
+ z -= (points[j][0] - points[i][0]) * (points[k][1] - points[j][1]);
+ if (z < 0)
+ flag |= 1;
+ else if (z > 0)
+ flag |= 2;
+ if (flag == 3)
+ return r_Polygon::CONCAVE;
+ }
+
+ if (flag != 0)
+ return r_Polygon::CONVEX;
+ else
+ return r_Polygon::UNKNOWN;
+}
+
+void
+r_Polygon::checkFistPoint()
+ {
+ if (firstPoint == currPoint)
+ closed = true;
+ else
+ closed = false;
+ }
+
+void
+r_Polygon::print_status( std::ostream& s ) const
+{
+
+ std::vector<r_Edge>::const_iterator iter = edges.begin();
+ std::vector<r_Edge>::const_iterator iterEnd = edges.end();
+ s << "{";
+ while (iter!=iterEnd)
+ {
+ iter->print_status(s);
+ s << ", ";
+ ++iter;
+ }
+ s << "} ";
+ if (closed)
+ s << "closed";
+ else //does not matter, because open will crash ...
+ s << "opened";
+
+}
+
+std::ostream& operator<<( std::ostream& s, const r_Polygon& d )
+{
+ d.print_status( s );
+ return s;
+}
+
+void
+r_Polygon::fillMArray( r_GMarray& myArray, bool fillInside, const std::string& bgr ) const throw(r_Error)
+{
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ RMInit::logOut << "r_Polygon::fillMArray(...) polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ // This code currently is not optimised. For every scanline all edges are checked.
+ // Normally you would keep a list of currently relevant edges and manage deletes
+ // and additions to this table by presorting. Anyway, focus was on correctnes
+ // for the time being and even that was not really easy.
+
+ // all edges of the poly except for horizontal ones.
+ std::set<r_Edge, EdgeSortCriterion> sortedEdges;
+ // the X values of the edges in the current scanline.
+ std::vector<double> currXVals;
+ // just to save some typing.
+ r_Minterval myDom = myArray.spatial_domain();
+ unsigned long typeSize = myArray.get_type_length();
+
+ // build sortedEdges (sorted after startPoint y, startPoint x).
+ std::vector<r_Edge>::const_iterator iter, iterEnd;
+ for(iter = edges.begin(), iterEnd=edges.end(); iter != iterEnd; ++iter)
+ sortedEdges.insert(*iter);
+
+ // now the actual filling is done. Remember that we only draw the outside!
+ // we iterate through the whole y range
+ for(r_Range y = myDom[1].low(); y <= myDom[1].high(); y++)
+ {
+ // update the currXVals by iterating through all edges.
+ for(std::multiset<r_Edge, EdgeSortCriterion>::const_iterator itera = sortedEdges.begin(); itera != sortedEdges.end(); itera++)
+ {
+ if( (*itera).getStart()[1] <= y && y <= (*itera).getEnd()[1] ||
+ (*itera).getEnd()[1] <= y && y <= (*itera).getStart()[1] )
+ {
+ currXVals.push_back((*itera).getCurrX(y));
+ }
+ }
+ // sort them.
+ sort(currXVals.begin(), currXVals.end());
+ // currently we can only draw concave polygons anyway (see below).
+ // So this is heavily simplified! Check version 1.3 for a
+ // blueprint of how it should look like.
+ if(fillInside)
+ {
+ if(currXVals.size() >= 1)
+ {
+ // currXVals is sorted, so just draw from the first to the last.
+ eraseLine(rint(currXVals.front()), rint(currXVals.back()), y, myArray, bgr);
+ }
+ }
+ else
+ {
+ // currXVals is sorted, so just draw from low to the first and
+ // from the last to high.
+ // This only works correctly if the polygon is clipped
+ // to the area of the image.
+ if(currXVals.size() >= 1)
+ {
+ eraseLine(myDom[0].low(), rint(currXVals.front())-1.0, y, myArray, bgr);
+ eraseLine(rint(currXVals.back())+1.0, myDom[0].high(), y, myArray, bgr);
+ }
+ else
+ {
+ eraseLine(myDom[0].low(), myDom[0].high(), y, myArray, bgr);
+ }
+ }
+ // Note:
+ // Couldn't get it working with an even/odd inside rule. Reason: If you
+ // want to do this correctly you have to classify two edges meeting into
+ // different categories to decide if they have to be put into currXVals
+ // once or twice. Otherwise you get problems. With this simplified version
+ // only convex polygons are filled correctly!
+
+ // delete the old currXVals
+ currXVals.clear();
+ }
+}
+
+r_Minterval
+r_Polygon::getBoundingBox() const throw(r_Error)
+{
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ TALK( "r_Polygon::getBoundingBox() polygon opened" );
+ RMInit::logOut << "r_Polygon::getBoundingBox() polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ r_Minterval retVal(2);
+ r_Range minX = LONG_MAX;
+ r_Range maxX = LONG_MIN;
+ r_Range minY = LONG_MAX;
+ r_Range maxY = LONG_MIN;
+ r_Range currMinX=0, currMaxX=0, currMinY=0, currMaxY=0;
+ std::vector<r_Edge>::const_iterator iter, iterEnd;
+
+ for(iter = edges.begin(), iterEnd=edges.end(); iter != iterEnd; ++iter)
+ {
+ currMinX = (*iter).getStart()[0] < (*iter).getEnd()[0] ? (*iter).getStart()[0] : (*iter).getEnd()[0];
+ currMaxX = (*iter).getStart()[0] > (*iter).getEnd()[0] ? (*iter).getStart()[0] : (*iter).getEnd()[0];
+ currMinY = (*iter).getStart()[1] < (*iter).getEnd()[1] ? (*iter).getStart()[1] : (*iter).getEnd()[1];
+ currMaxY = (*iter).getStart()[1] > (*iter).getEnd()[1] ? (*iter).getStart()[1] : (*iter).getEnd()[1];
+ minX = currMinX < minX ? currMinX : minX;
+ maxX = currMaxX > maxX ? currMaxX : maxX;
+ minY = currMinY < minY ? currMinY : minY;
+ maxY = currMaxY > maxY ? currMaxY : maxY;
+ }
+ retVal << r_Sinterval(minX, maxX) << r_Sinterval(minY, maxY);
+ return retVal;
+}
+
+void
+r_Polygon::clip(const r_Minterval& clipDom) throw(r_Error)
+{
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ TALK( "r_Polygon::getBoundingBox() polygon opened" );
+ RMInit::logOut << "r_Polygon::getBoundingBox() polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ std::vector<r_Point> pointList;
+
+ // Disjunct polygons used to crash the program.
+ // check if the bounding box of the polygon overlaps the clipDom
+ if(clipDom.intersects_with(getBoundingBox()))
+ {
+ // We just clip all 4 edges
+ for(int s = r_Polygon::top; s <= r_Polygon::right; ++s)
+ {
+ pointList=clip1Side(clipDom, (r_Polygon::Side)s);
+ if(pointList.empty()) // do we have intersection points?
+ {
+ // return a polygon with one line only. This should delete everything.
+ pointList.push_back(r_Point(clipDom[0].low(), clipDom[1].low()));
+ pointList.push_back(r_Point(clipDom[0].low(), clipDom[1].high()));
+ }
+ fromPoints(pointList);
+ pointList.clear();
+ }
+ }
+ else
+ {
+ // return a polygon with one line only. This should delete everything.
+ pointList.push_back(r_Point(clipDom[0].low(), clipDom[1].low()));
+ pointList.push_back(r_Point(clipDom[0].low(), clipDom[1].high()));
+ fromPoints(pointList);
+ }
+}
+
+
+void
+r_Polygon::scale(const r_Point& origin, const r_Minterval& mddDom,
+ const r_Minterval& clipDom, const double& scaleFactor) throw(r_Error)
+{
+ r_Dimension dim = origin.dimension();
+ std::vector<r_Point> oldPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = oldPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = oldPoints.end();
+ std::vector<r_Point> newPoints;
+ r_Point tmpPoint(dim);
+ r_Range coord=0;
+
+ // iterate through all points
+ while( iter != iterEnd )
+ {
+ // currently only 2-D, but who knows
+ for (int i=0; i<dim; i++)
+ {
+ coord = (*iter)[i];
+ // This is yet another copy of the code in tile.cc (another one is
+ // in fastscale.cc). Hope it is exact enough if I do not do the
+ // correction for seamless tiling as done in Tile::getScaleDomain().
+ coord = (r_Range)(origin[i] + floor((coord - origin[i]) * scaleFactor));
+ // This domain thing is driving me crazy. Ok, now we still have to
+ // shift the domain so that it coincides with the origin of the
+ // MInterval used for clipping later (i.e. the domain of the MDD
+ // object which will be later filled using the polygon. See
+ // fastscale.cc, r_Fast_Scale<T>::get_scaled_image().
+ coord = coord + mddDom[i].high() - clipDom[i].high();
+ tmpPoint[i] = coord;
+ }
+ newPoints.push_back(tmpPoint);
+ ++iter;
+ }
+ fromPoints(newPoints);
+}
+
+
+void
+r_Polygon::scale(const r_Point& origin, const double& scaleFactor) throw(r_Error)
+{
+ r_Dimension dim = origin.dimension();
+ std::vector<r_Point> oldPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = oldPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = oldPoints.end();
+ std::vector<r_Point> newPoints;
+ r_Point tmpPoint(dim);
+ r_Range coord=0;
+
+ //std::cout << "Polygon bounding box " << getBoundingBox() << std::endl;
+
+ // iterate through all points
+ while( iter != iterEnd )
+ {
+ // currently only 2-D, but who knows
+ for (int i=0; i<dim; i++)
+ {
+ coord = (*iter)[i];
+ // scaling is done in this way:
+ // translate to 0, scale and translate back
+ coord = origin[i]+(r_Range)floor((coord-origin[i]) * scaleFactor);
+ tmpPoint[i] = coord;
+ }
+ newPoints.push_back(tmpPoint);
+ ++iter;
+ }
+ fromPoints(newPoints);
+
+ //std::cout << "Polygon bounding box " << getBoundingBox() << std::endl;
+}
+
+void
+r_Polygon::mirror(const r_Minterval& mddDom) throw(r_Error)
+{
+ r_Dimension dim = mddDom.dimension();
+ std::vector<r_Point> oldPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = oldPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = oldPoints.end();
+ std::vector<r_Point> newPoints;
+ r_Point tmpPoint(dim);
+ r_Range y=0;
+
+ // iterate through all points
+ while( iter != iterEnd )
+ {
+ y = mddDom[1].high() - (*iter)[1];
+ tmpPoint = (*iter);
+ tmpPoint[1] = y;
+ newPoints.push_back(tmpPoint);
+ ++iter;
+ }
+ fromPoints(newPoints);
+}
+
+void
+r_Polygon::fromPoints(const std::vector<r_Point>& newPoints) throw(r_Error)
+{
+ std::vector<r_Point>::const_iterator iter, iterEnd;
+
+ if(newPoints.empty())
+ {
+ TALK( "r_Polygon::fromPoinst(....) newPoints is empty" );
+ RMInit::logOut << "r_Polygon::fromPoinst(....) newPoints is empty" << std::endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ iter = newPoints.begin();
+ iterEnd = newPoints.end();
+ edges.clear();
+
+ firstPoint = *iter;
+ currPoint = *iter;
+ while( ++iter != iterEnd )
+ {
+ edges.push_back(r_Edge(currPoint, *iter));
+ currPoint = *iter;
+ }
+ edges.push_back(r_Edge(currPoint, firstPoint));
+ closed = true;
+}
+
+void
+r_Polygon::eraseLine( r_Range x1, r_Range x2, r_Range y, r_GMarray& myArray, const std::string& bgr ) const throw(r_Error)
+{
+ // Do nothing in that case (may happen due to rounding problems)
+ if(x2 < x1)
+ return;
+
+ r_Minterval eraseDom(2);
+ eraseDom << r_Sinterval(x1, x2) << r_Sinterval(y, y);
+ r_Minterval arrayDom = myArray.spatial_domain();
+ r_Bytes typeSize = myArray.get_type_length();
+ r_Bytes bgrSize = bgr.size();
+ const char *bgrContent=bgr.c_str();
+ char *currCell=NULL;
+
+
+ // Grrr. In RasDaMan the y are stored close together. So the whole fillPolygon
+ // should have been organised by x instead of y. Well, for now I just use an
+ // r_Miter here.
+ r_Miter eraseIter( &eraseDom, &arrayDom, typeSize, myArray.get_array() );
+ while( !eraseIter.isDone() )
+ {
+ currCell = eraseIter.nextCell();
+ // FIXME This potentially wont work for all types. I just set every byte to 0.
+ if(bgr.empty())
+ memset(currCell, 0, typeSize);
+ else
+ {
+ if( typeSize != bgrSize)
+ throw r_Error( r_Error::r_Error_TypeInvalid );
+ memmove(currCell, bgrContent, bgrSize);
+ }
+ }
+}
+
+std::vector<r_Point>
+r_Polygon::clip1Side(const r_Minterval& b, r_Polygon::Side s)
+{
+ // This routine clips a polygon against one (endless) edge of a bounding box.
+ // It is an implementation of the Sutherland-Hodgman algorithm geared more
+ // towards readability than efficiency. The algorithm classifies edges into
+ // four cases:
+ // Case 1: both ends are inside. Then add the end point to the list of points.
+ // Case 2: start inside, end outside. And only the intersection of the
+ // bounding box edge and the polygon edge.
+ // Case 3: completely outside. Add no points.
+ // Case 4: start outside, end inside. Add end and the intersection of the
+ // bounding box edge and the polygon edge.
+
+ std::vector<r_Point> out;
+ std::vector<r_Edge>::const_iterator iter, iterEnd;
+
+ // iterate through all edges
+ for(iter = edges.begin(),iterEnd=edges.end(); iter != iterEnd; ++iter)
+ {
+ if(inside(b, (*iter).getEnd(), s))
+ {
+ if(inside(b, (*iter).getStart(), s))
+ {
+ // case 1
+ out.push_back((*iter).getEnd());
+ }
+ else
+ {
+ // case 4
+ out.push_back(intersect(b, *iter, s));
+ out.push_back((*iter).getEnd());
+ }
+ }
+ else
+ {
+ if(inside(b, (*iter).getStart(), s))
+ {
+ // case 2
+ out.push_back(intersect(b, *iter, s));
+ }
+ }
+ // do nothing for case 3
+ }
+ return out;
+}
+
+bool
+r_Polygon::inside(const r_Minterval& b, const r_Point& p, r_Polygon::Side s)
+{
+ switch(s)
+ {
+ case top:
+ return p[1] <= b[1].high();
+ case bottom:
+ return p[1] >= b[1].low();
+ case right:
+ return p[0] <= b[0].high();
+ case left:
+ return p[0] >= b[0].low();
+ default:
+ return false;
+ }
+}
+
+r_Point
+r_Polygon::intersect(const r_Minterval& b, const r_Edge& e, r_Polygon::Side s)
+{
+ switch(s)
+ {
+ case top:
+ return r_Point( e.getCurrX(b[1].high()), b[1].high() );
+ case bottom:
+ return r_Point( e.getCurrX(b[1].low()), b[1].low() );
+ case right:
+ return r_Point( b[0].high(), e.getCurrY(b[0].high()) );
+ default: //case left:
+ return r_Point( b[0].low(), e.getCurrY(b[0].low()) );
+ }
+}
+
+r_Point
+r_Polygon::getMiddle() const throw(r_Error)
+{
+ // Note that the summing up done here is a bit risky since overflows
+ // give incorrect results.
+
+ r_Point retVal(2);
+ double xSum = 0;
+ double ySum = 0;
+ int pointCount = 0;
+ std::vector<r_Point> myPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = myPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = myPoints.end();
+
+ while( iter != iterEnd )
+ {
+ ySum += (*iter)[1];
+ xSum += (*iter)[0];
+ ++pointCount;
+ ++iter;
+ }
+ retVal[0] = rint((xSum / pointCount));
+ retVal[1] = rint((ySum / pointCount));
+
+ return retVal;
+}
+
+void
+r_Polygon::shrinkPoly(int pixelCount) throw(r_Error)
+{
+ // Ok now, we move all points towards the middle. Since we store edges we
+ // have to use this somewhat clumsy form with using points in between.
+ // Note that there is quite a bit of potential for error (e.g. points
+ // coinciding after moving them), Anyway, this was programmed as a quick
+ // hack for a problem at BLVA.
+ r_Point middle = getMiddle();
+ r_Dimension dim = middle.dimension();
+ std::vector<r_Point> oldPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = oldPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = oldPoints.end();
+ std::vector<r_Point> newPoints;
+ r_Point tmpPoint(dim);
+ r_Range coord=0;
+
+ // iterate through all points
+ while( iter != iterEnd )
+ {
+ // currently only 2-D, but who knows
+ for (int i=0; i<dim; i++)
+ {
+ coord = (*iter)[i];
+ if(coord > middle[i])
+ {
+ coord = coord - pixelCount;
+ }
+ else
+ {
+ if(coord < middle[i])
+ {
+ coord = coord + pixelCount;
+ }
+ }
+ tmpPoint[i] = coord;
+ }
+ newPoints.push_back(tmpPoint);
+ ++iter;
+ }
+ fromPoints(newPoints);
+}
+
+
+int
+r_Polygon::countEdges() const
+{
+ return edges.size();
+}
+
+int
+r_Polygon::countHorizontalEdges() const
+{
+ int counter = 0;
+
+ std::vector<r_Edge>::const_iterator iter = edges.begin();
+
+ for(int i=0;i<edges.size();i++,iter++)
+ {
+ counter += iter->isHorizontal() ? 1:0;
+ }
+ return counter;
+}
+
diff --git a/rasodmg/polygon.hh b/rasodmg/polygon.hh
new file mode 100644
index 0000000..ebed9ea
--- /dev/null
+++ b/rasodmg/polygon.hh
@@ -0,0 +1,287 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: polygon.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Polygon
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_POLYGON_
+#define _R_POLYGON_
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "raslib/point.hh"
+#include "raslib/minterval.hh"
+
+class r_GMarray;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The class r_Edge is used to represent edges of 2-D polygons
+ represented in class r_Polygon. Edges cannot be modified. This does
+ not make sense, as a polygon always has to consist out of connecting
+ edges. Modifications should always be done on the polygon.
+
+*/
+
+class r_Edge
+{
+public:
+ /// constructor getting a 2-D start and end point.
+ r_Edge(const r_Point& newStart, const r_Point& newEnd);
+
+ /// retrieve 2-D start point of edge.
+ const r_Point& getStart() const;
+
+ /// retrieve 2-D end point of edge.
+ const r_Point& getEnd() const;
+
+ /// calculate inverse slope of the edge. Note: may throw exception due to division by 0.
+ double getInvSlope() const;
+
+ /// calculate slope of the edge. Note: may throw exception due to division by 0.
+ double getSlope() const;
+
+ /// retrieve x for a given y on a line with the slope of the edge. Calls getInvSlope().
+ double getCurrX(r_Range y) const;
+
+ /// retrieve y for a given x on a line with the slope of the edge. Calls getSlope().
+ double getCurrY(r_Range x) const;
+
+ /// print start and end point of the edge.
+ void print_status( std::ostream& s = std::cout ) const;
+
+ /// returns true if the edge is parallel to the first axis
+ bool isHorizontal() const;
+
+private:
+ /// start point of the edge.
+ r_Point start;
+
+ /// end point of the edge.
+ r_Point end;
+};
+
+/*@Doc:
+
+ The class r_Polygon is used to represent 2-D polygons in
+ RasDaMan. Polygons are always constructed by specifying a set of
+ points. This class is mainly used for doing polygonal cutouts on
+ r_Marray objects, it offers the relevant methods for that purpose.
+
+ The construction of a r_Polygon with addPoint has to finish with a
+ call to close(). A open polygon is not a legal polygon! Currently no
+ exceptions are thrown if a polygon is open and methods besides
+ addPointXY or close are called. The results are undefined, if the
+ polygon is not closed.
+
+*/
+
+class r_Polygon
+{
+public:
+
+ /// FIXME current we support only 2 dimensional polygon
+ static const r_Dimension polyPointDim;
+
+ /// enum used to clasify one polygon
+ enum r_Polygon_Type{
+ UNKNOWN,
+ CONCAVE,
+ CONVEX
+ };
+
+ /// constructor to initialize polygon from a string
+ r_Polygon(const char* init) throw (r_Error);
+
+ /// constructor getting x and y of the first point in the polygon.
+ r_Polygon(r_Range x, r_Range y);
+
+ /// copy constructor
+ r_Polygon(const r_Polygon&);
+
+ /// default constructor.
+ r_Polygon();
+
+ /// asignment opertor
+ r_Polygon& operator=(const r_Polygon&);
+
+ /// add a point to the polygon.
+ void addPoint(const r_Point& newPoint) throw(r_Error);
+
+ /// add a point to the polygon specifying x and y.
+ void addPointXY(r_Range x, r_Range y) throw(r_Error);
+
+ /// close a polygon after creation with addPointXY.
+ void close();
+
+ /// retrieve the set of all edges of the polygon.
+ const std::vector<r_Edge>& getEdges() const throw(r_Error);
+
+ /// determine the polygon type for an polygon in 2D
+ r_Polygon::r_Polygon_Type detectPolygonType() const throw(r_Error);
+ /**
+ It is assumed that the polygon is simple (does not intersect itself or have holes)
+ Returns UNKNOWN for incomputables eg: polygon with colinear points, polygon with less then 3 points
+ */
+
+ /// retrieve a vector of all points in the polygon.
+ std::vector<r_Point> getPoints() const throw(r_Error);
+ /**
+ Each point is connected with its successor. The last point is connected to the first one.
+ */
+
+ /// print all edges of the polygon.
+ void print_status( std::ostream& s = std::cout ) const;
+
+ /// Fill the 2-D array myArray according to the polygon.
+ void fillMArray( r_GMarray& myArray, bool fillInside = false, const std::string& bgr = "") const throw(r_Error);
+ /** The polygon has to be completely in the domain of the array. Should this not be the case,
+ then the polygon must be clipped according to the domain of the array. Filling is done
+ so that the data in the array is overwritten byte by byte with 0 which is not inside
+ the polygon.
+ */
+
+ /// retrieve the bounding box of the polygon.
+ r_Minterval getBoundingBox() const throw(r_Error);
+
+ /// clip the polygon according to the bounding box specified in clipDom.
+ void clip(const r_Minterval& clipDom) throw(r_Error);
+ /** Note that the r_Polygon object is modified! So after calling clip you will generally
+ have a different polygon represented by your object. */
+
+ /// scale the points of the polygon according to scaleFactor.
+ void scale(const r_Point& origin, const r_Minterval& mddDom,
+ const r_Minterval& clipDom, const double& scaleFactor) throw(r_Error);
+ /** This function is used when using a polygon to extract part of an image retrieved
+ with r_Fast_Scale. The scaling is done like in r_Fast_Base_Scale::get_scaled_domain().
+ origin is the point of origin for the scaling. mddDom is the domain of the MDD which
+ will later be filled with the polygon. Problem is, that the domain of this MDD is
+ currently not created by simply scaling the domain of the original MDD. Instead it
+ is made sure that the origin of the scaled domain stays the same. clipDom is used
+ to do the same when scaling the polygon, it contains the scaled domain of the MDD
+ without shifting it to origin of the domain of the MDD before scaling. It is a
+ bit complicated, I know. scaleFactor is trivially the scaleFactor used. */
+
+ /// scale the points of the polygon according to scaleFactor.
+ void scale(const r_Point& origin, const double& scaleFactor) throw(r_Error);
+ /** This function is used used when we scale a polygon to extract part of an image retrieved
+ with r_Fast_Scale. The scaling is done like in r_Fast_Base_Scale::get_scaled_domain().
+ origin is the point of origin for the scaling. scaleFactor is the scale factor used. */
+
+ /// mirrors a polygon along the y-axes point by point.
+ void mirror(const r_Minterval& mddDom) throw(r_Error);
+ /** The mirroring is done along the middle of mddDom. It is done like that to be coherent
+ with the mirroring commonly done when inserting TIFF image, e.g. in insertlva.cc. */
+
+ /// get "middle" point by averaging all x and y values.
+ r_Point getMiddle() const throw(r_Error);
+
+ /// "shrink" polygon by moving all points towards the middle by pixelCount pixels.
+ void shrinkPoly(int pixelCount) throw(r_Error);
+
+ /// returns the number of edges
+ int countEdges() const;
+
+ /// returns the number of horizontal edges (used by polygon cut out)
+ int countHorizontalEdges() const;
+
+private:
+
+ /// check if the current point is the first point to close the polygon
+ void checkFistPoint();
+
+ /// clipping is done side by side. This enum is used to tell functions which side to clip.
+ enum Side {
+ top, bottom, left, right
+ };
+
+ /// overwrite this with a polygon create from a vector of points.
+ void fromPoints(const std::vector<r_Point>& newPoints) throw(r_Error);
+
+ /// erase the area in myArray outside of the polygon for one scanline.
+ void eraseLine( r_Range x1, r_Range x2, r_Range y, r_GMarray& myArray, const std::string& bgr ) const throw(r_Error);
+
+ /// return the polygon clipped on the specified side as a list of points.
+ std::vector<r_Point> clip1Side(const r_Minterval& b, r_Polygon::Side s);
+
+ /// determine if a point is inside a bounding line on a certain side.
+ bool inside(const r_Minterval& b, const r_Point& p, r_Polygon::Side s);
+
+ /// intersect an edge with a bounding line on a certain side.
+ r_Point intersect(const r_Minterval& b, const r_Edge& e, r_Polygon::Side s);
+
+ /// flag if the polygon is closed.
+ bool closed;
+
+ /// flag if firstPoint has been set.
+ bool firstPointSet;
+
+ /// vector of all edges of the polygon.
+ std::vector<r_Edge> edges;
+ /// remember first point. Used when constructing the polygon.
+
+ r_Point firstPoint;
+
+ /// remember last added point. Used when constructing the polygon.
+ r_Point currPoint;
+};
+
+extern std::ostream& operator<<( std::ostream& s, const r_Polygon& d );
+
+// The following classes are STL function objects which can be used to make
+// sorted collection of r_Edge. In the current implementation only the first
+// one is needed.
+
+class EdgeSortCriterion
+{
+public:
+ // This is needed for keeping a sorted set of edges (sorted by start coordinate y,
+ // then start coordinate x).
+ bool operator() (const r_Edge& e1, const r_Edge& e2) const {
+ return e1.getStart()[1] < e2.getStart()[1] ||
+ (!(e2.getStart()[1] < e1.getStart()[1]) && e1.getStart()[0] < e2.getStart()[0]);
+ }
+};
+
+class ActiveEdgeSortCriterion
+{
+public:
+ // This is needed for keeping a sorted set of active edges (sorted by start coordinate x,
+ // then start coordinate y).
+ bool operator() (const r_Edge& e1, const r_Edge& e2) const {
+ return e1.getStart()[0] < e2.getStart()[0] ||
+ (!(e2.getStart()[0] < e1.getStart()[0]) && e1.getStart()[1] < e2.getStart()[1]);
+ }
+};
+
+#endif
diff --git a/rasodmg/ref.cc b/rasodmg/ref.cc
new file mode 100644
index 0000000..b63be0e
--- /dev/null
+++ b/rasodmg/ref.cc
@@ -0,0 +1,656 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: ref.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Ref
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsidref[] = "@(#)rasodmg, r_Ref: $Id: ref.cc,v 1.28 2002/08/28 12:10:18 coman Exp $";
+
+#include "rasodmg/database.hh"
+#include "rasodmg/ref.hh"
+
+#include "raslib/rmdebug.hh"
+
+#ifdef __VISUALC__
+#include <sstrea.h>
+#else
+#include <sstream>
+#endif
+
+#include "rasodmg/transaction.hh"
+#include "clientcomm/clientcomm.hh"
+
+// forward declaration needed because of EARLY_TEMPLATE
+class r_Transaction;
+
+// In case of early templates take care non-template code is only
+// compiled once.
+#ifndef __EXECUTABLE__
+
+r_Ref_Any::r_Ref_Any()
+ : memptr(0), oid()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any()")
+}
+
+
+
+r_Ref_Any::r_Ref_Any( const r_Ref_Any& obj )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( const r_Ref_Any& )")
+ memptr = obj.memptr;
+ oid = obj.oid;
+}
+
+
+
+r_Ref_Any::r_Ref_Any( const r_OId& initOId )
+ : memptr(0)
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( const r_OId& )")
+ oid = initOId;
+}
+
+
+
+r_Ref_Any::r_Ref_Any( r_Object* ptr )
+ : oid(), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( r_Object* )")
+}
+
+
+
+r_Ref_Any::r_Ref_Any( void* ptr )
+ : oid(), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( void* )")
+}
+
+
+r_Ref_Any::r_Ref_Any( const r_OId &initOId, r_Object* ptr )
+ : oid( initOId ), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( const r_OId &oid, const r_Object* )")
+}
+
+
+
+r_Ref_Any::~r_Ref_Any()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "~r_Ref_Any()")
+
+ // object should not be delete from databse when reference destructor is called
+ // if( memptr ){
+ // delete memptr;
+ // memptr = 0;
+ // }
+}
+
+
+
+r_Ref_Any&
+r_Ref_Any::operator=( const r_Ref_Any& objptr )
+{
+ memptr = objptr.memptr;
+ oid = objptr.oid;
+
+ return *this;
+}
+
+
+
+r_Ref_Any&
+r_Ref_Any::operator=( r_Object* ptr )
+{
+ memptr = ptr;
+ oid = r_OId();
+
+ return *this;
+}
+
+
+
+void
+r_Ref_Any::destroy()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "destroy()")
+
+ if( memptr && !oid.is_valid() ){
+ delete memptr;
+ memptr = 0;
+ }
+}
+
+
+void
+r_Ref_Any::delete_object()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "delete_object()")
+
+ if( memptr ){
+ delete memptr;
+ memptr = 0;
+ }
+}
+
+
+
+r_Ref_Any::operator const void*() const
+{
+ return memptr;
+}
+
+
+
+r_Ref_Any::operator void*()
+{
+ return memptr;
+}
+
+
+
+r_Ref_Any::operator r_Point*()
+{
+ return (r_Point*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Sinterval*()
+{
+ return (r_Sinterval*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Minterval*()
+{
+ return (r_Minterval*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_OId*()
+{
+ return (r_OId*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Scalar*()
+{
+ return (r_Scalar*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Primitive*()
+{
+ return (r_Primitive*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Structure*()
+{
+ return (r_Structure*)memptr;
+}
+
+
+
+int
+r_Ref_Any::operator!() const
+{
+ return !is_null();
+}
+
+
+
+int
+r_Ref_Any::is_null() const
+{
+ return (memptr==0) && !oid.is_valid();
+}
+
+
+
+int
+r_Ref_Any::operator==( const r_Ref_Any& ref ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "operator==( const r_Ref_Any& )")
+ return // both refs are not valid or ...
+ ( is_null() && ref.is_null() ) ||
+ // both oids are valid and the same or ...
+ ( oid.is_valid() && oid == ref.oid ) ||
+ // both oids are not valid and memory pointers are the same
+ ( !oid.is_valid() && !ref.oid.is_valid() && memptr == ref.memptr );
+}
+
+
+
+int
+r_Ref_Any::operator!=( const r_Ref_Any& ref ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "operator!=( const r_Ref_Any& )")
+ return !operator==( ref );
+}
+
+
+
+int
+r_Ref_Any::operator==( const r_Object* ptr ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "operator==( const r_Object* )")
+ return memptr == (void*)ptr;
+}
+
+
+
+int
+r_Ref_Any::operator!=( const r_Object* ptr ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "operator!=( const r_Object* )")
+ return !operator==( ptr );
+}
+
+
+
+
+void*
+r_Ref_Any::get_memory_ptr() const
+{
+ return memptr;
+}
+
+#endif // __EXECUTABLE__
+
+
+
+template<class T>
+r_Ref<T>::r_Ref()
+ : memptr(0), oid()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref()")
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( const r_Ref<T>& obj )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const r_Ref<T>& )")
+ memptr = obj.memptr;
+ oid = obj.oid;
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( const r_OId& initOId )
+ : memptr(0)
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const r_OId& )")
+ oid = initOId;
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( const r_Ref_Any& obj )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const r_Ref_Any& )")
+
+ memptr = (T*)obj.get_memory_ptr();
+ oid = obj.get_oid();
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( T* ptr )
+ : oid(), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const T* )")
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( const r_OId &initOId, T* ptr )
+ : oid( initOId ), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const r_OId &oid, const T* )")
+}
+
+
+
+template<class T>
+r_Ref<T>::~r_Ref()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "~r_Ref()")
+
+ // object should not be delete from databse when reference destructor is called
+ // if( memptr ){
+ // delete memptr;
+ // memptr = 0;
+ // }
+}
+
+
+
+template<class T>
+r_Ref<T>::operator r_Ref_Any() const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator r_Ref_Any()")
+ return r_Ref_Any( oid, (r_Object *)memptr );
+}
+
+
+/*
+template<class T>
+r_Ref<T>::operator const r_Ref_Any() const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator const r_Ref_Any()")
+ return r_Ref_Any( oid, memptr );
+}
+*/
+
+template<class T>
+r_Ref<T>&
+r_Ref<T>::operator=( const r_Ref_Any& ptr )
+{
+ memptr = (T*)ptr.get_memory_ptr();
+ oid = ptr.get_oid();
+
+ return *this;
+}
+
+
+
+template<class T>
+r_Ref<T>&
+r_Ref<T>::operator=( T* ptr )
+{
+ memptr = ptr;
+ oid = r_OId();
+
+ return *this;
+}
+
+
+
+/*
+template<class T>
+r_Ref<T>&
+r_Ref<T>::operator=( r_Ref<T>& objptr )
+{
+ memptr = objptr.memptr;
+ oid = objptr.oid;
+
+ return *this;
+}
+*/
+
+
+template<class T>
+r_Ref<T>&
+r_Ref<T>::operator=( const r_Ref<T>& objptr )
+{
+ memptr = objptr.memptr;
+ oid = objptr.oid;
+
+ return *this;
+}
+
+
+
+template<class T>
+const T&
+r_Ref<T>::operator*() const throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator*()")
+ if( !memptr )
+ load_object();
+
+ if( !memptr )
+ {
+ r_Error err = r_Error( r_Error::r_Error_RefNull );
+ throw err;
+ }
+
+ return *memptr;
+}
+
+
+template<class T>
+T&
+r_Ref<T>::operator*() throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator*()")
+ if( !memptr )
+ load_object();
+
+ if( !memptr )
+ {
+ r_Error err = r_Error( r_Error::r_Error_RefNull );
+ throw err;
+ }
+
+ return *memptr;
+}
+
+
+
+template<class T>
+const T*
+r_Ref<T>::operator->() const throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator->()")
+ if( !memptr )
+ load_object();
+
+ if( !memptr )
+ {
+ r_Error err = r_Error( r_Error::r_Error_RefNull );
+ throw err;
+ }
+
+ return memptr;
+}
+
+template<class T>
+T*
+r_Ref<T>::operator->() throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator->()")
+ if( !memptr )
+ load_object();
+
+ if( !memptr )
+ {
+ r_Error err = r_Error( r_Error::r_Error_RefNull );
+ throw err;
+ }
+
+ return memptr;
+}
+
+
+
+template<class T>
+const T*
+r_Ref<T>::ptr() const throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "ptr()")
+ if( !memptr )
+ load_object();
+
+ return memptr;
+}
+
+
+template<class T>
+T*
+r_Ref<T>::ptr() throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "ptr()")
+ if( !memptr )
+ load_object();
+
+ return memptr;
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator!() const
+{
+ return !is_null();
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::is_null() const
+{
+ return (memptr==0) && !oid.is_valid();
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator==( const r_Ref<T>& refR ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator==( const r_Ref<T>& )")
+ return // both refs are not valid or ...
+ ( is_null() && refR.is_null() ) ||
+ // both oids are valid and the same or ...
+ ( oid.is_valid() && oid == refR.oid ) ||
+ // both oids are not valid and memory pointers are the same
+ ( !oid.is_valid() && !refR.oid.is_valid() && memptr == refR.memptr );
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator!=( const r_Ref<T>& refR ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator!=( const r_Ref<T>& )")
+ return !operator==( refR );
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator==( const T* ptr ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator==( const T* )")
+ return memptr == ptr;
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator!=( const T* ptr ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator!=( const T* )")
+ return !operator==( ptr );
+}
+
+
+template<class T>
+void
+r_Ref<T>::destroy()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "destroy()")
+
+ if( memptr && !oid.is_valid() ){
+ delete memptr;
+ memptr = 0;
+ }
+}
+
+
+
+template<class T>
+void
+r_Ref<T>::delete_object()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "delete_object()")
+
+ if( memptr ){
+ delete memptr;
+ memptr = 0;
+ }
+}
+
+
+
+template<class T>
+T*
+r_Ref<T>::get_memory_ptr() const
+{
+ return memptr;
+}
+
+#ifdef DEF_TRANSACTION
+
+template<class T>
+void
+r_Ref<T>::load_object() const
+{
+ if( oid.is_valid() )
+ {
+ if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( r_Transaction::actual_transaction == 0 ||
+ r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ // load object and take its memory pointer
+ r_Ref<T> ref = r_Transaction::actual_transaction->load_object( oid );
+ memptr = ref.get_memory_ptr();
+ }
+}
+
+#endif
diff --git a/rasodmg/ref.hh b/rasodmg/ref.hh
new file mode 100644
index 0000000..2b5678e
--- /dev/null
+++ b/rasodmg/ref.hh
@@ -0,0 +1,323 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: ref.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Ref, r_Ref_Any
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_REF_
+#define _D_REF_
+
+#include "raslib/error.hh"
+#include "raslib/oid.hh"
+
+class r_Object;
+class r_Point;
+class r_Sinterval;
+class r_Minterval;
+class r_Oid;
+class r_Scalar;
+class r_Primitive;
+class r_Structure;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/**
+ The class \Ref{r_Ref_Any} is defined to support a reference to any
+ type. Its primary purpose is to handle generic refernces and allow
+ conversions of \Ref{r_Ref}s in the type hierarchy. A \Ref{r_Ref_Any}
+ object can be used as an intermediary between any two types \Ref{r_Ref}<X>
+ and \Ref{r_Ref}<Y> where X and Y are different types. A \Ref{r_Ref}<T> can
+ always be converted to a \Ref{r_Ref_Any}; there is a function to perform
+ the conversion in the \Ref{r_Ref}<T> template. Each \Ref{r_Ref}<T> class
+ has a constructor and assignment operator that takes a reference to a
+ \Ref{r_Ref_Any}.
+*/
+
+class r_Ref_Any
+{
+ public:
+ /// default constructor
+ r_Ref_Any();
+
+ /// copy constructor
+ r_Ref_Any( const r_Ref_Any& );
+
+ /// constructor for creating a reference with an oid
+ r_Ref_Any( const r_OId& initOId );
+ /**
+ Dereferencing the self object results in loading the object with {\tt initOId}.
+ */
+
+ /// constructor getting a pointer to a persistent capable object
+ r_Ref_Any( r_Object* );
+
+ /// constructor getting a general pointer
+ r_Ref_Any( void* );
+
+ /// destructor deletes referenced object from main memory and database
+ ~r_Ref_Any();
+
+ /// assignment operator for assigning a \Ref{r_Ref_Any} pointer
+ r_Ref_Any& operator=( const r_Ref_Any& );
+
+ /// assignment operator for assigning a pointer to a persistent capable object
+ r_Ref_Any& operator=( r_Object* );
+
+ /// delete from main memory
+ void destroy();
+
+ /// deletes referenced object from main memory and database
+ void delete_object();
+
+ //@Man: Cast operators:
+ //@{
+ ///
+
+ ///
+ operator const void*() const;
+ ///
+ operator void*();
+ ///
+ operator r_Point*();
+ ///
+ operator r_Sinterval*();
+ ///
+ operator r_Minterval*();
+ ///
+ operator r_OId*();
+ ///
+ operator r_Scalar*();
+ ///
+ operator r_Structure*();
+ ///
+ operator r_Primitive*();
+
+ ///
+ //@}
+
+
+ /// operator for validity test
+ int operator!() const;
+
+ /// method for reference validity test
+ int is_null() const;
+ /**
+ The method delivers true iff the oid and/or the memory pointer are valid.
+ */
+
+ //@Man: Comparison operators:
+ //@{
+ ///
+
+ ///
+ int operator==( const r_Ref_Any& ) const;
+ ///
+ int operator!=( const r_Ref_Any& ) const;
+ /// compares the memory pointer (does not load the object)
+ int operator==( const r_Object* ) const;
+ /// compares the memory pointer (does not load the object)
+ int operator!=( const r_Object* ) const;
+
+ ///
+ //@}
+
+ /// get oid
+ inline const r_OId& get_oid() const;
+
+ //@Man: Methods for internal use only
+ //@{
+ ///
+ /// constructor getting oid and memory pointer
+ r_Ref_Any( const r_OId&, r_Object* );
+ ///
+ inline unsigned int is_oid_valid() const;
+ /// get memory pointer (without loading the object)
+ void* get_memory_ptr() const;
+ ///
+ //@}
+
+ private:
+ /// main memory pointer
+ void* memptr;
+
+ /// object identifier
+ r_OId oid;
+};
+
+
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/**
+ References of type \Ref{r_Ref} in many respects behave like
+ C++ pointers but provide an additional mechanism that guarantees
+ integrity in references to persistent objects. \Ref{r_Ref}
+ implements a so called {\bf smart pointer} which behaves like
+ a C++ pointer but can do additional things in time of dereferencing
+ the pointer. In case that no valid memory pointer is available,
+ which means that the object is not present, and an oid is existing,
+ the object belonging to the oid is read from the db and the new
+ memory pointer is given back.
+*/
+
+template<class T>
+class r_Ref
+{
+ public:
+ /// default constructor
+ r_Ref();
+
+ /// constructor for r_Ref_Any objects
+ r_Ref( const r_Ref_Any& );
+
+ /// constructor for creating a reference with an oid
+ r_Ref( const r_OId& initOId );
+ /**
+ Dereferencing the self object results in loading the object with {\tt initOId}.
+ */
+
+ /// copy constructor
+ r_Ref( const r_Ref<T>& );
+
+ /// destructor deletes referenced object from main memory and database
+ ~r_Ref();
+
+ /// cast to \Ref{r_Ref_Any}
+ operator r_Ref_Any() const;
+
+ // cast to const \Ref{r_Ref_Any}
+ // operator const r_Ref_Any() const;
+
+ /// assignment operator for assigning a \Ref{r_Ref_Any}
+ r_Ref<T>& operator=( const r_Ref_Any& );
+
+ /// assignment operator for assigning a C pointer
+ r_Ref<T>& operator=( T* );
+
+ // assignment operator for assigning a r_Ref pointer
+ // r_Ref<T>& operator=( r_Ref<T>& );
+
+ /// assignment operator for assigning a r_Ref pointer
+ r_Ref<T>& operator=( const r_Ref<T>& );
+
+ /// dereference operator (error kinds: r_Error_RefNull, r_Error_RefInvalid)
+ const T& operator*() const throw (r_Error);
+
+ /// dereference operator (error kinds: r_Error_RefNull, r_Error_RefInvalid)
+ T& operator*() throw( r_Error );
+ /**
+ If the memory pointer is zero and the oid is valid, the object is loaded from the server
+ and a reference to the object in memory is returned.
+ */
+
+ const T* operator->() const throw (r_Error);
+
+ /// operator for dereferencing the reference (error kinds: r_Error_RefNull, r_Error_RefInvalid)
+ T* operator->() throw( r_Error );
+ /**
+ If the memory pointer is zero and the oid is valid, the object is loaded from the server
+ and the new memory location is returned.
+ */
+
+ const T* ptr() const throw (r_Error);
+
+ /// method for dereferencing the reference (error kinds: r_Error_RefNull, r_Error_RefInvalid)
+ T* ptr() throw( r_Error );
+ /**
+ If the memory pointer is zero and the oid is valid, the object is loaded from the server
+ and the new memory location is returned.
+ */
+
+ /// operator for validity test
+ int operator!() const;
+
+ /// method for reference validity test
+ int is_null() const;
+ /**
+ The method delivers true iff the oid and/or the memory pointer are valid.
+ */
+
+ //@Man: Comparison operators:
+ //@{
+ ///
+
+ ///
+ int operator==( const r_Ref<T>& refR ) const;
+ ///
+ int operator!=( const r_Ref<T>& refR ) const;
+ /// compares the memory pointer (does not load the object)
+ int operator==( const T* ) const;
+ /// compares the memory pointer (does not load the object)
+ int operator!=( const T* ) const;
+
+ ///
+ //@}
+
+ /// delete from main memory
+ void destroy();
+
+ /// deletes referenced object from main memory and database
+ void delete_object();
+
+ /// get oid
+ inline const r_OId& get_oid() const;
+
+ //@Man: Methods for internal use only
+ //@{
+ ///
+ /// constructor getting memory pointer
+ r_Ref( T* );
+
+ /// constructor getting oid and memory pointer
+ r_Ref( const r_OId&, T* );
+
+ /// get memory pointer (without loading the object)
+ T* get_memory_ptr() const;
+
+ ///
+ inline unsigned int is_oid_valid() const;
+
+ ///
+ //@}
+
+ private:
+ /// loads an object from database
+ void load_object() const;
+
+ /// main memory pointer
+ mutable T* memptr;
+
+ /// object identifier
+ r_OId oid;
+};
+
+#include "rasodmg/ref.icc"
+
+#endif
diff --git a/rasodmg/ref.icc b/rasodmg/ref.icc
new file mode 100644
index 0000000..8289b8f
--- /dev/null
+++ b/rasodmg/ref.icc
@@ -0,0 +1,64 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: ref.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Ref
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+inline const r_OId&
+r_Ref_Any::get_oid() const
+{
+ return oid;
+}
+
+
+
+inline unsigned int
+r_Ref_Any::is_oid_valid() const
+{
+ return oid.is_valid();
+}
+
+
+
+template<class T>
+inline const r_OId&
+r_Ref<T>::get_oid() const
+{
+ return oid;
+}
+
+
+
+template<class T>
+inline unsigned int
+r_Ref<T>::is_oid_valid() const
+{
+ return oid.is_valid();
+}
diff --git a/rasodmg/set.cc b/rasodmg/set.cc
new file mode 100644
index 0000000..b79fc4e
--- /dev/null
+++ b/rasodmg/set.cc
@@ -0,0 +1,92 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: set.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Set
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+static const char rcsidset[] = "@(#)rasodmg, r_Set: $Id: set.cc,v 1.17 2002/08/23 11:18:44 schatz Exp $";
+
+#include "rasodmg/set.hh"
+
+class r_GMarray;
+
+#ifdef __VISUALC__
+ template class r_Set< r_GMarray *>;
+#endif
+
+#ifndef __GNUG__
+#define NULL 0
+#endif
+
+template<class T>
+r_Set<T>::r_Set() throw(r_Error)
+ : r_Collection<T>()
+{
+ this->allowsDuplicates = 0;
+ this->isOrdered = 0;
+ this->card = 0;
+}
+
+/* OBSOLETE
+template<class T>
+r_Set<T>::r_Set( const char* name )
+ : r_Collection<T>( name )
+{
+ allowsDuplicates = 0;
+ isOrdered = 0;
+ card = 0;
+}
+*/
+
+template<class T>
+r_Set<T>::r_Set( const r_Set<T>& set ) throw(r_Error)
+ : r_Collection<T>( set )
+{
+ this->allowsDuplicates = 0;
+ this->isOrdered = 0;
+}
+
+template<class T>
+r_Set<T>::~r_Set()
+{
+}
+
+template<class T>
+void
+r_Set<T>::insert_element( const T& element, int no_modification )
+{
+ typename r_Collection<T>::CNode* ptr = (typename r_Collection<T>::CNode*)this->coll;
+
+ while ( ptr->next != NULL && *((T*)(ptr->elem)) != element )
+ ptr = ptr->next;
+
+ if ( ptr->elem == NULL || *((T*)(ptr->elem)) != element )
+ r_Collection<T>::insert_element( element, no_modification );
+}
diff --git a/rasodmg/set.hh b/rasodmg/set.hh
new file mode 100644
index 0000000..b9f4915
--- /dev/null
+++ b/rasodmg/set.hh
@@ -0,0 +1,79 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: set.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Set
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_SET_
+#define _D_SET_
+
+#include "rasodmg/collection.hh"
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The class implements a set container. It inherits most of the
+ functionality from {\tt r_Collection}. The set can not have
+ any duplicates and it is not ordered.
+
+*/
+
+template <class T>
+class r_Set : public r_Collection<T>
+{
+ public:
+ /// default constructor
+ r_Set() throw(r_Error);
+ /// copy constructor
+ r_Set( const r_Set<T>& set ) throw(r_Error);
+ /// virtual destructor
+ virtual ~r_Set();
+
+ /// inserts an element at the beginning (no duplicates)
+ virtual void insert_element( const T& element, int no_modification = 0 );
+ /**
+ The method inserts an element into the collection. If {\tt no_modification}
+ is set, the {\tt mark_modified()} method of r_Object is not invoked and, therefore,
+ a modification will not be recognized at the commit point.
+ */
+
+};
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#ifdef __VISUALC__
+#include "rasodmg/set.cpp"
+#else
+#include "rasodmg/set.cc"
+#endif
+#endif
+#endif
+
+#endif
diff --git a/rasodmg/stattiling.cc b/rasodmg/stattiling.cc
new file mode 100644
index 0000000..d99df04
--- /dev/null
+++ b/rasodmg/stattiling.cc
@@ -0,0 +1,678 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: stattiling.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Stat_Tiling r_Access
+ *
+ * COMMENTS:
+ * None
+ */
+
+#ifdef __VISUALC__
+// Diable warning for signed/unsigned mismatch.
+#pragma warning( disable : 4018 )
+#endif
+
+#include "rasodmg/interesttiling.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/stattiling.hh"
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <cstdlib>
+
+// Uncoment the _VISUALIZE_2D_DECOMP_ line to generate ppm files the
+// visualization of the domain decomposition done by the algoritm
+// #define _VISUALIZE_2D_DECOMP_
+
+// Uncomment the following line to have debug information (printfs)
+// #define _DEBUG_STATTILING_
+
+#ifdef _VISUALIZE_2D_DECOMP_
+#include "tools/visualtiling2d.hh"
+#endif
+
+const char*
+r_Stat_Tiling::description = "dimensions, access patterns, border threshold, interesting threshold, tile size (in bytes) (ex: \"2;[0:9,0:9],3;[100:109,0:9],2;2;0.3;100\")";
+
+const r_ULong
+r_Stat_Tiling::DEF_BORDER_THR = 50;
+const r_Double
+r_Stat_Tiling::DEF_INTERESTING_THR = 0.20;
+
+r_Stat_Tiling::r_Stat_Tiling(const char* encoded) throw (r_Error)
+ : r_Dimension_Tiling(0, 0)
+{
+ if(!encoded)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << (encoded?encoded: "NULL") << ")" << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ r_Dimension tileD=0;
+ std::vector<r_Access> vectAccessInfo;
+ r_Access* accessInfo=NULL;
+ r_Minterval* accessInterv=NULL;
+ r_ULong accessTimes=0;
+ r_Bytes tileS=0, lenToConvert=0, lenInToConvert=0;
+ r_Area borderTH=0;
+ r_Double interestTH=0.;
+ const char *pStart=NULL, *pEnd=NULL, *pRes=NULL, *pTemp=NULL;
+ char *pToConvert=NULL;
+ const char *pInRes=NULL, *pInEnd=NULL;
+ char *pInToConvert=NULL;
+
+ pStart=encoded;
+ pEnd=pStart+strlen(pStart);
+ pTemp=pStart;
+
+ pRes=strstr(pTemp,COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with dimension
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert,pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ tileD=strtol(pToConvert, (char**)NULL, DefaultBase);
+ if (!tileD)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pToConvert << "\", is not a number." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileD < 0)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pToConvert << "\", is negative." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access information from \"" << pStart << "\", end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with access informations
+ pTemp=pRes;
+ pRes=strstr(pTemp, COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access information from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ while(pRes)
+ {
+ //is access info?
+ if(*pTemp!=*LSQRBRA)
+ break;
+
+ //copy substring in buffer
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ //deal with access Interval
+ pInEnd=pToConvert+strlen(pToConvert);
+ pInRes=strstr(pToConvert, RSQRBRA);
+ if(!pInRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access information from \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ lenInToConvert=pInRes-pToConvert+1; //1 for ]
+ pInToConvert=new char[lenInToConvert+1];
+ memcpy(pInToConvert, pToConvert, lenInToConvert);
+ pInToConvert[lenInToConvert]='\0';
+
+ try
+ {
+ accessInterv=new r_Minterval(pInToConvert);
+ delete [] pInToConvert;
+ }
+ catch(r_Error &err)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access interval \"" << pInToConvert << "\" from \"" << pToConvert << "\"." << endl;
+ RMInit::logOut << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with access Times
+ pInRes=strstr(pInRes, COMMA);
+ if(!pInRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access times \"" << pInRes << "\" from acess information \"" << pToConvert << "\", not specified." << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if(pInRes!=(pEnd-1))
+ pInRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access times \"" << pInRes << "\" from acess information \"" << pToConvert << "\", not specified." << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ accessTimes=strtol(pInRes, (char**)NULL, DefaultBase);
+ if(!accessTimes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access times \"" << pInRes << "\" from acess information \"" << pToConvert << "\", not a number." << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if(accessTimes<0)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access times \"" << pInRes << "\" from acess information \"" << pToConvert << "\", negative number." << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ accessInfo=new r_Access(*accessInterv, accessTimes);
+ vectAccessInfo.push_back(*accessInfo);
+ delete accessInfo;
+ delete accessInterv;
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access informations, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with next item
+ pTemp=pRes;
+ pRes=strstr(pTemp, COLON);
+ }
+
+ if(vectAccessInfo.empty())
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access informations, no access informations specified." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with borderTH
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ borderTH=strtol(pToConvert, (char**)NULL, DefaultBase);
+ if (!borderTH)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding border threshold \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (borderTH < 0)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding border threshold \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with interestTH
+ pTemp=pRes;
+ pRes=strstr(pTemp,COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //copy substring into buffer
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ interestTH=strtod(pToConvert, (char**)NULL);
+ if (!interestTH)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (interestTH < 0.)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold \"" << pToConvert << "\", negative number." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ if (interestTH > 1.)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold \"" << pToConvert << "\", not in [0,1] interval." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile size, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with tilesize
+ pTemp=pRes;
+ tileS=strtol(pTemp, (char**)NULL, DefaultBase);
+ if (!tileS)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile size \"" << pToConvert << "\", not a number." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileS < 0.)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile size \"" << pToConvert << "\", negative number." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ border_thr = borderTH;
+ stat_info = vectAccessInfo;
+ interesting_thr = interestTH;
+ dimension = tileD;
+ tile_size = tileS;
+}
+
+
+r_Stat_Tiling::r_Stat_Tiling(r_Dimension dim, const std::vector<r_Access>& stat_info2, r_Bytes ts, r_ULong border_threshold, r_Double interesting_threshold) throw (r_Error)
+ : r_Dimension_Tiling(dim, ts),
+ border_thr(border_threshold),
+ stat_info(stat_info2),
+ interesting_thr(interesting_threshold)
+{
+ RMDBGENTER(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Filtering accesses... ");
+ // Filter accesses all areas have the same dimension if successfull else exception
+ filter(stat_info);
+ RMDBGMIDDLE(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "done\n");
+ std::vector<r_Access>::iterator areas_it = stat_info.begin();
+ // Count total accesses
+ r_ULong total_accesses = 0;
+
+
+
+ for (;areas_it != stat_info.end(); areas_it++)
+ {
+ if ((*areas_it).get_pattern().dimension() != dim)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << dim << ", " << &stat_info
+ << ", " << ts << ", " << border_threshold << ", " << interesting_threshold
+ << ") dimension (" << dim << ") does not match dimension of access patterns ("
+ << (*areas_it).get_pattern().dimension() << ")" << endl;
+ throw r_Edim_mismatch(dim, (*areas_it).get_pattern().dimension());
+ }
+ total_accesses += (*areas_it).get_times();
+ }
+
+ RMDBGMIDDLE(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Defining interest areas... ");
+
+ // Mininum number of accesses for being interesting
+ r_ULong critical_accesses = (r_ULong)(interesting_thr*total_accesses);
+
+ iareas.clear();
+ for (areas_it = stat_info.begin(); areas_it != stat_info.end(); areas_it++)
+ {
+ if ((*areas_it).get_times() >= critical_accesses) // Threshold exceeded or equal
+ {
+ iareas.push_back(areas_it->get_pattern()); // count this area in
+ }
+ }
+
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Defining interest areas... done\n");
+}
+
+r_Stat_Tiling::~r_Stat_Tiling()
+{
+}
+
+r_Tiling* r_Stat_Tiling::clone() const
+{
+ r_Tiling* copy = new r_Stat_Tiling(dimension, stat_info, tile_size, border_thr, interesting_thr);
+ return copy;
+}
+
+void r_Stat_Tiling::print_status(std::ostream& os) const
+{
+ os << "r_Stat_Tiling[ ";
+ r_Dimension_Tiling::print_status(os);
+ os << " border threshold = " << border_thr << ", interesting threshold = " << interesting_thr << " ]";
+}
+
+const std::vector<r_Minterval>&
+r_Stat_Tiling::get_interesting_areas() const
+ {
+ return iareas;
+ }
+
+r_Tiling_Scheme
+r_Stat_Tiling::get_tiling_scheme() const
+ {
+ return r_StatisticalTiling;
+ }
+
+r_Area
+r_Stat_Tiling::get_border_threshold() const
+{
+ return border_thr;
+}
+
+r_Double
+r_Stat_Tiling::get_interesting_threshold() const
+{
+ return interesting_thr;
+}
+
+r_Access
+r_Stat_Tiling::merge(const std::vector<r_Access>& patterns) const
+{
+ // Create an interator for list of patterns
+ std::vector<r_Access>::const_iterator it = patterns.begin();
+
+ // The result (initialy updated to the first element of patterns)
+ r_Access result = (*it);
+ it++;
+
+ // For all patterns
+ for (;it != patterns.end(); it++)
+ {
+ result.merge_with(*it); // Merge them
+ }
+ return result; // Return the result
+}
+
+void r_Stat_Tiling::filter(std::vector<r_Access>& patterns) const throw (r_Error)
+{
+ // List to hold the result
+ std::vector<r_Access> result;
+
+ // List to hold the clusters
+ std::vector<r_Access> cluster;
+
+ // Iterators for pattern and cluster list
+ std::vector<r_Access>::iterator pattern_it = patterns.begin();
+ std::vector<r_Access>::iterator cluster_it;
+
+ // For all elements in pattern table
+ while (!patterns.empty())
+ {
+ // Clean cluster
+ cluster.clear();
+ // Cluster with first element of pattern list
+ cluster.push_back(patterns.back());
+ patterns.pop_back();
+
+ // For all elements in the cluster
+ for (cluster_it = cluster.begin(); cluster_it != cluster.end(); cluster_it++)
+ {
+ // For all remaining patterns
+ for (pattern_it = patterns.begin(); pattern_it != patterns.end(); pattern_it++)
+ {
+ // Pattern near an element from the cluster
+ if ((*cluster_it).is_near(*pattern_it, border_thr))
+ {
+ // Add pattern to the cluster
+ cluster.push_back(*pattern_it);
+ // Remove pattern from list
+ patterns.erase(pattern_it);
+ }
+ }
+ }
+ // Merge cluster and add to result
+ result.push_back(merge(cluster));
+ }
+ // Filtered table
+ patterns = result;
+}
+
+std::vector<r_Minterval>*
+r_Stat_Tiling::compute_tiles(const r_Minterval& domain, r_Bytes typelen) const throw (r_Error)
+{
+ r_Dimension num_dims = domain.dimension(); // Dimensionality of dom
+if (domain.dimension() != dimension)
+ {
+ RMInit::logOut << "r_Stat_Tiling::compute_tiles(" << domain << ", " << typelen << ") dimension (" << dimension << ") does not match dimension of object to tile (" << num_dims << ")" << endl;
+ throw r_Edim_mismatch(dimension, num_dims);
+ }
+if (typelen > tile_size)
+ {
+ RMInit::logOut << "r_Stat_Tiling::compute_tiles(" << domain << ", " << typelen << ") tile size (" << tile_size << ") is smaller than type length (" << typelen << ")" << endl;
+ throw r_Error(TILESIZETOOSMALL);
+ }
+#ifdef _VISUALIZE_2D_DECOMP_ // User wants a visual
+ static int count; // Number of decomps
+ ++count; // Update num decomps
+ // of the 2D decomp.
+ Visual_Tiling_2D* vis;
+ if (domain.dimension() == 2)
+ {
+ // Create an object for visualization
+ char fname[80];
+ sprintf(fname, "2D_decomp_stat_%d.ppm", count);
+ vis = new Visual_Tiling_2D(domain, fname);
+ }
+#endif
+
+ // *** Main algoritm ***
+
+ std::vector<r_Minterval>* result; // Holds the result
+
+ if (iareas.empty()) // No interest areas
+ {
+ // Perform regular tiling
+
+ RMDBGENTER(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Regular tiling...");
+
+ result = r_Size_Tiling::compute_tiles(domain, typelen);
+
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "done\n");
+ }
+ else // We have interest areas
+ {
+ // Use interest areas for tiling the domain
+
+ RMDBGENTER(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Statistic tiling...\n");
+ r_Interest_Tiling* tiling=NULL;
+
+ try
+ {
+ tiling=new r_Interest_Tiling(dimension, iareas, get_tile_size(), r_Interest_Tiling::SUB_TILING);
+ result = tiling->compute_tiles(domain, typelen);
+ delete tiling;
+ }
+ catch(r_Error& err)
+ {
+ if(tiling)
+ delete tiling;
+ throw;
+ }
+
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "done\n");
+ }
+
+ // *** End of the main algorithm
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(0, 255, 255);
+
+ std::vector<r_Minterval>::iterator it(*result);
+ it.seek_begin();
+ for (; it.not_done(); it++)
+ (*vis) << (*it);
+
+ vis->set_pen(255, 255, 0);
+
+ std::vector<r_Minterval>& ia = (std::vector<r_Minterval>) iareas; // Cast away constness
+
+ std::vector<r_Minterval>::iterator it2(ia);
+ it2.seek_begin();
+ for (; it2.not_done(); it2++)
+ (*vis) << (*it2);
+
+ delete vis;
+ }
+#endif
+
+ // Return result
+
+ return result;
+}
+
+
+
+//***************************************************************************
+
+r_Access::r_Access() :
+ times(0)
+{
+}
+
+r_Access::r_Access(const r_Minterval& pattern, r_ULong accesses) :
+ interval(pattern), times(accesses)
+{
+}
+
+const r_Minterval& r_Access::get_pattern() const
+{
+ return interval;
+}
+
+void r_Access::set_pattern(const r_Minterval& pattern)
+{
+ interval = pattern;
+}
+
+r_ULong r_Access::get_times() const
+{
+ return times;
+}
+
+void r_Access::set_times(r_ULong accesses)
+{
+ times = accesses;
+}
+
+bool r_Access::is_near(const r_Access& other, r_ULong border_threshold) const throw (r_Error)
+{
+ const r_Minterval& a = this->interval;
+ const r_Minterval& b = other.interval;
+
+ r_Dimension num_dims = interval.dimension();
+ if (num_dims != b.dimension())
+ {
+ RMInit::logOut << "r_Access::is_near(" << other << ", " << border_threshold << ") parameter 1 does not match my dimension (" << num_dims << ")" << endl;
+ throw r_Edim_mismatch(num_dims, b.dimension());
+ }
+ bool the_same = true;
+
+ // For all dimensions
+ for (r_Dimension i = 0; i < num_dims; i++)
+ {
+ // Higher limit does not exceed border threshold
+ if (labs(a[i].high() - b[i].high()) > border_threshold)
+ {
+ the_same = false;
+ break;
+ }
+
+ // Lower limit does not exceed border threshold
+ if (labs(a[i].low() - b[i].low()) > border_threshold)
+ {
+ the_same = false;
+ break;
+ }
+ }
+
+ return the_same;
+}
+
+void r_Access::merge_with(const r_Access& other)
+{
+ interval.closure_with(other.interval);
+ times+= other.times;
+}
+
+void r_Access::print_status(std::ostream& os) const
+{
+ os << "{" << times <<"x: " << interval << "}";
+}
+
+std::ostream& operator<<(std::ostream& os, const r_Access& access)
+{
+ access.print_status(os);
+
+ return os;
+}
+
+bool r_Access::operator==(const r_Access& other) const
+{
+ return ((this->interval == other.interval) && (this->times == other.times));
+}
+
+bool r_Access::operator!=(const r_Access& other) const
+{
+ return !(*this == other);
+}
diff --git a/rasodmg/stattiling.hh b/rasodmg/stattiling.hh
new file mode 100644
index 0000000..415b919
--- /dev/null
+++ b/rasodmg/stattiling.hh
@@ -0,0 +1,210 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: stattiling.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Stat_Tiling r_Access
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_STATTILING_HH_
+#define _R_STATTILING_HH_
+
+// Include statements
+
+class r_Access;
+class r_Stat_Tiling;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ This class represents an access pattern to a certain object.
+ {\tt r_Stat_Tiling} receives a list of this objects so that
+ an appropriate tiling can be defined.
+*/
+
+class r_Access
+{
+ public:
+
+ /// Class constructor
+ r_Access(const r_Minterval& pattern, r_ULong accesses = 1);
+ /**
+ It takes as parameter the interval and the number of times
+ that interval was accessed.
+ */
+
+ /// Gets the current interval (access pattern)
+ const r_Minterval& get_pattern() const;
+
+ /// Sets the current interval (access pattern)
+ void set_pattern(const r_Minterval& pattern);
+
+ /// Gets the number of times the pattern was accessed
+ r_ULong get_times() const;
+
+ /// Sets the number of times the pattern was accessed
+ void set_times(r_ULong accesses);
+
+ /// Checks if a certain access pattern is "close enough" of other
+ /// throws exception if the domains do not match
+ bool is_near(const r_Access& other, r_ULong border_threshold) const throw (r_Error);
+
+ /// Merge this access pattern with another
+ void merge_with(const r_Access& other);
+
+ /// Print object status
+ void print_status(std::ostream& os) const;
+
+ /// Operator equal
+ bool operator==(const r_Access& other) const;
+
+ /// Operator different
+ bool operator!=(const r_Access& other) const;
+
+ private:
+
+ /// The user can't use the default constructor
+ r_Access();
+
+ /// The actual stored pattern
+ r_Minterval interval;
+
+ /// The number of times it was accessed
+ r_ULong times;
+};
+
+//@ManMemo: Module: {\bf rasodmg}
+/**
+ Prints the status of a Access object to a stream
+*/
+extern std::ostream& operator<<(std::ostream& os, const r_Access& access);
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ This class implements the "statistic tiling" algorithm.
+
+ Three parameters are passed in the constructor of the class,
+ the border threshold for considering two access patterns to be the
+ same, the interesting threshold which specifies the percentage of
+ accesses that must take place so that an areas is considered of interest
+ when performing tiling and also the tilesize.
+
+ A call to {\tt update_stat_information} should be made prior to performing
+ tiling so that the static information about the accesses to the object
+ can be updated and the tiling operation prepared.
+*/
+
+class r_Stat_Tiling : public r_Dimension_Tiling
+{
+ // ******************* PUBLIC SECTION *******************
+
+ public: // constants
+
+ /// Default threshold for two borders being considered the same
+ const static r_Area DEF_BORDER_THR;
+
+ /// Default threshold for considering an area interesting when tiling
+ const static r_Double DEF_INTERESTING_THR;
+
+ /// read everything from an encoded string
+ /// e.g. "2;[0:9,0:9],3;[100:109,0:9],2;2;0.3;100"
+ r_Stat_Tiling(const char* encoded) throw (r_Error);
+
+ /// Class constructor
+ r_Stat_Tiling(r_Dimension dim,
+ const std::vector<r_Access>& stat_info,
+ r_Bytes ts = RMInit::clientTileSize,
+ r_Area border_threshold = DEF_BORDER_THR,
+ r_Double interesting_threshold = DEF_INTERESTING_THR) throw (r_Error);
+ /**
+ This is the "Statistic Tiling" class constructor.
+ It takes as parameters the threshold for, when performing filtering,
+ considering two borders the same, and also, the threshold at which
+ an area is considered interesting and should be taken in account when
+ performing tiling. Finally, the tilesize is considered as a parameter.
+ stat_info inputs the statistic information into the class and
+ calculates the new interest areas that will be used to perform tiling
+ on the object.
+ An exception is thrown when the statistical data does not fit the dimension.
+ */
+
+ virtual ~r_Stat_Tiling();
+
+ /// Gets the statistical information
+ virtual const std::vector<r_Minterval>& get_interesting_areas() const;
+
+ /// Gets the threshold at which to intervals are considered the same
+ r_Area get_border_threshold() const;
+ /**
+ This method gets the number of points (pixels/cells) at which two
+ intervals are considered to be the same, in the access patterns.
+ */
+
+ /// Gets the threshold at which an area is considered to be interesting
+ r_Double get_interesting_threshold() const;
+ /**
+ This method gets the threshold at which an area is considered to be
+ interesting. All the areas that are accessed above the specified
+ threshold, will be considered interest areas when performing tiling.
+ */
+
+ virtual void print_status(std::ostream& os) const;
+
+ virtual std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error);
+
+ virtual r_Tiling* clone() const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ static const char* description;
+
+ protected: // methods
+
+ /// Filters and access pattern table (list)
+ /// throws exception if dimensions of access patterns are not the same
+ void filter(std::vector<r_Access>& patterns) const throw (r_Error);
+
+ /// Merges a list of access patterns
+ r_Access merge(const std::vector<r_Access>& patterns) const;
+
+ /// The "interesting area" threshold
+ r_Double interesting_thr;
+
+ /// The "same border" threshold
+ r_Area border_thr;
+
+ /// Current interest areas
+ std::vector<r_Minterval> iareas;
+
+ /// Statistical data
+ std::vector<r_Access> stat_info;
+};
+
+#endif
diff --git a/rasodmg/storagelayout.cc b/rasodmg/storagelayout.cc
new file mode 100644
index 0000000..847759d
--- /dev/null
+++ b/rasodmg/storagelayout.cc
@@ -0,0 +1,182 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: storagelayout.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_StorageLayout, r_Domain_Storage_Layout
+ *
+ * COMMENTS:
+ * None
+ *
+*/
+
+// Because of NT port
+#include <string.h>
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream>
+#endif
+#include <math.h>
+#include <vector>
+
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/iterator.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/rminit.hh"
+#include "raslib/minterval.hh"
+#include "rasodmg/gmarray.hh"
+
+r_Storage_Layout::r_Storage_Layout(r_Data_Format init_format, const char* formatParams)
+ : til(0),
+ storage_format(init_format),
+ storage_params(0)
+{
+ til = new r_Size_Tiling();
+ if (formatParams != NULL)
+ storage_params = strdup(formatParams);
+}
+
+r_Storage_Layout::r_Storage_Layout(r_Tiling* ts, r_Data_Format init_format, const char* formatParams)
+ : til(ts),
+ storage_format(init_format),
+ storage_params(0)
+{
+ if (til == NULL)
+ til = new r_Size_Tiling();
+ if (formatParams != NULL)
+ storage_params = strdup(formatParams);
+}
+
+r_Storage_Layout::r_Storage_Layout(const r_Storage_Layout& sl)
+ : til(sl.get_tiling()->clone()),
+ storage_format(sl.get_storage_format()),
+ storage_params(0)
+{
+ if (sl.storage_params != NULL)
+ storage_params = strdup(sl.storage_params);
+}
+
+r_Storage_Layout*
+r_Storage_Layout::clone() const
+{
+ r_Storage_Layout* newSL = new r_Storage_Layout(til->clone(), storage_format, storage_params);
+ return newSL;
+}
+
+r_Storage_Layout::~r_Storage_Layout()
+{
+ if(til)
+ {
+ delete til;
+ til = NULL;
+ }
+ if (storage_params)
+ {
+ free(storage_params);
+ storage_params = NULL;
+ }
+}
+
+const r_Tiling*
+r_Storage_Layout::get_tiling() const
+{
+ return til;
+}
+
+r_Data_Format
+r_Storage_Layout::get_storage_format() const
+{
+ return storage_format;
+}
+
+const char*
+r_Storage_Layout::get_storage_format_params() const
+{
+ return storage_params;
+}
+
+r_Set< r_GMarray* >*
+r_Storage_Layout::decomposeMDD(const r_GMarray* mar) const throw (r_Error)
+{
+ r_Bytes cell_size = mar->get_type_length();
+ std::vector<r_Minterval>* tiles=NULL;
+ r_Set<r_GMarray*>* result=NULL;
+
+ if (!til->is_compatible(mar->spatial_domain(), cell_size))
+ {
+ RMInit::logOut << "r_Storage_Layout::decomposeMDD() gmarray is not compatible with tiling" << endl;
+ RMInit::logOut << "\tgmarray domain : " << mar->spatial_domain() << endl;
+ RMInit::logOut << "\tgmarray type size: " << mar->get_type_length() << endl;
+ RMInit::logOut << "\tstorage layout : " << *this << endl;
+ throw r_Error(STORAGERLAYOUTINCOMPATIBLEWITHGMARRAY);
+ }
+
+
+
+ try
+ {
+ tiles = til->compute_tiles(mar->spatial_domain(), cell_size);
+ }
+ catch(r_Error& err)
+ {
+ throw;
+ }
+
+ result = new r_Set<r_GMarray*>;
+
+ for (std::vector<r_Minterval>::iterator it = tiles->begin(); it != tiles->end(); it++)
+ result->insert_element(mar->intersect(*it));
+
+ delete tiles;
+ return result;
+}
+
+void
+r_Storage_Layout::print_status(std::ostream& os) const
+{
+ os << "r_Storage_Layout[ tiling = "<< *til << " storage format = " << storage_format << " storage parameters = ";
+ if (storage_params != NULL)
+ os << "upps, not here";
+ //os << storage_params;
+ else
+ os << "none defined";
+ os << " ]";
+}
+
+bool
+r_Storage_Layout::is_compatible(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const
+{
+ return til->is_compatible(obj_domain, cellTypeSize);
+}
+
+std::ostream&
+operator<<(std::ostream& s, const r_Storage_Layout& sl)
+{
+ sl.print_status(s);
+ return s;
+}
+
diff --git a/rasodmg/storagelayout.hh b/rasodmg/storagelayout.hh
new file mode 100644
index 0000000..decb1a0
--- /dev/null
+++ b/rasodmg/storagelayout.hh
@@ -0,0 +1,132 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: storagelayout.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Storage_Layout, r_Domain_Storage_Layout
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_STORAGELAYOUT_HH_
+#define _R_STORAGELAYOUT_HH_
+
+
+#include <iostream>
+using std::cout;
+
+#include "raslib/mddtypes.hh"
+#include "rasodmg/set.hh"
+
+// forward declarations
+class r_Storage_Layout;
+class r_GMarray;
+class ClientComm;
+class r_Tiling;
+class r_Minterval;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The {\tt r_Storage_Layout} class is used to express the storage options
+ for {\tt r_Marray} objects. This is the superclass of different storage
+ layout classes which may be used for different types of storage layout
+ schemes. It is also used directly by the rasdaman client for
+ default storage layout, i.e., for the storage layout for objects for
+ which absolutely none has been defined.
+
+ Notice: the tiling options are invalid if the rasdaman client is running
+ with the option notiling. In that case, no tiling is done,
+ independently of the storage layout chosen.
+ For the time being, compression does not work.
+*/
+
+class r_Storage_Layout
+{
+ public:
+
+ /// the dataformat is not used. please use the database methods for this purpose.
+ r_Storage_Layout(r_Data_Format init_format = r_Array, const char* formatParams = NULL);
+
+ /// the dataformat is not used. please use the database methods for this purpose.
+ r_Storage_Layout(r_Tiling* ts, r_Data_Format init_format = r_Array, const char* formatParams = NULL);
+
+ /// Copy constructor.
+ r_Storage_Layout(const r_Storage_Layout& sl);
+
+ ///
+ virtual r_Storage_Layout* clone() const;
+
+ /// virtual destructor
+ virtual ~r_Storage_Layout();
+
+ ///
+ const r_Tiling* get_tiling() const;
+
+ /// this does not do anything important. please use the database methods for this purpose.
+ r_Data_Format get_storage_format() const;
+
+ /// this does not do anything important. please use the database methods for this purpose.
+ const char* get_storage_format_params() const;
+
+ /// Function for decomposing large MDDs into a set of smaller tiles
+ virtual r_Set< r_GMarray* >* decomposeMDD(const r_GMarray* mar) const throw (r_Error);
+
+ /// writes the state of the object to the specified stream
+ void print_status(std::ostream& s = cout) const;
+
+ ///
+ virtual bool is_compatible(const r_Minterval& obj_domain, r_Bytes celltypesize) const;
+
+ protected:
+
+ friend class ClientComm;
+ friend class r_GMArray;
+
+ char* storage_params;
+
+ /// the dataformat is not used. please use the database methods for this purpose.
+ r_Data_Format storage_format;
+
+ /// Tiling scheme
+ r_Tiling* til;
+
+};
+
+//@ManMemo: Module: {\bf rasodmg }
+/**
+ Output stream operator for objects of type {\tt const} \Ref{r_Storage_Layout}.
+*/
+extern std::ostream& operator<<(std::ostream& s, const r_Storage_Layout& sl);
+
+#if (defined(__VISUALC__) && !defined(__EXECUTABLE__))
+ #define __EXECUTABLE__
+ #include "raslib/dlist.hh"
+ #undef __EXECUTABLE__
+#else
+ #include "raslib/dlist.hh"
+#endif
+#endif
diff --git a/rasodmg/storagelayout.icc b/rasodmg/storagelayout.icc
new file mode 100644
index 0000000..f31834d
--- /dev/null
+++ b/rasodmg/storagelayout.icc
@@ -0,0 +1,31 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: storagelayout.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Storage_Layout
+ *
+ * COMMENTS:
+ * None
+*/
diff --git a/rasodmg/test/Makefile b/rasodmg/test/Makefile
new file mode 100644
index 0000000..07385a2
--- /dev/null
+++ b/rasodmg/test/Makefile
@@ -0,0 +1,372 @@
+# -*-Makefile-*-
+#
+# This file is part of rasdaman community.
+#
+# Rasdaman community is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Rasdaman community is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+#
+# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+# rasdaman GmbH.
+#
+# For more information please see <http://www.rasdaman.org>
+# or contact Peter Baumann via <baumann@rasdaman.com>. # Top Level makefile. This points to the various modules that have to be build
+# and/or deployed
+#
+# MAKEFILE FOR:
+# test programs of module rasodmg
+#
+# COMMENTS:
+# - the rasql situated here is obsolete, see applications/rasql
+#
+##################################################################
+#
+# This is just an example Makefile for a test program.
+# The dependency of the test program on the lib of the
+# corresponding module is in the Makefile of the module.
+#
+
+######################### Definitions ############################
+
+# standard include with general options
+include $(RMANBASE)/Makefile.inc
+
+DEFCLIENTLIBS = $(RASODMG) $(CLIENTCOMM) $(COMPRESSION) $(RASLIB) $(CONVERSION)
+
+# use client specific flags
+CXXFLAGS := $(CLIENTCXXFLAGS)
+LDFLAGS := $(CLIENTLDFLAGS)
+
+# add communication flags
+CXXFLAGS += $(COMMCXXFLAGS)
+LDFLAGS += $(COMMLDFLAGS)
+
+# COMPDATE must be made more general at the final destination
+COMPDATE = `date +\"%d.%m.%Y %H:%M:%S\"`
+CXXFLAGS += -DCOMPDATE="\"$(COMPDATE)\""
+
+## a symbol for not writing too much when linking
+QL = $(SUPPORT_BASE)/lib/lib
+SUPPORTLIBS= $(QL)tiff.a $(QL)jpeg.a $(QL)png.a $(QL)crypto.a $(QL)z.a \
+ $(QL)mfhdf.a $(QL)df.a $(QL)ppm.a $(QL)pgm.a $(QL)pbm.a $(LIBAKINSIDE) \
+ $(LIBAKNET)
+
+# all test programs
+ALLTESTS = test_oqlquery test_collection test_set test_iterator \
+ test_marray deletecollection \
+ test_ref test_insert test_lookup test_query test_insert3 \
+ test_breakdown test_benchmark test_storage test_alignedtiling \
+ test_dirtiling test_interesttiling test_stattiling test_bmark_dir \
+ gen_pattern test_bmark_int test_bmark_stat test_bmark_dir1 \
+ test_bmark_int1 test_gmarray test_transaction test_fastscale \
+ test_polygon exporttif defdiff defconv system_update system_compare \
+ system_insert system_query
+
+SRCCXX= defconv.cc system_compare.cc test_bmark_dir1.cc test_dirtiling.cc test_lookup.cc \
+ test_stattiling.cc defdiff.cc system_insert.cc test_bmark_int.cc test_fastscale.cc \
+ test_marray.cc test_storage.cc deletecollection.cc system_query.cc test_bmark_int1.cc \
+ test_gmarray.cc test_oqlquery.cc test_transaction.cc gen_pattern.cc system_update.cc \
+ test_bmark_pet.cc test_insert.cc test_polygon.cc rasql.cc test_alignedtiling.cc \
+ test_bmark_stat.cc test_insert3.cc test_query.cc readln.cc test_benchmark.cc \
+ test_breakdown.cc test_interesttiling.cc test_ref.cc system_basic.cc test_bmark_dir.cc \
+ test_collection.cc test_iterator.cc test_set.cc
+
+OBJS = ${SRCCXX:%.cc=%.o}
+
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+LDFLAGS+= -lsocket
+endif
+
+MISCCLEAN = $(OBJS) $(ALLTESTS)
+
+########################### Targets ##############################
+# all tests
+tests: $(ALLTESTS)
+
+# test target for class r_Collection
+# test target for class r_OQL_Query
+.PHONY : oqlquery
+oqlquery: test_module test_oqlquery
+
+# test target for class r_Collection
+.PHONY : collection
+collection: test_module test_collection
+
+# test target for class r_Set
+.PHONY : set
+set: test_module test_set
+
+# test target for class r_Iterator
+.PHONY : iterator
+iterator: test_module test_iterator
+
+# test target for class r_Marray
+.PHONY : marray
+marray: test_module test_marray
+
+# test target for class r_GMarray
+.PHONY : gmarray
+gmarray: test_module test_gmarray
+
+# test target for class r_Ref, r_Transaction
+.PHONY : ref
+ref: test_module test_ref
+
+# test target for ODMG conformant insertion of r_Marrays
+.PHONY : insert
+insert: test_module test_insert
+
+# test target for ODMG conformant lookup of r_Marrays
+.PHONY : lookup
+lookup: test_module test_lookup
+
+# test target for RasQL queries
+.PHONY : query
+query: test_module test_query
+
+# test target for test_insert3
+.PHONY : insert3
+insert3: test_module test_insert3
+
+# test target for deletecollection
+.PHONY : deletecoll
+insert3: test_module deletecollection
+
+# test target for simulation of communication breakdown
+.PHONY : breakdown
+breakdown: test_module test_breakdown
+
+# test target for RasQL benchmark
+.PHONY : benchmark
+benchmark: test_module test_benchmark
+
+# test target for storage layout
+storage: test_module test_storage test_alignedtiling test_dirtiling
+
+# test target for transactions
+transaction: test_module test_transaction
+
+.PHONY : test_module
+test_module:
+ cd $(RMANBASE)/rasodmg; $(MAKE)
+ cd $(RMANBASE)/raslib; $(MAKE)
+
+test_oqlquery: test_oqlquery.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_collection: test_collection.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_set: test_set.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_iterator: test_iterator.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_marray: test_marray.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_gmarray: test_gmarray.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_ref: test_ref.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_insert: test_insert.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_lookup: test_lookup.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_fastscale: test_fastscale.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+exporttif_static: exporttif.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o test_polygon -Xlinker -Bstatic $^ $(SUPPORTLIBS) -lstdc++
+endif
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+exporttif: exporttif.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) -nodefaultlibs $(LDFLAGS) -o $@ -Xlinker -Bstatic $^ \
+ $(SUPPORTLIBS) -lstdc++ -Xlinker -Bdynamic -lm -lgcc -lc -lgcc
+endif
+
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+test_polygon_static: test_polygon.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o test_polygon -Xlinker -Bstatic $^ \
+ $(SUPPORTLIBS) -lstdc++
+endif
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+test_polygon: test_polygon.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) -nodefaultlibs $(LDFLAGS) -o $@ -Xlinker -Bstatic $^ \
+ $(SUPPORTLIBS) -lstdc++ -Xlinker -Bdynamic -lm -lgcc -lc -lgcc
+endif
+
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+test_polygon: test_polygon.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS)
+endif
+
+test_query: test_query.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+test_query_static: test_query.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) -nodefaultlibs $(LDFLAGS) -o test_query $^ -Xlinker -Bstatic \
+ $(SUPPORTLIBS) -lstdc++ -Xlinker -Bdynamic -lgcc -lc -lgcc
+endif
+
+system_compare: system_basic.o system_compare.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lstdc++ -lm $(SUPPORTLIBS)
+else
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic $(SUPPORTLIBS)
+endif
+
+system_update: system_update.o system_basic.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) -lNCSCNet -lNCSEcw -lNCSUtil -mt
+endif
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic $(SUPPORTLIBS)
+endif
+ifeq ($(OSTYPE),$(OSTYPE_OSF1))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS)
+endif
+
+system_insert: system_insert.o system_basic.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lstdc++ -lm $(SUPPORTLIBS)
+else
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS)
+endif
+
+system_query: system_query.o system_basic.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS) -lstdc++ -lm
+else
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic $(SUPPORTLIBS)
+endif
+
+defdiff: defdiff.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic -lstdc++ -lm $(SUPPORTLIBS)
+
+defconv: defconv.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic -lstdc++ -lm $(SUPPORTLIBS)
+
+test_insert3: test_insert3.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+test_insert3_static: test_insert3.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) -nodefaultlibs $(LDFLAGS) -o test_insert3 $^ -Xlinker -Bstatic \
+ $(SUPPORTLIBS) -lstdc++ -Xlinker -Bdynamic -lgcc -lc -lgcc
+endif
+
+deletecollection: deletecollection.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_breakdown: test_breakdown.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_benchmark: test_benchmark.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_storage: test_storage.o $(DEFCLIENTLIBS) $(TOOLS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_alignedtiling: test_alignedtiling.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_dirtiling: test_dirtiling.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_interesttiling: test_interesttiling.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_stattiling: test_stattiling.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_dir: test_bmark_dir.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_dir1: test_bmark_dir1.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_int: test_bmark_int.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_int1: test_bmark_int1.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_pet: test_bmark_pet.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_stat: test_bmark_stat.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+gen_pattern: gen_pattern.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_transaction: test_transaction.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_db2blob: test_db2blob.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ -mt $^ -lm $(DB2LDFLAGS) $(SUPPORTLIBS)
+
+test_db2blob.cc: test_db2blob.sqC
+ db2 connect to sample
+ db2 prep $< bindfile OUTPUT $@
+ db2 bind test_db2blob.bnd
+ db2 connect reset
+
+.PHONY : raslib
+raslib:
+ cd $(RMANBASE)/raslib; $(MAKE)
+
+.PHONY : rasodmg
+rasodmg:
+ cd $(RMANBASE)/rasodmg; $(MAKE)
+
+.PHONY : clientcomm
+clientcomm:
+ cd $(RMANBASE)/clientcomm; $(MAKE)
+
+
+rasql: readln.o rasql.o
+ $(CXX) -o rasql $^ -L$(SUPPORT_BASE)/lib -lreadline -lcurses
+ ln -s -f $(RMANHOME)/rasodmg/test/rasql $(RMANHOME)/bin/rasql
+
+
+updatemap: updatemap.o updatemap_util.o updatemap_error.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) -lNCSCNet -lNCSEcw -lNCSUtil -mt
+endif
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic $(SUPPORTLIBS)
+endif
+ifeq ($(OSTYPE),$(OSTYPE_OSF1))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS)
+endif
+
+PHONY: clean
+clean:
+ -rm $(MISCCLEAN)
+
+######################## Dependencies ############################
+
+# automatically created dependencies
+include Makefile.dep
+
diff --git a/rasodmg/test/Makefile.dep b/rasodmg/test/Makefile.dep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/rasodmg/test/Makefile.dep
diff --git a/rasodmg/test/cmov_16.ql b/rasodmg/test/cmov_16.ql
new file mode 100644
index 0000000..47e4178
--- /dev/null
+++ b/rasodmg/test/cmov_16.ql
@@ -0,0 +1,425 @@
+// This query tests different selectivities with moving query boxes
+// on comp_cubed with 16kB tiles ([0:24,0:24,0:24]). Each selectivity
+// is repeated 20 times with query boxes of the same shape and size
+// starting at different origins.
+
+// [0.5]: [39:83, 43:87, 117:143]
+SELECT img[39:83, 43:87, 117:143]
+FROM comp_cubed_16 AS img
+// [0.5]: [146:190, 116:160, 35:61]
+SELECT img[146:190, 116:160, 35:61]
+FROM comp_cubed_16 AS img
+// [0.5]: [17:61, 42:86, 15:41]
+SELECT img[17:61, 42:86, 15:41]
+FROM comp_cubed_16 AS img
+// [0.5]: [112:156, 154:198, 108:134]
+SELECT img[112:156, 154:198, 108:134]
+FROM comp_cubed_16 AS img
+// [0.5]: [138:182, 26:70, 48:74]
+SELECT img[138:182, 26:70, 48:74]
+FROM comp_cubed_16 AS img
+// [0.5]: [53:97, 94:138, 22:48]
+SELECT img[53:97, 94:138, 22:48]
+FROM comp_cubed_16 AS img
+// [0.5]: [190:234, 59:103, 17:43]
+SELECT img[190:234, 59:103, 17:43]
+FROM comp_cubed_16 AS img
+// [0.5]: [118:162, 147:191, 30:56]
+SELECT img[118:162, 147:191, 30:56]
+FROM comp_cubed_16 AS img
+// [0.5]: [210:254, 179:223, 18:44]
+SELECT img[210:254, 179:223, 18:44]
+FROM comp_cubed_16 AS img
+// [0.5]: [129:173, 76:120, 102:128]
+SELECT img[129:173, 76:120, 102:128]
+FROM comp_cubed_16 AS img
+// [0.5]: [199:243, 119:163, 59:85]
+SELECT img[199:243, 119:163, 59:85]
+FROM comp_cubed_16 AS img
+// [0.5]: [47:91, 52:96, 108:134]
+SELECT img[47:91, 52:96, 108:134]
+FROM comp_cubed_16 AS img
+// [0.5]: [87:131, 103:147, 11:37]
+SELECT img[87:131, 103:147, 11:37]
+FROM comp_cubed_16 AS img
+// [0.5]: [32:76, 81:125, 87:113]
+SELECT img[32:76, 81:125, 87:113]
+FROM comp_cubed_16 AS img
+// [0.5]: [14:58, 77:121, 0:26]
+SELECT img[14:58, 77:121, 0:26]
+FROM comp_cubed_16 AS img
+// [0.5]: [128:172, 145:189, 21:47]
+SELECT img[128:172, 145:189, 21:47]
+FROM comp_cubed_16 AS img
+// [0.5]: [185:229, 102:146, 60:86]
+SELECT img[185:229, 102:146, 60:86]
+FROM comp_cubed_16 AS img
+// [0.5]: [40:84, 39:83, 106:132]
+SELECT img[40:84, 39:83, 106:132]
+FROM comp_cubed_16 AS img
+// [0.5]: [37:81, 10:54, 51:77]
+SELECT img[37:81, 10:54, 51:77]
+FROM comp_cubed_16 AS img
+// [0.5]: [46:90, 21:65, 102:128]
+SELECT img[46:90, 21:65, 102:128]
+FROM comp_cubed_16 AS img
+// [1]: [199:254, 50:105, 11:44]
+SELECT img[199:254, 50:105, 11:44]
+FROM comp_cubed_16 AS img
+// [1]: [180:235, 51:106, 91:124]
+SELECT img[180:235, 51:106, 91:124]
+FROM comp_cubed_16 AS img
+// [1]: [199:254, 43:98, 113:146]
+SELECT img[199:254, 43:98, 113:146]
+FROM comp_cubed_16 AS img
+// [1]: [78:133, 40:95, 37:70]
+SELECT img[78:133, 40:95, 37:70]
+FROM comp_cubed_16 AS img
+// [1]: [11:66, 98:153, 19:52]
+SELECT img[11:66, 98:153, 19:52]
+FROM comp_cubed_16 AS img
+// [1]: [90:145, 74:129, 83:116]
+SELECT img[90:145, 74:129, 83:116]
+FROM comp_cubed_16 AS img
+// [1]: [82:137, 103:158, 1:34]
+SELECT img[82:137, 103:158, 1:34]
+FROM comp_cubed_16 AS img
+// [1]: [186:241, 191:246, 47:80]
+SELECT img[186:241, 191:246, 47:80]
+FROM comp_cubed_16 AS img
+// [1]: [143:198, 68:123, 77:110]
+SELECT img[143:198, 68:123, 77:110]
+FROM comp_cubed_16 AS img
+// [1]: [188:243, 23:78, 94:127]
+SELECT img[188:243, 23:78, 94:127]
+FROM comp_cubed_16 AS img
+// [1]: [71:126, 11:66, 75:108]
+SELECT img[71:126, 11:66, 75:108]
+FROM comp_cubed_16 AS img
+// [1]: [89:144, 109:164, 12:45]
+SELECT img[89:144, 109:164, 12:45]
+FROM comp_cubed_16 AS img
+// [1]: [47:102, 56:111, 14:47]
+SELECT img[47:102, 56:111, 14:47]
+FROM comp_cubed_16 AS img
+// [1]: [24:79, 190:245, 77:110]
+SELECT img[24:79, 190:245, 77:110]
+FROM comp_cubed_16 AS img
+// [1]: [14:69, 189:244, 0:33]
+SELECT img[14:69, 189:244, 0:33]
+FROM comp_cubed_16 AS img
+// [1]: [198:253, 167:222, 117:150]
+SELECT img[198:253, 167:222, 117:150]
+FROM comp_cubed_16 AS img
+// [1]: [125:180, 1:56, 113:146]
+SELECT img[125:180, 1:56, 113:146]
+FROM comp_cubed_16 AS img
+// [1]: [90:145, 126:181, 109:142]
+SELECT img[90:145, 126:181, 109:142]
+FROM comp_cubed_16 AS img
+// [1]: [154:209, 9:64, 47:80]
+SELECT img[154:209, 9:64, 47:80]
+FROM comp_cubed_16 AS img
+// [1]: [81:136, 1:56, 87:120]
+SELECT img[81:136, 1:56, 87:120]
+FROM comp_cubed_16 AS img
+// [2]: [116:185, 1:70, 77:119]
+SELECT img[116:185, 1:70, 77:119]
+FROM comp_cubed_16 AS img
+// [2]: [99:168, 87:156, 20:62]
+SELECT img[99:168, 87:156, 20:62]
+FROM comp_cubed_16 AS img
+// [2]: [81:150, 74:143, 35:77]
+SELECT img[81:150, 74:143, 35:77]
+FROM comp_cubed_16 AS img
+// [2]: [16:85, 100:169, 56:98]
+SELECT img[16:85, 100:169, 56:98]
+FROM comp_cubed_16 AS img
+// [2]: [180:249, 47:116, 92:134]
+SELECT img[180:249, 47:116, 92:134]
+FROM comp_cubed_16 AS img
+// [2]: [78:147, 57:126, 9:51]
+SELECT img[78:147, 57:126, 9:51]
+FROM comp_cubed_16 AS img
+// [2]: [160:229, 76:145, 39:81]
+SELECT img[160:229, 76:145, 39:81]
+FROM comp_cubed_16 AS img
+// [2]: [95:164, 29:98, 26:68]
+SELECT img[95:164, 29:98, 26:68]
+FROM comp_cubed_16 AS img
+// [2]: [143:212, 120:189, 35:77]
+SELECT img[143:212, 120:189, 35:77]
+FROM comp_cubed_16 AS img
+// [2]: [163:232, 116:185, 78:120]
+SELECT img[163:232, 116:185, 78:120]
+FROM comp_cubed_16 AS img
+// [2]: [116:185, 58:127, 69:111]
+SELECT img[116:185, 58:127, 69:111]
+FROM comp_cubed_16 AS img
+// [2]: [38:107, 169:238, 0:42]
+SELECT img[38:107, 169:238, 0:42]
+FROM comp_cubed_16 AS img
+// [2]: [87:156, 112:181, 41:83]
+SELECT img[87:156, 112:181, 41:83]
+FROM comp_cubed_16 AS img
+// [2]: [14:83, 118:187, 37:79]
+SELECT img[14:83, 118:187, 37:79]
+FROM comp_cubed_16 AS img
+// [2]: [24:93, 172:241, 27:69]
+SELECT img[24:93, 172:241, 27:69]
+FROM comp_cubed_16 AS img
+// [2]: [105:174, 14:83, 21:63]
+SELECT img[105:174, 14:83, 21:63]
+FROM comp_cubed_16 AS img
+// [2]: [54:123, 92:161, 0:42]
+SELECT img[54:123, 92:161, 0:42]
+FROM comp_cubed_16 AS img
+// [2]: [151:220, 160:229, 58:100]
+SELECT img[151:220, 160:229, 58:100]
+FROM comp_cubed_16 AS img
+// [2]: [73:142, 42:111, 73:115]
+SELECT img[73:142, 42:111, 73:115]
+FROM comp_cubed_16 AS img
+// [2]: [38:107, 181:250, 25:67]
+SELECT img[38:107, 181:250, 25:67]
+FROM comp_cubed_16 AS img
+// [5]: [82:176, 43:137, 32:88]
+SELECT img[82:176, 43:137, 32:88]
+FROM comp_cubed_16 AS img
+// [5]: [114:208, 6:100, 52:108]
+SELECT img[114:208, 6:100, 52:108]
+FROM comp_cubed_16 AS img
+// [5]: [116:210, 132:226, 29:85]
+SELECT img[116:210, 132:226, 29:85]
+FROM comp_cubed_16 AS img
+// [5]: [29:123, 69:163, 53:109]
+SELECT img[29:123, 69:163, 53:109]
+FROM comp_cubed_16 AS img
+// [5]: [85:179, 1:95, 72:128]
+SELECT img[85:179, 1:95, 72:128]
+FROM comp_cubed_16 AS img
+// [5]: [80:174, 121:215, 27:83]
+SELECT img[80:174, 121:215, 27:83]
+FROM comp_cubed_16 AS img
+// [5]: [142:236, 129:223, 46:102]
+SELECT img[142:236, 129:223, 46:102]
+FROM comp_cubed_16 AS img
+// [5]: [130:224, 156:250, 82:138]
+SELECT img[130:224, 156:250, 82:138]
+FROM comp_cubed_16 AS img
+// [5]: [27:121, 111:205, 45:101]
+SELECT img[27:121, 111:205, 45:101]
+FROM comp_cubed_16 AS img
+// [5]: [139:233, 122:216, 49:105]
+SELECT img[139:233, 122:216, 49:105]
+FROM comp_cubed_16 AS img
+// [5]: [12:106, 3:97, 84:140]
+SELECT img[12:106, 3:97, 84:140]
+FROM comp_cubed_16 AS img
+// [5]: [73:167, 70:164, 1:57]
+SELECT img[73:167, 70:164, 1:57]
+FROM comp_cubed_16 AS img
+// [5]: [160:254, 1:95, 80:136]
+SELECT img[160:254, 1:95, 80:136]
+FROM comp_cubed_16 AS img
+// [5]: [152:246, 54:148, 72:128]
+SELECT img[152:246, 54:148, 72:128]
+FROM comp_cubed_16 AS img
+// [5]: [25:119, 50:144, 55:111]
+SELECT img[25:119, 50:144, 55:111]
+FROM comp_cubed_16 AS img
+// [5]: [151:245, 34:128, 92:148]
+SELECT img[151:245, 34:128, 92:148]
+FROM comp_cubed_16 AS img
+// [5]: [28:122, 68:162, 76:132]
+SELECT img[28:122, 68:162, 76:132]
+FROM comp_cubed_16 AS img
+// [5]: [145:239, 98:192, 44:100]
+SELECT img[145:239, 98:192, 44:100]
+FROM comp_cubed_16 AS img
+// [5]: [73:167, 122:216, 2:58]
+SELECT img[73:167, 122:216, 2:58]
+FROM comp_cubed_16 AS img
+// [5]: [1:95, 107:201, 68:124]
+SELECT img[1:95, 107:201, 68:124]
+FROM comp_cubed_16 AS img
+// [10]: [102:220, 43:161, 75:146]
+SELECT img[102:220, 43:161, 75:146]
+FROM comp_cubed_16 AS img
+// [10]: [106:224, 36:154, 79:150]
+SELECT img[106:224, 36:154, 79:150]
+FROM comp_cubed_16 AS img
+// [10]: [95:213, 56:174, 69:140]
+SELECT img[95:213, 56:174, 69:140]
+FROM comp_cubed_16 AS img
+// [10]: [62:180, 126:244, 74:145]
+SELECT img[62:180, 126:244, 74:145]
+FROM comp_cubed_16 AS img
+// [10]: [93:211, 63:181, 46:117]
+SELECT img[93:211, 63:181, 46:117]
+FROM comp_cubed_16 AS img
+// [10]: [129:247, 74:192, 67:138]
+SELECT img[129:247, 74:192, 67:138]
+FROM comp_cubed_16 AS img
+// [10]: [44:162, 84:202, 75:146]
+SELECT img[44:162, 84:202, 75:146]
+FROM comp_cubed_16 AS img
+// [10]: [52:170, 107:225, 19:90]
+SELECT img[52:170, 107:225, 19:90]
+FROM comp_cubed_16 AS img
+// [10]: [89:207, 94:212, 9:80]
+SELECT img[89:207, 94:212, 9:80]
+FROM comp_cubed_16 AS img
+// [10]: [52:170, 120:238, 67:138]
+SELECT img[52:170, 120:238, 67:138]
+FROM comp_cubed_16 AS img
+// [10]: [98:216, 51:169, 42:113]
+SELECT img[98:216, 51:169, 42:113]
+FROM comp_cubed_16 AS img
+// [10]: [30:148, 109:227, 51:122]
+SELECT img[30:148, 109:227, 51:122]
+FROM comp_cubed_16 AS img
+// [10]: [130:248, 118:236, 30:101]
+SELECT img[130:248, 118:236, 30:101]
+FROM comp_cubed_16 AS img
+// [10]: [25:143, 25:143, 46:117]
+SELECT img[25:143, 25:143, 46:117]
+FROM comp_cubed_16 AS img
+// [10]: [86:204, 119:237, 12:83]
+SELECT img[86:204, 119:237, 12:83]
+FROM comp_cubed_16 AS img
+// [10]: [116:234, 18:136, 11:82]
+SELECT img[116:234, 18:136, 11:82]
+FROM comp_cubed_16 AS img
+// [10]: [61:179, 24:142, 68:139]
+SELECT img[61:179, 24:142, 68:139]
+FROM comp_cubed_16 AS img
+// [10]: [53:171, 14:132, 72:143]
+SELECT img[53:171, 14:132, 72:143]
+FROM comp_cubed_16 AS img
+// [10]: [49:167, 84:202, 64:135]
+SELECT img[49:167, 84:202, 64:135]
+FROM comp_cubed_16 AS img
+// [10]: [85:203, 80:198, 13:84]
+SELECT img[85:203, 80:198, 13:84]
+FROM comp_cubed_16 AS img
+// [20]: [97:246, 85:234, 54:143]
+SELECT img[97:246, 85:234, 54:143]
+FROM comp_cubed_16 AS img
+// [20]: [63:212, 18:167, 43:132]
+SELECT img[63:212, 18:167, 43:132]
+FROM comp_cubed_16 AS img
+// [20]: [99:248, 28:177, 58:147]
+SELECT img[99:248, 28:177, 58:147]
+FROM comp_cubed_16 AS img
+// [20]: [57:206, 16:165, 46:135]
+SELECT img[57:206, 16:165, 46:135]
+FROM comp_cubed_16 AS img
+// [20]: [83:232, 93:242, 36:125]
+SELECT img[83:232, 93:242, 36:125]
+FROM comp_cubed_16 AS img
+// [20]: [57:206, 31:180, 48:137]
+SELECT img[57:206, 31:180, 48:137]
+FROM comp_cubed_16 AS img
+// [20]: [86:235, 70:219, 32:121]
+SELECT img[86:235, 70:219, 32:121]
+FROM comp_cubed_16 AS img
+// [20]: [39:188, 49:198, 50:139]
+SELECT img[39:188, 49:198, 50:139]
+FROM comp_cubed_16 AS img
+// [20]: [62:211, 104:253, 29:118]
+SELECT img[62:211, 104:253, 29:118]
+FROM comp_cubed_16 AS img
+// [20]: [103:252, 44:193, 13:102]
+SELECT img[103:252, 44:193, 13:102]
+FROM comp_cubed_16 AS img
+// [20]: [48:197, 14:163, 2:91]
+SELECT img[48:197, 14:163, 2:91]
+FROM comp_cubed_16 AS img
+// [20]: [0:149, 79:228, 13:102]
+SELECT img[0:149, 79:228, 13:102]
+FROM comp_cubed_16 AS img
+// [20]: [6:155, 103:252, 35:124]
+SELECT img[6:155, 103:252, 35:124]
+FROM comp_cubed_16 AS img
+// [20]: [0:149, 91:240, 46:135]
+SELECT img[0:149, 91:240, 46:135]
+FROM comp_cubed_16 AS img
+// [20]: [23:172, 50:199, 42:131]
+SELECT img[23:172, 50:199, 42:131]
+FROM comp_cubed_16 AS img
+// [20]: [80:229, 33:182, 17:106]
+SELECT img[80:229, 33:182, 17:106]
+FROM comp_cubed_16 AS img
+// [20]: [38:187, 41:190, 1:90]
+SELECT img[38:187, 41:190, 1:90]
+FROM comp_cubed_16 AS img
+// [20]: [42:191, 17:166, 39:128]
+SELECT img[42:191, 17:166, 39:128]
+FROM comp_cubed_16 AS img
+// [20]: [98:247, 95:244, 58:147]
+SELECT img[98:247, 95:244, 58:147]
+FROM comp_cubed_16 AS img
+// [20]: [10:159, 51:200, 21:110]
+SELECT img[10:159, 51:200, 21:110]
+FROM comp_cubed_16 AS img
+// [50]: [8:210, 13:215, 9:130]
+SELECT img[8:210, 13:215, 9:130]
+FROM comp_cubed_16 AS img
+// [50]: [48:250, 45:247, 24:145]
+SELECT img[48:250, 45:247, 24:145]
+FROM comp_cubed_16 AS img
+// [50]: [29:231, 6:208, 23:144]
+SELECT img[29:231, 6:208, 23:144]
+FROM comp_cubed_16 AS img
+// [50]: [12:214, 44:246, 23:144]
+SELECT img[12:214, 44:246, 23:144]
+FROM comp_cubed_16 AS img
+// [50]: [11:213, 27:229, 7:128]
+SELECT img[11:213, 27:229, 7:128]
+FROM comp_cubed_16 AS img
+// [50]: [1:203, 2:204, 14:135]
+SELECT img[1:203, 2:204, 14:135]
+FROM comp_cubed_16 AS img
+// [50]: [22:224, 50:252, 10:131]
+SELECT img[22:224, 50:252, 10:131]
+FROM comp_cubed_16 AS img
+// [50]: [15:217, 35:237, 9:130]
+SELECT img[15:217, 35:237, 9:130]
+FROM comp_cubed_16 AS img
+// [50]: [4:206, 51:253, 28:149]
+SELECT img[4:206, 51:253, 28:149]
+FROM comp_cubed_16 AS img
+// [50]: [22:224, 20:222, 31:152]
+SELECT img[22:224, 20:222, 31:152]
+FROM comp_cubed_16 AS img
+// [50]: [16:218, 42:244, 27:148]
+SELECT img[16:218, 42:244, 27:148]
+FROM comp_cubed_16 AS img
+// [50]: [21:223, 32:234, 22:143]
+SELECT img[21:223, 32:234, 22:143]
+FROM comp_cubed_16 AS img
+// [50]: [37:239, 44:246, 29:150]
+SELECT img[37:239, 44:246, 29:150]
+FROM comp_cubed_16 AS img
+// [50]: [17:219, 49:251, 14:135]
+SELECT img[17:219, 49:251, 14:135]
+FROM comp_cubed_16 AS img
+// [50]: [49:251, 50:252, 3:124]
+SELECT img[49:251, 50:252, 3:124]
+FROM comp_cubed_16 AS img
+// [50]: [17:219, 15:217, 1:122]
+SELECT img[17:219, 15:217, 1:122]
+FROM comp_cubed_16 AS img
+// [50]: [21:223, 51:253, 13:134]
+SELECT img[21:223, 51:253, 13:134]
+FROM comp_cubed_16 AS img
+// [50]: [7:209, 47:249, 11:132]
+SELECT img[7:209, 47:249, 11:132]
+FROM comp_cubed_16 AS img
+// [50]: [4:206, 22:224, 4:125]
+SELECT img[4:206, 22:224, 4:125]
+FROM comp_cubed_16 AS img
+// [50]: [16:218, 51:253, 21:142]
+SELECT img[16:218, 51:253, 21:142]
+FROM comp_cubed_16 AS img
diff --git a/rasodmg/test/cmov_32.ql b/rasodmg/test/cmov_32.ql
new file mode 100644
index 0000000..c6b31fe
--- /dev/null
+++ b/rasodmg/test/cmov_32.ql
@@ -0,0 +1,425 @@
+// This query tests different selectivities with moving query boxes
+// on comp_cubed with 32kB tiles ([0:31,0:31,0:31]). Each selectivity
+// is repeated 20 times with query boxes of the same shape and size
+// starting at different origins.
+
+// [0.5]: [46:90, 176:220, 60:86]
+SELECT img[46:90, 176:220, 60:86]
+FROM comp_cubed AS img
+// [0.5]: [143:187, 175:219, 106:132]
+SELECT img[143:187, 175:219, 106:132]
+FROM comp_cubed AS img
+// [0.5]: [169:213, 75:119, 66:92]
+SELECT img[169:213, 75:119, 66:92]
+FROM comp_cubed AS img
+// [0.5]: [90:134, 178:222, 48:74]
+SELECT img[90:134, 178:222, 48:74]
+FROM comp_cubed AS img
+// [0.5]: [76:120, 136:180, 31:57]
+SELECT img[76:120, 136:180, 31:57]
+FROM comp_cubed AS img
+// [0.5]: [7:51, 150:194, 89:115]
+SELECT img[7:51, 150:194, 89:115]
+FROM comp_cubed AS img
+// [0.5]: [133:177, 113:157, 0:26]
+SELECT img[133:177, 113:157, 0:26]
+FROM comp_cubed AS img
+// [0.5]: [114:158, 125:169, 108:134]
+SELECT img[114:158, 125:169, 108:134]
+FROM comp_cubed AS img
+// [0.5]: [210:254, 12:56, 56:82]
+SELECT img[210:254, 12:56, 56:82]
+FROM comp_cubed AS img
+// [0.5]: [176:220, 171:215, 83:109]
+SELECT img[176:220, 171:215, 83:109]
+FROM comp_cubed AS img
+// [0.5]: [102:146, 50:94, 34:60]
+SELECT img[102:146, 50:94, 34:60]
+FROM comp_cubed AS img
+// [0.5]: [134:178, 96:140, 97:123]
+SELECT img[134:178, 96:140, 97:123]
+FROM comp_cubed AS img
+// [0.5]: [200:244, 43:87, 123:149]
+SELECT img[200:244, 43:87, 123:149]
+FROM comp_cubed AS img
+// [0.5]: [155:199, 127:171, 48:74]
+SELECT img[155:199, 127:171, 48:74]
+FROM comp_cubed AS img
+// [0.5]: [111:155, 80:124, 11:37]
+SELECT img[111:155, 80:124, 11:37]
+FROM comp_cubed AS img
+// [0.5]: [164:208, 2:46, 64:90]
+SELECT img[164:208, 2:46, 64:90]
+FROM comp_cubed AS img
+// [0.5]: [137:181, 102:146, 17:43]
+SELECT img[137:181, 102:146, 17:43]
+FROM comp_cubed AS img
+// [0.5]: [100:144, 149:193, 121:147]
+SELECT img[100:144, 149:193, 121:147]
+FROM comp_cubed AS img
+// [0.5]: [186:230, 38:82, 108:134]
+SELECT img[186:230, 38:82, 108:134]
+FROM comp_cubed AS img
+// [0.5]: [48:92, 53:97, 14:40]
+SELECT img[48:92, 53:97, 14:40]
+FROM comp_cubed AS img
+// [1]: [64:119, 65:120, 57:90]
+SELECT img[64:119, 65:120, 57:90]
+FROM comp_cubed AS img
+// [1]: [13:68, 121:176, 20:53]
+SELECT img[13:68, 121:176, 20:53]
+FROM comp_cubed AS img
+// [1]: [3:58, 115:170, 59:92]
+SELECT img[3:58, 115:170, 59:92]
+FROM comp_cubed AS img
+// [1]: [174:229, 82:137, 93:126]
+SELECT img[174:229, 82:137, 93:126]
+FROM comp_cubed AS img
+// [1]: [40:95, 143:198, 43:76]
+SELECT img[40:95, 143:198, 43:76]
+FROM comp_cubed AS img
+// [1]: [126:181, 160:215, 86:119]
+SELECT img[126:181, 160:215, 86:119]
+FROM comp_cubed AS img
+// [1]: [20:75, 44:99, 89:122]
+SELECT img[20:75, 44:99, 89:122]
+FROM comp_cubed AS img
+// [1]: [15:70, 92:147, 23:56]
+SELECT img[15:70, 92:147, 23:56]
+FROM comp_cubed AS img
+// [1]: [122:177, 62:117, 75:108]
+SELECT img[122:177, 62:117, 75:108]
+FROM comp_cubed AS img
+// [1]: [183:238, 174:229, 70:103]
+SELECT img[183:238, 174:229, 70:103]
+FROM comp_cubed AS img
+// [1]: [13:68, 82:137, 97:130]
+SELECT img[13:68, 82:137, 97:130]
+FROM comp_cubed AS img
+// [1]: [174:229, 107:162, 91:124]
+SELECT img[174:229, 107:162, 91:124]
+FROM comp_cubed AS img
+// [1]: [79:134, 83:138, 88:121]
+SELECT img[79:134, 83:138, 88:121]
+FROM comp_cubed AS img
+// [1]: [3:58, 62:117, 39:72]
+SELECT img[3:58, 62:117, 39:72]
+FROM comp_cubed AS img
+// [1]: [96:151, 25:80, 93:126]
+SELECT img[96:151, 25:80, 93:126]
+FROM comp_cubed AS img
+// [1]: [124:179, 183:238, 21:54]
+SELECT img[124:179, 183:238, 21:54]
+FROM comp_cubed AS img
+// [1]: [106:161, 111:166, 89:122]
+SELECT img[106:161, 111:166, 89:122]
+FROM comp_cubed AS img
+// [1]: [66:121, 103:158, 74:107]
+SELECT img[66:121, 103:158, 74:107]
+FROM comp_cubed AS img
+// [1]: [180:235, 131:186, 80:113]
+SELECT img[180:235, 131:186, 80:113]
+FROM comp_cubed AS img
+// [1]: [4:59, 132:187, 59:92]
+SELECT img[4:59, 132:187, 59:92]
+FROM comp_cubed AS img
+// [2]: [69:138, 184:253, 75:117]
+SELECT img[69:138, 184:253, 75:117]
+FROM comp_cubed AS img
+// [2]: [58:127, 168:237, 87:129]
+SELECT img[58:127, 168:237, 87:129]
+FROM comp_cubed AS img
+// [2]: [162:231, 145:214, 58:100]
+SELECT img[162:231, 145:214, 58:100]
+FROM comp_cubed AS img
+// [2]: [129:198, 122:191, 7:49]
+SELECT img[129:198, 122:191, 7:49]
+FROM comp_cubed AS img
+// [2]: [86:155, 170:239, 54:96]
+SELECT img[86:155, 170:239, 54:96]
+FROM comp_cubed AS img
+// [2]: [0:69, 98:167, 70:112]
+SELECT img[0:69, 98:167, 70:112]
+FROM comp_cubed AS img
+// [2]: [41:110, 33:102, 58:100]
+SELECT img[41:110, 33:102, 58:100]
+FROM comp_cubed AS img
+// [2]: [37:106, 24:93, 65:107]
+SELECT img[37:106, 24:93, 65:107]
+FROM comp_cubed AS img
+// [2]: [39:108, 114:183, 26:68]
+SELECT img[39:108, 114:183, 26:68]
+FROM comp_cubed AS img
+// [2]: [166:235, 9:78, 38:80]
+SELECT img[166:235, 9:78, 38:80]
+FROM comp_cubed AS img
+// [2]: [147:216, 174:243, 45:87]
+SELECT img[147:216, 174:243, 45:87]
+FROM comp_cubed AS img
+// [2]: [121:190, 69:138, 58:100]
+SELECT img[121:190, 69:138, 58:100]
+FROM comp_cubed AS img
+// [2]: [87:156, 78:147, 73:115]
+SELECT img[87:156, 78:147, 73:115]
+FROM comp_cubed AS img
+// [2]: [31:100, 109:178, 75:117]
+SELECT img[31:100, 109:178, 75:117]
+FROM comp_cubed AS img
+// [2]: [54:123, 155:224, 26:68]
+SELECT img[54:123, 155:224, 26:68]
+FROM comp_cubed AS img
+// [2]: [150:219, 139:208, 25:67]
+SELECT img[150:219, 139:208, 25:67]
+FROM comp_cubed AS img
+// [2]: [65:134, 119:188, 87:129]
+SELECT img[65:134, 119:188, 87:129]
+FROM comp_cubed AS img
+// [2]: [159:228, 45:114, 47:89]
+SELECT img[159:228, 45:114, 47:89]
+FROM comp_cubed AS img
+// [2]: [77:146, 60:129, 87:129]
+SELECT img[77:146, 60:129, 87:129]
+FROM comp_cubed AS img
+// [2]: [169:238, 135:204, 4:46]
+SELECT img[169:238, 135:204, 4:46]
+FROM comp_cubed AS img
+// [5]: [24:118, 61:155, 77:133]
+SELECT img[24:118, 61:155, 77:133]
+FROM comp_cubed AS img
+// [5]: [137:231, 119:213, 11:67]
+SELECT img[137:231, 119:213, 11:67]
+FROM comp_cubed AS img
+// [5]: [140:234, 131:225, 56:112]
+SELECT img[140:234, 131:225, 56:112]
+FROM comp_cubed AS img
+// [5]: [154:248, 6:100, 54:110]
+SELECT img[154:248, 6:100, 54:110]
+FROM comp_cubed AS img
+// [5]: [146:240, 62:156, 60:116]
+SELECT img[146:240, 62:156, 60:116]
+FROM comp_cubed AS img
+// [5]: [78:172, 21:115, 3:59]
+SELECT img[78:172, 21:115, 3:59]
+FROM comp_cubed AS img
+// [5]: [80:174, 33:127, 84:140]
+SELECT img[80:174, 33:127, 84:140]
+FROM comp_cubed AS img
+// [5]: [138:232, 95:189, 52:108]
+SELECT img[138:232, 95:189, 52:108]
+FROM comp_cubed AS img
+// [5]: [60:154, 136:230, 70:126]
+SELECT img[60:154, 136:230, 70:126]
+FROM comp_cubed AS img
+// [5]: [79:173, 149:243, 65:121]
+SELECT img[79:173, 149:243, 65:121]
+FROM comp_cubed AS img
+// [5]: [13:107, 53:147, 57:113]
+SELECT img[13:107, 53:147, 57:113]
+FROM comp_cubed AS img
+// [5]: [13:107, 66:160, 44:100]
+SELECT img[13:107, 66:160, 44:100]
+FROM comp_cubed AS img
+// [5]: [137:231, 47:141, 38:94]
+SELECT img[137:231, 47:141, 38:94]
+FROM comp_cubed AS img
+// [5]: [11:105, 84:178, 42:98]
+SELECT img[11:105, 84:178, 42:98]
+FROM comp_cubed AS img
+// [5]: [19:113, 31:125, 51:107]
+SELECT img[19:113, 31:125, 51:107]
+FROM comp_cubed AS img
+// [5]: [27:121, 17:111, 29:85]
+SELECT img[27:121, 17:111, 29:85]
+FROM comp_cubed AS img
+// [5]: [142:236, 76:170, 94:150]
+SELECT img[142:236, 76:170, 94:150]
+FROM comp_cubed AS img
+// [5]: [153:247, 71:165, 83:139]
+SELECT img[153:247, 71:165, 83:139]
+FROM comp_cubed AS img
+// [5]: [12:106, 108:202, 79:135]
+SELECT img[12:106, 108:202, 79:135]
+FROM comp_cubed AS img
+// [5]: [146:240, 26:120, 59:115]
+SELECT img[146:240, 26:120, 59:115]
+FROM comp_cubed AS img
+// 1[0]: [3:121, 62:180, 39:110]
+SELECT img[3:121, 62:180, 39:110]
+FROM comp_cubed AS img
+// 1[0]: [11:129, 26:144, 19:90]
+SELECT img[11:129, 26:144, 19:90]
+FROM comp_cubed AS img
+// 1[0]: [49:167, 76:194, 77:148]
+SELECT img[49:167, 76:194, 77:148]
+FROM comp_cubed AS img
+// [10]: [55:173, 86:204, 21:92]
+SELECT img[55:173, 86:204, 21:92]
+FROM comp_cubed AS img
+// [10]: [110:228, 98:216, 80:151]
+SELECT img[110:228, 98:216, 80:151]
+FROM comp_cubed AS img
+// [10]: [123:241, 28:146, 59:130]
+SELECT img[123:241, 28:146, 59:130]
+FROM comp_cubed AS img
+// [10]: [89:207, 90:208, 34:105]
+SELECT img[89:207, 90:208, 34:105]
+FROM comp_cubed AS img
+// [10]: [111:229, 51:169, 5:76]
+SELECT img[111:229, 51:169, 5:76]
+FROM comp_cubed AS img
+// [10]: [15:133, 74:192, 12:83]
+SELECT img[15:133, 74:192, 12:83]
+FROM comp_cubed AS img
+// [10]: [103:221, 94:212, 74:145]
+SELECT img[103:221, 94:212, 74:145]
+FROM comp_cubed AS img
+// [10]: [107:225, 111:229, 16:87]
+SELECT img[107:225, 111:229, 16:87]
+FROM comp_cubed AS img
+// [10]: [14:132, 80:198, 58:129]
+SELECT img[14:132, 80:198, 58:129]
+FROM comp_cubed AS img
+// [10]: [2:120, 64:182, 25:96]
+SELECT img[2:120, 64:182, 25:96]
+FROM comp_cubed AS img
+// [10]: [74:192, 130:248, 3:74]
+SELECT img[74:192, 130:248, 3:74]
+FROM comp_cubed AS img
+// [10]: [96:214, 61:179, 14:85]
+SELECT img[96:214, 61:179, 14:85]
+FROM comp_cubed AS img
+// [10]: [73:191, 93:211, 6:77]
+SELECT img[73:191, 93:211, 6:77]
+FROM comp_cubed AS img
+// [10]: [55:173, 12:130, 54:125]
+SELECT img[55:173, 12:130, 54:125]
+FROM comp_cubed AS img
+// [10]: [1:119, 123:241, 51:122]
+SELECT img[1:119, 123:241, 51:122]
+FROM comp_cubed AS img
+// [10]: [117:235, 101:219, 55:126]
+SELECT img[117:235, 101:219, 55:126]
+FROM comp_cubed AS img
+// [10]: [24:142, 26:144, 33:104]
+SELECT img[24:142, 26:144, 33:104]
+FROM comp_cubed AS img
+// [20]: [36:185, 0:149, 39:128]
+SELECT img[36:185, 0:149, 39:128]
+FROM comp_cubed AS img
+// [20]: [85:234, 31:180, 54:143]
+SELECT img[85:234, 31:180, 54:143]
+FROM comp_cubed AS img
+// [20]: [55:204, 78:227, 20:109]
+SELECT img[55:204, 78:227, 20:109]
+FROM comp_cubed AS img
+// [20]: [28:177, 98:247, 26:115]
+SELECT img[28:177, 98:247, 26:115]
+FROM comp_cubed AS img
+// [20]: [53:202, 14:163, 15:104]
+SELECT img[53:202, 14:163, 15:104]
+FROM comp_cubed AS img
+// [20]: [84:233, 59:208, 28:117]
+SELECT img[84:233, 59:208, 28:117]
+FROM comp_cubed AS img
+// [20]: [24:173, 81:230, 21:110]
+SELECT img[24:173, 81:230, 21:110]
+FROM comp_cubed AS img
+// [20]: [70:219, 103:252, 59:148]
+SELECT img[70:219, 103:252, 59:148]
+FROM comp_cubed AS img
+// [20]: [75:224, 32:181, 36:125]
+SELECT img[75:224, 32:181, 36:125]
+FROM comp_cubed AS img
+// [20]: [80:229, 65:214, 22:111]
+SELECT img[80:229, 65:214, 22:111]
+FROM comp_cubed AS img
+// [20]: [5:154, 34:183, 20:109]
+SELECT img[5:154, 34:183, 20:109]
+FROM comp_cubed AS img
+// [20]: [16:165, 72:221, 57:146]
+SELECT img[16:165, 72:221, 57:146]
+FROM comp_cubed AS img
+// [20]: [90:239, 27:176, 55:144]
+SELECT img[90:239, 27:176, 55:144]
+FROM comp_cubed AS img
+// [20]: [81:230, 63:212, 61:150]
+SELECT img[81:230, 63:212, 61:150]
+FROM comp_cubed AS img
+// [20]: [87:236, 79:228, 61:150]
+SELECT img[87:236, 79:228, 61:150]
+FROM comp_cubed AS img
+// [20]: [100:249, 33:182, 35:124]
+SELECT img[100:249, 33:182, 35:124]
+FROM comp_cubed AS img
+// [20]: [14:163, 91:240, 38:127]
+SELECT img[14:163, 91:240, 38:127]
+FROM comp_cubed AS img
+// [20]: [60:209, 95:244, 11:100]
+SELECT img[60:209, 95:244, 11:100]
+FROM comp_cubed AS img
+// [20]: [99:248, 4:153, 29:118]
+SELECT img[99:248, 4:153, 29:118]
+FROM comp_cubed AS img
+// [20]: [10:159, 64:213, 32:121]
+SELECT img[10:159, 64:213, 32:121]
+FROM comp_cubed AS img
+// [50]: [8:210, 0:202, 1:122]
+SELECT img[8:210, 0:202, 1:122]
+FROM comp_cubed AS img
+// [50]: [17:219, 21:223, 6:127]
+SELECT img[17:219, 21:223, 6:127]
+FROM comp_cubed AS img
+// [50]: [49:251, 0:202, 4:125]
+SELECT img[49:251, 0:202, 4:125]
+FROM comp_cubed AS img
+// [50]: [11:213, 37:239, 15:136]
+SELECT img[11:213, 37:239, 15:136]
+FROM comp_cubed AS img
+// [50]: [29:231, 36:238, 18:139]
+SELECT img[29:231, 36:238, 18:139]
+FROM comp_cubed AS img
+// [50]: [38:240, 21:223, 2:123]
+SELECT img[38:240, 21:223, 2:123]
+FROM comp_cubed AS img
+// [50]: [26:228, 4:206, 9:130]
+SELECT img[26:228, 4:206, 9:130]
+FROM comp_cubed AS img
+// [50]: [1:203, 41:243, 21:142]
+SELECT img[1:203, 41:243, 21:142]
+FROM comp_cubed AS img
+// [50]: [39:241, 37:239, 10:131]
+SELECT img[39:241, 37:239, 10:131]
+FROM comp_cubed AS img
+// [50]: [6:208, 49:251, 2:123]
+SELECT img[6:208, 49:251, 2:123]
+FROM comp_cubed AS img
+// [50]: [2:204, 51:253, 8:129]
+SELECT img[2:204, 51:253, 8:129]
+FROM comp_cubed AS img
+// [50]: [23:225, 51:253, 9:130]
+SELECT img[23:225, 51:253, 9:130]
+FROM comp_cubed AS img
+// [50]: [32:234, 43:245, 10:131]
+SELECT img[32:234, 43:245, 10:131]
+FROM comp_cubed AS img
+// [50]: [33:235, 9:211, 31:152]
+SELECT img[33:235, 9:211, 31:152]
+FROM comp_cubed AS img
+// [50]: [28:230, 36:238, 4:125]
+SELECT img[28:230, 36:238, 4:125]
+FROM comp_cubed AS img
+// [50]: [25:227, 40:242, 3:124]
+SELECT img[25:227, 40:242, 3:124]
+FROM comp_cubed AS img
+// [50]: [33:235, 28:230, 25:146]
+SELECT img[33:235, 28:230, 25:146]
+FROM comp_cubed AS img
+// [50]: [42:244, 34:236, 1:122]
+SELECT img[42:244, 34:236, 1:122]
+FROM comp_cubed AS img
+// [50]: [34:236, 47:249, 6:127]
+SELECT img[34:236, 47:249, 6:127]
+FROM comp_cubed AS img
+// [50]: [35:237, 22:224, 31:152]
+SELECT img[35:237, 22:224, 31:152]
+FROM comp_cubed AS img
diff --git a/rasodmg/test/cmov_64.ql b/rasodmg/test/cmov_64.ql
new file mode 100644
index 0000000..4cb19ff
--- /dev/null
+++ b/rasodmg/test/cmov_64.ql
@@ -0,0 +1,425 @@
+// This query tests different selectivities with moving query boxes
+// on comp_cubed with 64kB tiles ([0:39,0:39,0:39]). Each selectivity
+// is repeated 20 times with query boxes of the same shape and size
+// starting at different origins.
+
+// [0.5]: [205:249, 154:198, 39:65]
+SELECT img[205:249, 154:198, 39:65]
+FROM comp_cubed_64 AS img
+// [0.5]: [125:169, 124:168, 15:41]
+SELECT img[125:169, 124:168, 15:41]
+FROM comp_cubed_64 AS img
+// [0.5]: [197:241, 71:115, 82:108]
+SELECT img[197:241, 71:115, 82:108]
+FROM comp_cubed_64 AS img
+// [0.5]: [53:97, 192:236, 122:148]
+SELECT img[53:97, 192:236, 122:148]
+FROM comp_cubed_64 AS img
+// [0.5]: [140:184, 93:137, 121:147]
+SELECT img[140:184, 93:137, 121:147]
+FROM comp_cubed_64 AS img
+// [0.5]: [154:198, 82:126, 120:146]
+SELECT img[154:198, 82:126, 120:146]
+FROM comp_cubed_64 AS img
+// [0.5]: [209:253, 51:95, 47:73]
+SELECT img[209:253, 51:95, 47:73]
+FROM comp_cubed_64 AS img
+// [0.5]: [57:101, 159:203, 113:139]
+SELECT img[57:101, 159:203, 113:139]
+FROM comp_cubed_64 AS img
+// [0.5]: [98:142, 166:210, 12:38]
+SELECT img[98:142, 166:210, 12:38]
+FROM comp_cubed_64 AS img
+// [0.5]: [194:238, 88:132, 52:78]
+SELECT img[194:238, 88:132, 52:78]
+FROM comp_cubed_64 AS img
+// [0.5]: [162:206, 101:145, 53:79]
+SELECT img[162:206, 101:145, 53:79]
+FROM comp_cubed_64 AS img
+// [0.5]: [166:210, 60:104, 126:152]
+SELECT img[166:210, 60:104, 126:152]
+FROM comp_cubed_64 AS img
+// [0.5]: [127:171, 157:201, 92:118]
+SELECT img[127:171, 157:201, 92:118]
+FROM comp_cubed_64 AS img
+// [0.5]: [46:90, 94:138, 53:79]
+SELECT img[46:90, 94:138, 53:79]
+FROM comp_cubed_64 AS img
+// [0.5]: [19:63, 42:86, 17:43]
+SELECT img[19:63, 42:86, 17:43]
+FROM comp_cubed_64 AS img
+// [0.5]: [182:226, 0:44, 97:123]
+SELECT img[182:226, 0:44, 97:123]
+FROM comp_cubed_64 AS img
+// [0.5]: [139:183, 98:142, 47:73]
+SELECT img[139:183, 98:142, 47:73]
+FROM comp_cubed_64 AS img
+// [0.5]: [106:150, 182:226, 11:37]
+SELECT img[106:150, 182:226, 11:37]
+FROM comp_cubed_64 AS img
+// [0.5]: [193:237, 200:244, 23:49]
+SELECT img[193:237, 200:244, 23:49]
+FROM comp_cubed_64 AS img
+// [0.5]: [40:84, 2:46, 5:31]
+SELECT img[40:84, 2:46, 5:31]
+FROM comp_cubed_64 AS img
+// [1]: [51:106, 169:224, 105:138]
+SELECT img[51:106, 169:224, 105:138]
+FROM comp_cubed_64 AS img
+// [1]: [72:127, 30:85, 113:146]
+SELECT img[72:127, 30:85, 113:146]
+FROM comp_cubed_64 AS img
+// [1]: [104:159, 82:137, 48:81]
+SELECT img[104:159, 82:137, 48:81]
+FROM comp_cubed_64 AS img
+// [1]: [91:146, 86:141, 40:73]
+SELECT img[91:146, 86:141, 40:73]
+FROM comp_cubed_64 AS img
+// [1]: [121:176, 19:74, 59:92]
+SELECT img[121:176, 19:74, 59:92]
+FROM comp_cubed_64 AS img
+// [1]: [69:124, 156:211, 27:60]
+SELECT img[69:124, 156:211, 27:60]
+FROM comp_cubed_64 AS img
+// [1]: [24:79, 64:119, 25:58]
+SELECT img[24:79, 64:119, 25:58]
+FROM comp_cubed_64 AS img
+// [1]: [70:125, 193:248, 90:123]
+SELECT img[70:125, 193:248, 90:123]
+FROM comp_cubed_64 AS img
+// [1]: [193:248, 1:56, 38:71]
+SELECT img[193:248, 1:56, 38:71]
+FROM comp_cubed_64 AS img
+// [1]: [118:173, 178:233, 56:89]
+SELECT img[118:173, 178:233, 56:89]
+FROM comp_cubed_64 AS img
+// [1]: [118:173, 23:78, 21:54]
+SELECT img[118:173, 23:78, 21:54]
+FROM comp_cubed_64 AS img
+// [1]: [9:64, 166:221, 44:77]
+SELECT img[9:64, 166:221, 44:77]
+FROM comp_cubed_64 AS img
+// [1]: [66:121, 65:120, 93:126]
+SELECT img[66:121, 65:120, 93:126]
+FROM comp_cubed_64 AS img
+// [1]: [63:118, 141:196, 31:64]
+SELECT img[63:118, 141:196, 31:64]
+FROM comp_cubed_64 AS img
+// [1]: [89:144, 58:113, 39:72]
+SELECT img[89:144, 58:113, 39:72]
+FROM comp_cubed_64 AS img
+// [1]: [72:127, 124:179, 93:126]
+SELECT img[72:127, 124:179, 93:126]
+FROM comp_cubed_64 AS img
+// [1]: [46:101, 178:233, 41:74]
+SELECT img[46:101, 178:233, 41:74]
+FROM comp_cubed_64 AS img
+// [1]: [52:107, 10:65, 49:82]
+SELECT img[52:107, 10:65, 49:82]
+FROM comp_cubed_64 AS img
+// [1]: [151:206, 5:60, 1:34]
+SELECT img[151:206, 5:60, 1:34]
+FROM comp_cubed_64 AS img
+// [1]: [95:150, 71:126, 85:118]
+SELECT img[95:150, 71:126, 85:118]
+FROM comp_cubed_64 AS img
+// [2]: [31:100, 166:235, 7:49]
+SELECT img[31:100, 166:235, 7:49]
+FROM comp_cubed_64 AS img
+// [2]: [109:178, 174:243, 31:73]
+SELECT img[109:178, 174:243, 31:73]
+FROM comp_cubed_64 AS img
+// [2]: [24:93, 32:101, 91:133]
+SELECT img[24:93, 32:101, 91:133]
+FROM comp_cubed_64 AS img
+// [2]: [76:145, 52:121, 33:75]
+SELECT img[76:145, 52:121, 33:75]
+FROM comp_cubed_64 AS img
+// [2]: [82:151, 5:74, 17:59]
+SELECT img[82:151, 5:74, 17:59]
+FROM comp_cubed_64 AS img
+// [2]: [48:117, 100:169, 72:114]
+SELECT img[48:117, 100:169, 72:114]
+FROM comp_cubed_64 AS img
+// [2]: [81:150, 183:252, 39:81]
+SELECT img[81:150, 183:252, 39:81]
+FROM comp_cubed_64 AS img
+// [2]: [8:77, 122:191, 5:47]
+SELECT img[8:77, 122:191, 5:47]
+FROM comp_cubed_64 AS img
+// [2]: [170:239, 145:214, 23:65]
+SELECT img[170:239, 145:214, 23:65]
+FROM comp_cubed_64 AS img
+// [2]: [84:153, 101:170, 86:128]
+SELECT img[84:153, 101:170, 86:128]
+FROM comp_cubed_64 AS img
+// [2]: [72:141, 147:216, 32:74]
+SELECT img[72:141, 147:216, 32:74]
+FROM comp_cubed_64 AS img
+// [2]: [12:81, 25:94, 108:150]
+SELECT img[12:81, 25:94, 108:150]
+FROM comp_cubed_64 AS img
+// [2]: [94:163, 125:194, 29:71]
+SELECT img[94:163, 125:194, 29:71]
+FROM comp_cubed_64 AS img
+// [2]: [4:73, 44:113, 0:42]
+SELECT img[4:73, 44:113, 0:42]
+FROM comp_cubed_64 AS img
+// [2]: [134:203, 7:76, 85:127]
+SELECT img[134:203, 7:76, 85:127]
+FROM comp_cubed_64 AS img
+// [2]: [84:153, 168:237, 3:45]
+SELECT img[84:153, 168:237, 3:45]
+FROM comp_cubed_64 AS img
+// [2]: [166:235, 140:209, 41:83]
+SELECT img[166:235, 140:209, 41:83]
+FROM comp_cubed_64 AS img
+// [2]: [98:167, 43:112, 81:123]
+SELECT img[98:167, 43:112, 81:123]
+FROM comp_cubed_64 AS img
+// [2]: [5:74, 137:206, 29:71]
+SELECT img[5:74, 137:206, 29:71]
+FROM comp_cubed_64 AS img
+// [2]: [177:246, 45:114, 28:70]
+SELECT img[177:246, 45:114, 28:70]
+FROM comp_cubed_64 AS img
+// [5]: [52:146, 5:99, 72:128]
+SELECT img[52:146, 5:99, 72:128]
+FROM comp_cubed_64 AS img
+// [5]: [147:241, 45:139, 90:146]
+SELECT img[147:241, 45:139, 90:146]
+FROM comp_cubed_64 AS img
+// [5]: [156:250, 145:239, 7:63]
+SELECT img[156:250, 145:239, 7:63]
+FROM comp_cubed_64 AS img
+// [5]: [30:124, 108:202, 74:130]
+SELECT img[30:124, 108:202, 74:130]
+FROM comp_cubed_64 AS img
+// [5]: [140:234, 44:138, 25:81]
+SELECT img[140:234, 44:138, 25:81]
+FROM comp_cubed_64 AS img
+// [5]: [48:142, 9:103, 8:64]
+SELECT img[48:142, 9:103, 8:64]
+FROM comp_cubed_64 AS img
+// [5]: [0:94, 157:251, 73:129]
+SELECT img[0:94, 157:251, 73:129]
+FROM comp_cubed_64 AS img
+// [5]: [125:219, 53:147, 7:63]
+SELECT img[125:219, 53:147, 7:63]
+FROM comp_cubed_64 AS img
+// [5]: [26:120, 133:227, 38:94]
+SELECT img[26:120, 133:227, 38:94]
+FROM comp_cubed_64 AS img
+// [5]: [157:251, 41:135, 74:130]
+SELECT img[157:251, 41:135, 74:130]
+FROM comp_cubed_64 AS img
+// [5]: [41:135, 120:214, 31:87]
+SELECT img[41:135, 120:214, 31:87]
+FROM comp_cubed_64 AS img
+// [5]: [33:127, 116:210, 71:127]
+SELECT img[33:127, 116:210, 71:127]
+FROM comp_cubed_64 AS img
+// [5]: [138:232, 127:221, 20:76]
+SELECT img[138:232, 127:221, 20:76]
+FROM comp_cubed_64 AS img
+// [5]: [13:107, 9:103, 60:116]
+SELECT img[13:107, 9:103, 60:116]
+FROM comp_cubed_64 AS img
+// [5]: [124:218, 139:233, 74:130]
+SELECT img[124:218, 139:233, 74:130]
+FROM comp_cubed_64 AS img
+// [5]: [117:211, 86:180, 91:147]
+SELECT img[117:211, 86:180, 91:147]
+FROM comp_cubed_64 AS img
+// [5]: [143:237, 52:146, 71:127]
+SELECT img[143:237, 52:146, 71:127]
+FROM comp_cubed_64 AS img
+// [5]: [10:104, 35:129, 19:75]
+SELECT img[10:104, 35:129, 19:75]
+FROM comp_cubed_64 AS img
+// [5]: [110:204, 64:158, 64:120]
+SELECT img[110:204, 64:158, 64:120]
+FROM comp_cubed_64 AS img
+// [5]: [12:106, 103:197, 96:152]
+SELECT img[12:106, 103:197, 96:152]
+FROM comp_cubed_64 AS img
+// [10]: [108:226, 53:171, 9:80]
+SELECT img[108:226, 53:171, 9:80]
+FROM comp_cubed_64 AS img
+// [10]: [46:164, 103:221, 10:81]
+SELECT img[46:164, 103:221, 10:81]
+FROM comp_cubed_64 AS img
+// [10]: [80:198, 73:191, 38:109]
+SELECT img[80:198, 73:191, 38:109]
+FROM comp_cubed_64 AS img
+// [10]: [38:156, 132:250, 26:97]
+SELECT img[38:156, 132:250, 26:97]
+FROM comp_cubed_64 AS img
+// [10]: [11:129, 86:204, 77:148]
+SELECT img[11:129, 86:204, 77:148]
+FROM comp_cubed_64 AS img
+// [10]: [46:164, 90:208, 17:88]
+SELECT img[46:164, 90:208, 17:88]
+FROM comp_cubed_64 AS img
+// [10]: [86:204, 125:243, 6:77]
+SELECT img[86:204, 125:243, 6:77]
+FROM comp_cubed_64 AS img
+// [10]: [54:172, 49:167, 69:140]
+SELECT img[54:172, 49:167, 69:140]
+FROM comp_cubed_64 AS img
+// [10]: [11:129, 111:229, 23:94]
+SELECT img[11:129, 111:229, 23:94]
+FROM comp_cubed_64 AS img
+// [10]: [46:164, 66:184, 2:73]
+SELECT img[46:164, 66:184, 2:73]
+FROM comp_cubed_64 AS img
+// [10]: [88:206, 88:206, 39:110]
+SELECT img[88:206, 88:206, 39:110]
+FROM comp_cubed_64 AS img
+// [10]: [46:164, 22:140, 43:114]
+SELECT img[46:164, 22:140, 43:114]
+FROM comp_cubed_64 AS img
+// [10]: [4:122, 59:177, 47:118]
+SELECT img[4:122, 59:177, 47:118]
+FROM comp_cubed_64 AS img
+// [10]: [22:140, 37:155, 31:102]
+SELECT img[22:140, 37:155, 31:102]
+FROM comp_cubed_64 AS img
+// [10]: [109:227, 71:189, 81:152]
+SELECT img[109:227, 71:189, 81:152]
+FROM comp_cubed_64 AS img
+// [10]: [96:214, 76:194, 67:138]
+SELECT img[96:214, 76:194, 67:138]
+FROM comp_cubed_64 AS img
+// [10]: [4:122, 126:244, 10:81]
+SELECT img[4:122, 126:244, 10:81]
+FROM comp_cubed_64 AS img
+// [10]: [38:156, 90:208, 31:102]
+SELECT img[38:156, 90:208, 31:102]
+FROM comp_cubed_64 AS img
+// [10]: [12:130, 67:185, 70:141]
+SELECT img[12:130, 67:185, 70:141]
+FROM comp_cubed_64 AS img
+// [10]: [108:226, 59:177, 70:141]
+SELECT img[108:226, 59:177, 70:141]
+FROM comp_cubed_64 AS img
+// [20]: [60:209, 12:161, 15:104]
+SELECT img[60:209, 12:161, 15:104]
+FROM comp_cubed_64 AS img
+// [20]: [36:185, 68:217, 31:120]
+SELECT img[36:185, 68:217, 31:120]
+FROM comp_cubed_64 AS img
+// [20]: [19:168, 96:245, 50:139]
+SELECT img[19:168, 96:245, 50:139]
+FROM comp_cubed_64 AS img
+// [20]: [68:217, 96:245, 4:93]
+SELECT img[68:217, 96:245, 4:93]
+FROM comp_cubed_64 AS img
+// [20]: [16:165, 44:193, 49:138]
+SELECT img[16:165, 44:193, 49:138]
+FROM comp_cubed_64 AS img
+// [20]: [71:220, 91:240, 11:100]
+SELECT img[71:220, 91:240, 11:100]
+FROM comp_cubed_64 AS img
+// [20]: [96:245, 58:207, 4:93]
+SELECT img[96:245, 58:207, 4:93]
+FROM comp_cubed_64 AS img
+// [20]: [40:189, 6:155, 11:100]
+SELECT img[40:189, 6:155, 11:100]
+FROM comp_cubed_64 AS img
+// [20]: [91:240, 22:171, 7:96]
+SELECT img[91:240, 22:171, 7:96]
+FROM comp_cubed_64 AS img
+// [20]: [79:228, 85:234, 39:128]
+SELECT img[79:228, 85:234, 39:128]
+FROM comp_cubed_64 AS img
+// [20]: [97:246, 104:253, 6:95]
+SELECT img[97:246, 104:253, 6:95]
+FROM comp_cubed_64 AS img
+// [20]: [62:211, 26:175, 7:96]
+SELECT img[62:211, 26:175, 7:96]
+FROM comp_cubed_64 AS img
+// [20]: [35:184, 5:154, 29:118]
+SELECT img[35:184, 5:154, 29:118]
+FROM comp_cubed_64 AS img
+// [20]: [20:169, 92:241, 5:94]
+SELECT img[20:169, 92:241, 5:94]
+FROM comp_cubed_64 AS img
+// [20]: [77:226, 33:182, 45:134]
+SELECT img[77:226, 33:182, 45:134]
+FROM comp_cubed_64 AS img
+// [20]: [6:155, 40:189, 55:144]
+SELECT img[6:155, 40:189, 55:144]
+FROM comp_cubed_64 AS img
+// [20]: [102:251, 25:174, 20:109]
+SELECT img[102:251, 25:174, 20:109]
+FROM comp_cubed_64 AS img
+// [20]: [35:184, 70:219, 31:120]
+SELECT img[35:184, 70:219, 31:120]
+FROM comp_cubed_64 AS img
+// [20]: [99:248, 88:237, 10:99]
+SELECT img[99:248, 88:237, 10:99]
+FROM comp_cubed_64 AS img
+// [20]: [67:216, 63:212, 60:149]
+SELECT img[67:216, 63:212, 60:149]
+FROM comp_cubed_64 AS img
+// [50]: [46:248, 7:209, 31:152]
+SELECT img[46:248, 7:209, 31:152]
+FROM comp_cubed_64 AS img
+// [50]: [45:247, 24:226, 17:138]
+SELECT img[45:247, 24:226, 17:138]
+FROM comp_cubed_64 AS img
+// [50]: [22:224, 30:232, 9:130]
+SELECT img[22:224, 30:232, 9:130]
+FROM comp_cubed_64 AS img
+// [50]: [29:231, 39:241, 4:125]
+SELECT img[29:231, 39:241, 4:125]
+FROM comp_cubed_64 AS img
+// [50]: [19:221, 51:253, 6:127]
+SELECT img[19:221, 51:253, 6:127]
+FROM comp_cubed_64 AS img
+// [50]: [27:229, 14:216, 10:131]
+SELECT img[27:229, 14:216, 10:131]
+FROM comp_cubed_64 AS img
+// [50]: [33:235, 15:217, 26:147]
+SELECT img[33:235, 15:217, 26:147]
+FROM comp_cubed_64 AS img
+// [50]: [48:250, 1:203, 18:139]
+SELECT img[48:250, 1:203, 18:139]
+FROM comp_cubed_64 AS img
+// [50]: [24:226, 23:225, 23:144]
+SELECT img[24:226, 23:225, 23:144]
+FROM comp_cubed_64 AS img
+// [50]: [31:233, 12:214, 8:129]
+SELECT img[31:233, 12:214, 8:129]
+FROM comp_cubed_64 AS img
+// [50]: [34:236, 1:203, 24:145]
+SELECT img[34:236, 1:203, 24:145]
+FROM comp_cubed_64 AS img
+// [50]: [27:229, 17:219, 22:143]
+SELECT img[27:229, 17:219, 22:143]
+FROM comp_cubed_64 AS img
+// [50]: [15:217, 50:252, 16:137]
+SELECT img[15:217, 50:252, 16:137]
+FROM comp_cubed_64 AS img
+// [50]: [49:251, 3:205, 29:150]
+SELECT img[49:251, 3:205, 29:150]
+FROM comp_cubed_64 AS img
+// [50]: [11:213, 33:235, 17:138]
+SELECT img[11:213, 33:235, 17:138]
+FROM comp_cubed_64 AS img
+// [50]: [15:217, 23:225, 29:150]
+SELECT img[15:217, 23:225, 29:150]
+FROM comp_cubed_64 AS img
+// [50]: [46:248, 28:230, 30:151]
+SELECT img[46:248, 28:230, 30:151]
+FROM comp_cubed_64 AS img
+// [50]: [11:213, 6:208, 1:122]
+SELECT img[11:213, 6:208, 1:122]
+FROM comp_cubed_64 AS img
+// [50]: [13:215, 16:218, 24:145]
+SELECT img[13:215, 16:218, 24:145]
+FROM comp_cubed_64 AS img
+// [50]: [44:246, 46:248, 28:149]
+SELECT img[44:246, 46:248, 28:149]
+FROM comp_cubed_64 AS img
diff --git a/rasodmg/test/croll_16.ql b/rasodmg/test/croll_16.ql
new file mode 100644
index 0000000..8e37740
--- /dev/null
+++ b/rasodmg/test/croll_16.ql
@@ -0,0 +1,180 @@
+// ["x"] comp_cubed_16 [232:238,*:*,*:*]
+SELECT img[232,*:*,*:*]+img[233,*:*,*:*]+img[234,*:*,*:*]+img[235,*:*,*:*]+img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [179:185,*:*,*:*]
+SELECT img[179,*:*,*:*]+img[180,*:*,*:*]+img[181,*:*,*:*]+img[182,*:*,*:*]+img[183,*:*,*:*]+img[184,*:*,*:*]+img[185,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [24:30,*:*,*:*]
+SELECT img[24,*:*,*:*]+img[25,*:*,*:*]+img[26,*:*,*:*]+img[27,*:*,*:*]+img[28,*:*,*:*]+img[29,*:*,*:*]+img[30,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [188:194,*:*,*:*]
+SELECT img[188,*:*,*:*]+img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]+img[192,*:*,*:*]+img[193,*:*,*:*]+img[194,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [238:244,*:*,*:*]
+SELECT img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [76:82,*:*,*:*]
+SELECT img[76,*:*,*:*]+img[77,*:*,*:*]+img[78,*:*,*:*]+img[79,*:*,*:*]+img[80,*:*,*:*]+img[81,*:*,*:*]+img[82,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [239:245,*:*,*:*]
+SELECT img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]+img[245,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [119:125,*:*,*:*]
+SELECT img[119,*:*,*:*]+img[120,*:*,*:*]+img[121,*:*,*:*]+img[122,*:*,*:*]+img[123,*:*,*:*]+img[124,*:*,*:*]+img[125,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [176:182,*:*,*:*]
+SELECT img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]+img[180,*:*,*:*]+img[181,*:*,*:*]+img[182,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [51:57,*:*,*:*]
+SELECT img[51,*:*,*:*]+img[52,*:*,*:*]+img[53,*:*,*:*]+img[54,*:*,*:*]+img[55,*:*,*:*]+img[56,*:*,*:*]+img[57,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [8:14,*:*,*:*]
+SELECT img[8,*:*,*:*]+img[9,*:*,*:*]+img[10,*:*,*:*]+img[11,*:*,*:*]+img[12,*:*,*:*]+img[13,*:*,*:*]+img[14,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [173:179,*:*,*:*]
+SELECT img[173,*:*,*:*]+img[174,*:*,*:*]+img[175,*:*,*:*]+img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [237:243,*:*,*:*]
+SELECT img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [84:90,*:*,*:*]
+SELECT img[84,*:*,*:*]+img[85,*:*,*:*]+img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]+img[90,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [14:20,*:*,*:*]
+SELECT img[14,*:*,*:*]+img[15,*:*,*:*]+img[16,*:*,*:*]+img[17,*:*,*:*]+img[18,*:*,*:*]+img[19,*:*,*:*]+img[20,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [144:150,*:*,*:*]
+SELECT img[144,*:*,*:*]+img[145,*:*,*:*]+img[146,*:*,*:*]+img[147,*:*,*:*]+img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [215:221,*:*,*:*]
+SELECT img[215,*:*,*:*]+img[216,*:*,*:*]+img[217,*:*,*:*]+img[218,*:*,*:*]+img[219,*:*,*:*]+img[220,*:*,*:*]+img[221,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [86:92,*:*,*:*]
+SELECT img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]+img[90,*:*,*:*]+img[91,*:*,*:*]+img[92,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [136:142,*:*,*:*]
+SELECT img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]+img[141,*:*,*:*]+img[142,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [135:141,*:*,*:*]
+SELECT img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]+img[141,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 146:152, *:*]
+SELECT img[*:*,146,*:*]+img[*:*,147,*:*]+img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 15:21, *:*]
+SELECT img[*:*,15,*:*]+img[*:*,16,*:*]+img[*:*,17,*:*]+img[*:*,18,*:*]+img[*:*,19,*:*]+img[*:*,20,*:*]+img[*:*,21,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 148:154, *:*]
+SELECT img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]+img[*:*,153,*:*]+img[*:*,154,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 82:88, *:*]
+SELECT img[*:*,82,*:*]+img[*:*,83,*:*]+img[*:*,84,*:*]+img[*:*,85,*:*]+img[*:*,86,*:*]+img[*:*,87,*:*]+img[*:*,88,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 149:155, *:*]
+SELECT img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]+img[*:*,153,*:*]+img[*:*,154,*:*]+img[*:*,155,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 154:160, *:*]
+SELECT img[*:*,154,*:*]+img[*:*,155,*:*]+img[*:*,156,*:*]+img[*:*,157,*:*]+img[*:*,158,*:*]+img[*:*,159,*:*]+img[*:*,160,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 46:52, *:*]
+SELECT img[*:*,46,*:*]+img[*:*,47,*:*]+img[*:*,48,*:*]+img[*:*,49,*:*]+img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 3:9, *:*]
+SELECT img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 20:26, *:*]
+SELECT img[*:*,20,*:*]+img[*:*,21,*:*]+img[*:*,22,*:*]+img[*:*,23,*:*]+img[*:*,24,*:*]+img[*:*,25,*:*]+img[*:*,26,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 17:23, *:*]
+SELECT img[*:*,17,*:*]+img[*:*,18,*:*]+img[*:*,19,*:*]+img[*:*,20,*:*]+img[*:*,21,*:*]+img[*:*,22,*:*]+img[*:*,23,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 236:242, *:*]
+SELECT img[*:*,236,*:*]+img[*:*,237,*:*]+img[*:*,238,*:*]+img[*:*,239,*:*]+img[*:*,240,*:*]+img[*:*,241,*:*]+img[*:*,242,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 98:104, *:*]
+SELECT img[*:*,98,*:*]+img[*:*,99,*:*]+img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]+img[*:*,103,*:*]+img[*:*,104,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 4:10, *:*]
+SELECT img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 199:205, *:*]
+SELECT img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 197:203, *:*]
+SELECT img[*:*,197,*:*]+img[*:*,198,*:*]+img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 19:25, *:*]
+SELECT img[*:*,19,*:*]+img[*:*,20,*:*]+img[*:*,21,*:*]+img[*:*,22,*:*]+img[*:*,23,*:*]+img[*:*,24,*:*]+img[*:*,25,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 64:70, *:*]
+SELECT img[*:*,64,*:*]+img[*:*,65,*:*]+img[*:*,66,*:*]+img[*:*,67,*:*]+img[*:*,68,*:*]+img[*:*,69,*:*]+img[*:*,70,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 169:175, *:*]
+SELECT img[*:*,169,*:*]+img[*:*,170,*:*]+img[*:*,171,*:*]+img[*:*,172,*:*]+img[*:*,173,*:*]+img[*:*,174,*:*]+img[*:*,175,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 109:115, *:*]
+SELECT img[*:*,109,*:*]+img[*:*,110,*:*]+img[*:*,111,*:*]+img[*:*,112,*:*]+img[*:*,113,*:*]+img[*:*,114,*:*]+img[*:*,115,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 148:154, *:*]
+SELECT img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]+img[*:*,153,*:*]+img[*:*,154,*:*]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 35:41]
+SELECT img[*:*,*:*,35]+img[*:*,*:*,36]+img[*:*,*:*,37]+img[*:*,*:*,38]+img[*:*,*:*,39]+img[*:*,*:*,40]+img[*:*,*:*,41]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 24:30]
+SELECT img[*:*,*:*,24]+img[*:*,*:*,25]+img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]+img[*:*,*:*,29]+img[*:*,*:*,30]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 38:44]
+SELECT img[*:*,*:*,38]+img[*:*,*:*,39]+img[*:*,*:*,40]+img[*:*,*:*,41]+img[*:*,*:*,42]+img[*:*,*:*,43]+img[*:*,*:*,44]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 129:135]
+SELECT img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 88:94]
+SELECT img[*:*,*:*,88]+img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]+img[*:*,*:*,94]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 49:55]
+SELECT img[*:*,*:*,49]+img[*:*,*:*,50]+img[*:*,*:*,51]+img[*:*,*:*,52]+img[*:*,*:*,53]+img[*:*,*:*,54]+img[*:*,*:*,55]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 70:76]
+SELECT img[*:*,*:*,70]+img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 76:82]
+SELECT img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]+img[*:*,*:*,82]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 60:66]
+SELECT img[*:*,*:*,60]+img[*:*,*:*,61]+img[*:*,*:*,62]+img[*:*,*:*,63]+img[*:*,*:*,64]+img[*:*,*:*,65]+img[*:*,*:*,66]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 9:15]
+SELECT img[*:*,*:*,9]+img[*:*,*:*,10]+img[*:*,*:*,11]+img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 14:20]
+SELECT img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]+img[*:*,*:*,19]+img[*:*,*:*,20]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 2:8]
+SELECT img[*:*,*:*,2]+img[*:*,*:*,3]+img[*:*,*:*,4]+img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 29:35]
+SELECT img[*:*,*:*,29]+img[*:*,*:*,30]+img[*:*,*:*,31]+img[*:*,*:*,32]+img[*:*,*:*,33]+img[*:*,*:*,34]+img[*:*,*:*,35]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 48:54]
+SELECT img[*:*,*:*,48]+img[*:*,*:*,49]+img[*:*,*:*,50]+img[*:*,*:*,51]+img[*:*,*:*,52]+img[*:*,*:*,53]+img[*:*,*:*,54]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 89:95]
+SELECT img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]+img[*:*,*:*,94]+img[*:*,*:*,95]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 75:81]
+SELECT img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 83:89]
+SELECT img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]+img[*:*,*:*,86]+img[*:*,*:*,87]+img[*:*,*:*,88]+img[*:*,*:*,89]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 125:131]
+SELECT img[*:*,*:*,125]+img[*:*,*:*,126]+img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 132:138]
+SELECT img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 32:38]
+SELECT img[*:*,*:*,32]+img[*:*,*:*,33]+img[*:*,*:*,34]+img[*:*,*:*,35]+img[*:*,*:*,36]+img[*:*,*:*,37]+img[*:*,*:*,38]
+FROM comp_cubed_16 as img
diff --git a/rasodmg/test/croll_32.ql b/rasodmg/test/croll_32.ql
new file mode 100644
index 0000000..b4b1790
--- /dev/null
+++ b/rasodmg/test/croll_32.ql
@@ -0,0 +1,180 @@
+// ["x"] comp_cubed [133:139,*:*,*:*]
+SELECT img[133,*:*,*:*]+img[134,*:*,*:*]+img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [248:254,*:*,*:*]
+SELECT img[248,*:*,*:*]+img[249,*:*,*:*]+img[250,*:*,*:*]+img[251,*:*,*:*]+img[252,*:*,*:*]+img[253,*:*,*:*]+img[254,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [94:100,*:*,*:*]
+SELECT img[94,*:*,*:*]+img[95,*:*,*:*]+img[96,*:*,*:*]+img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]+img[100,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [3:9,*:*,*:*]
+SELECT img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]+img[9,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [93:99,*:*,*:*]
+SELECT img[93,*:*,*:*]+img[94,*:*,*:*]+img[95,*:*,*:*]+img[96,*:*,*:*]+img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [62:68,*:*,*:*]
+SELECT img[62,*:*,*:*]+img[63,*:*,*:*]+img[64,*:*,*:*]+img[65,*:*,*:*]+img[66,*:*,*:*]+img[67,*:*,*:*]+img[68,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [174:180,*:*,*:*]
+SELECT img[174,*:*,*:*]+img[175,*:*,*:*]+img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]+img[180,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [97:103,*:*,*:*]
+SELECT img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]+img[100,*:*,*:*]+img[101,*:*,*:*]+img[102,*:*,*:*]+img[103,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [43:49,*:*,*:*]
+SELECT img[43,*:*,*:*]+img[44,*:*,*:*]+img[45,*:*,*:*]+img[46,*:*,*:*]+img[47,*:*,*:*]+img[48,*:*,*:*]+img[49,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [41:47,*:*,*:*]
+SELECT img[41,*:*,*:*]+img[42,*:*,*:*]+img[43,*:*,*:*]+img[44,*:*,*:*]+img[45,*:*,*:*]+img[46,*:*,*:*]+img[47,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [38:44,*:*,*:*]
+SELECT img[38,*:*,*:*]+img[39,*:*,*:*]+img[40,*:*,*:*]+img[41,*:*,*:*]+img[42,*:*,*:*]+img[43,*:*,*:*]+img[44,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [75:81,*:*,*:*]
+SELECT img[75,*:*,*:*]+img[76,*:*,*:*]+img[77,*:*,*:*]+img[78,*:*,*:*]+img[79,*:*,*:*]+img[80,*:*,*:*]+img[81,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [189:195,*:*,*:*]
+SELECT img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]+img[192,*:*,*:*]+img[193,*:*,*:*]+img[194,*:*,*:*]+img[195,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [3:9,*:*,*:*]
+SELECT img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]+img[9,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [38:44,*:*,*:*]
+SELECT img[38,*:*,*:*]+img[39,*:*,*:*]+img[40,*:*,*:*]+img[41,*:*,*:*]+img[42,*:*,*:*]+img[43,*:*,*:*]+img[44,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [5:11,*:*,*:*]
+SELECT img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]+img[9,*:*,*:*]+img[10,*:*,*:*]+img[11,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [83:89,*:*,*:*]
+SELECT img[83,*:*,*:*]+img[84,*:*,*:*]+img[85,*:*,*:*]+img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [23:29,*:*,*:*]
+SELECT img[23,*:*,*:*]+img[24,*:*,*:*]+img[25,*:*,*:*]+img[26,*:*,*:*]+img[27,*:*,*:*]+img[28,*:*,*:*]+img[29,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [185:191,*:*,*:*]
+SELECT img[185,*:*,*:*]+img[186,*:*,*:*]+img[187,*:*,*:*]+img[188,*:*,*:*]+img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [148:154,*:*,*:*]
+SELECT img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]+img[151,*:*,*:*]+img[152,*:*,*:*]+img[153,*:*,*:*]+img[154,*:*,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 100:106, *:*]
+SELECT img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]+img[*:*,103,*:*]+img[*:*,104,*:*]+img[*:*,105,*:*]+img[*:*,106,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 2:8, *:*]
+SELECT img[*:*,2,*:*]+img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 166:172, *:*]
+SELECT img[*:*,166,*:*]+img[*:*,167,*:*]+img[*:*,168,*:*]+img[*:*,169,*:*]+img[*:*,170,*:*]+img[*:*,171,*:*]+img[*:*,172,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 246:252, *:*]
+SELECT img[*:*,246,*:*]+img[*:*,247,*:*]+img[*:*,248,*:*]+img[*:*,249,*:*]+img[*:*,250,*:*]+img[*:*,251,*:*]+img[*:*,252,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 78:84, *:*]
+SELECT img[*:*,78,*:*]+img[*:*,79,*:*]+img[*:*,80,*:*]+img[*:*,81,*:*]+img[*:*,82,*:*]+img[*:*,83,*:*]+img[*:*,84,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 174:180, *:*]
+SELECT img[*:*,174,*:*]+img[*:*,175,*:*]+img[*:*,176,*:*]+img[*:*,177,*:*]+img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 233:239, *:*]
+SELECT img[*:*,233,*:*]+img[*:*,234,*:*]+img[*:*,235,*:*]+img[*:*,236,*:*]+img[*:*,237,*:*]+img[*:*,238,*:*]+img[*:*,239,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 131:137, *:*]
+SELECT img[*:*,131,*:*]+img[*:*,132,*:*]+img[*:*,133,*:*]+img[*:*,134,*:*]+img[*:*,135,*:*]+img[*:*,136,*:*]+img[*:*,137,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 25:31, *:*]
+SELECT img[*:*,25,*:*]+img[*:*,26,*:*]+img[*:*,27,*:*]+img[*:*,28,*:*]+img[*:*,29,*:*]+img[*:*,30,*:*]+img[*:*,31,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 170:176, *:*]
+SELECT img[*:*,170,*:*]+img[*:*,171,*:*]+img[*:*,172,*:*]+img[*:*,173,*:*]+img[*:*,174,*:*]+img[*:*,175,*:*]+img[*:*,176,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 85:91, *:*]
+SELECT img[*:*,85,*:*]+img[*:*,86,*:*]+img[*:*,87,*:*]+img[*:*,88,*:*]+img[*:*,89,*:*]+img[*:*,90,*:*]+img[*:*,91,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 178:184, *:*]
+SELECT img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]+img[*:*,181,*:*]+img[*:*,182,*:*]+img[*:*,183,*:*]+img[*:*,184,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 198:204, *:*]
+SELECT img[*:*,198,*:*]+img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 54:60, *:*]
+SELECT img[*:*,54,*:*]+img[*:*,55,*:*]+img[*:*,56,*:*]+img[*:*,57,*:*]+img[*:*,58,*:*]+img[*:*,59,*:*]+img[*:*,60,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 227:233, *:*]
+SELECT img[*:*,227,*:*]+img[*:*,228,*:*]+img[*:*,229,*:*]+img[*:*,230,*:*]+img[*:*,231,*:*]+img[*:*,232,*:*]+img[*:*,233,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 4:10, *:*]
+SELECT img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 7:13, *:*]
+SELECT img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]+img[*:*,11,*:*]+img[*:*,12,*:*]+img[*:*,13,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 217:223, *:*]
+SELECT img[*:*,217,*:*]+img[*:*,218,*:*]+img[*:*,219,*:*]+img[*:*,220,*:*]+img[*:*,221,*:*]+img[*:*,222,*:*]+img[*:*,223,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 200:206, *:*]
+SELECT img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]+img[*:*,206,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 181:187, *:*]
+SELECT img[*:*,181,*:*]+img[*:*,182,*:*]+img[*:*,183,*:*]+img[*:*,184,*:*]+img[*:*,185,*:*]+img[*:*,186,*:*]+img[*:*,187,*:*]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 4:10]
+SELECT img[*:*,*:*,4]+img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]+img[*:*,*:*,9]+img[*:*,*:*,10]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 29:35]
+SELECT img[*:*,*:*,29]+img[*:*,*:*,30]+img[*:*,*:*,31]+img[*:*,*:*,32]+img[*:*,*:*,33]+img[*:*,*:*,34]+img[*:*,*:*,35]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 74:80]
+SELECT img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 71:77]
+SELECT img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 125:131]
+SELECT img[*:*,*:*,125]+img[*:*,*:*,126]+img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 146:152]
+SELECT img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]+img[*:*,*:*,149]+img[*:*,*:*,150]+img[*:*,*:*,151]+img[*:*,*:*,152]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 138:144]
+SELECT img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]+img[*:*,*:*,141]+img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 81:87]
+SELECT img[*:*,*:*,81]+img[*:*,*:*,82]+img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]+img[*:*,*:*,86]+img[*:*,*:*,87]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 133:139]
+SELECT img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]+img[*:*,*:*,139]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 131:137]
+SELECT img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 52:58]
+SELECT img[*:*,*:*,52]+img[*:*,*:*,53]+img[*:*,*:*,54]+img[*:*,*:*,55]+img[*:*,*:*,56]+img[*:*,*:*,57]+img[*:*,*:*,58]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 67:73]
+SELECT img[*:*,*:*,67]+img[*:*,*:*,68]+img[*:*,*:*,69]+img[*:*,*:*,70]+img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 104:110]
+SELECT img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]+img[*:*,*:*,109]+img[*:*,*:*,110]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 95:101]
+SELECT img[*:*,*:*,95]+img[*:*,*:*,96]+img[*:*,*:*,97]+img[*:*,*:*,98]+img[*:*,*:*,99]+img[*:*,*:*,100]+img[*:*,*:*,101]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 71:77]
+SELECT img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 5:11]
+SELECT img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]+img[*:*,*:*,9]+img[*:*,*:*,10]+img[*:*,*:*,11]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 127:133]
+SELECT img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 4:10]
+SELECT img[*:*,*:*,4]+img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]+img[*:*,*:*,9]+img[*:*,*:*,10]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 141:147]
+SELECT img[*:*,*:*,141]+img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]+img[*:*,*:*,145]+img[*:*,*:*,146]+img[*:*,*:*,147]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 82:88]
+SELECT img[*:*,*:*,82]+img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]+img[*:*,*:*,86]+img[*:*,*:*,87]+img[*:*,*:*,88]
+FROM comp_cubed as img
diff --git a/rasodmg/test/croll_64.ql b/rasodmg/test/croll_64.ql
new file mode 100644
index 0000000..5729a42
--- /dev/null
+++ b/rasodmg/test/croll_64.ql
@@ -0,0 +1,180 @@
+// ["x"] comp_cubed_64 [32:38,*:*,*:*]
+SELECT img[32,*:*,*:*]+img[33,*:*,*:*]+img[34,*:*,*:*]+img[35,*:*,*:*]+img[36,*:*,*:*]+img[37,*:*,*:*]+img[38,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [134:140,*:*,*:*]
+SELECT img[134,*:*,*:*]+img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [116:122,*:*,*:*]
+SELECT img[116,*:*,*:*]+img[117,*:*,*:*]+img[118,*:*,*:*]+img[119,*:*,*:*]+img[120,*:*,*:*]+img[121,*:*,*:*]+img[122,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [244:250,*:*,*:*]
+SELECT img[244,*:*,*:*]+img[245,*:*,*:*]+img[246,*:*,*:*]+img[247,*:*,*:*]+img[248,*:*,*:*]+img[249,*:*,*:*]+img[250,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [182:188,*:*,*:*]
+SELECT img[182,*:*,*:*]+img[183,*:*,*:*]+img[184,*:*,*:*]+img[185,*:*,*:*]+img[186,*:*,*:*]+img[187,*:*,*:*]+img[188,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [233:239,*:*,*:*]
+SELECT img[233,*:*,*:*]+img[234,*:*,*:*]+img[235,*:*,*:*]+img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [134:140,*:*,*:*]
+SELECT img[134,*:*,*:*]+img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [216:222,*:*,*:*]
+SELECT img[216,*:*,*:*]+img[217,*:*,*:*]+img[218,*:*,*:*]+img[219,*:*,*:*]+img[220,*:*,*:*]+img[221,*:*,*:*]+img[222,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [176:182,*:*,*:*]
+SELECT img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]+img[180,*:*,*:*]+img[181,*:*,*:*]+img[182,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [200:206,*:*,*:*]
+SELECT img[200,*:*,*:*]+img[201,*:*,*:*]+img[202,*:*,*:*]+img[203,*:*,*:*]+img[204,*:*,*:*]+img[205,*:*,*:*]+img[206,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [140:146,*:*,*:*]
+SELECT img[140,*:*,*:*]+img[141,*:*,*:*]+img[142,*:*,*:*]+img[143,*:*,*:*]+img[144,*:*,*:*]+img[145,*:*,*:*]+img[146,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [54:60,*:*,*:*]
+SELECT img[54,*:*,*:*]+img[55,*:*,*:*]+img[56,*:*,*:*]+img[57,*:*,*:*]+img[58,*:*,*:*]+img[59,*:*,*:*]+img[60,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [94:100,*:*,*:*]
+SELECT img[94,*:*,*:*]+img[95,*:*,*:*]+img[96,*:*,*:*]+img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]+img[100,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [14:20,*:*,*:*]
+SELECT img[14,*:*,*:*]+img[15,*:*,*:*]+img[16,*:*,*:*]+img[17,*:*,*:*]+img[18,*:*,*:*]+img[19,*:*,*:*]+img[20,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [211:217,*:*,*:*]
+SELECT img[211,*:*,*:*]+img[212,*:*,*:*]+img[213,*:*,*:*]+img[214,*:*,*:*]+img[215,*:*,*:*]+img[216,*:*,*:*]+img[217,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [156:162,*:*,*:*]
+SELECT img[156,*:*,*:*]+img[157,*:*,*:*]+img[158,*:*,*:*]+img[159,*:*,*:*]+img[160,*:*,*:*]+img[161,*:*,*:*]+img[162,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [196:202,*:*,*:*]
+SELECT img[196,*:*,*:*]+img[197,*:*,*:*]+img[198,*:*,*:*]+img[199,*:*,*:*]+img[200,*:*,*:*]+img[201,*:*,*:*]+img[202,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [181:187,*:*,*:*]
+SELECT img[181,*:*,*:*]+img[182,*:*,*:*]+img[183,*:*,*:*]+img[184,*:*,*:*]+img[185,*:*,*:*]+img[186,*:*,*:*]+img[187,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [80:86,*:*,*:*]
+SELECT img[80,*:*,*:*]+img[81,*:*,*:*]+img[82,*:*,*:*]+img[83,*:*,*:*]+img[84,*:*,*:*]+img[85,*:*,*:*]+img[86,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [1:7,*:*,*:*]
+SELECT img[1,*:*,*:*]+img[2,*:*,*:*]+img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 72:78, *:*]
+SELECT img[*:*,72,*:*]+img[*:*,73,*:*]+img[*:*,74,*:*]+img[*:*,75,*:*]+img[*:*,76,*:*]+img[*:*,77,*:*]+img[*:*,78,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 211:217, *:*]
+SELECT img[*:*,211,*:*]+img[*:*,212,*:*]+img[*:*,213,*:*]+img[*:*,214,*:*]+img[*:*,215,*:*]+img[*:*,216,*:*]+img[*:*,217,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 199:205, *:*]
+SELECT img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 92:98, *:*]
+SELECT img[*:*,92,*:*]+img[*:*,93,*:*]+img[*:*,94,*:*]+img[*:*,95,*:*]+img[*:*,96,*:*]+img[*:*,97,*:*]+img[*:*,98,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 233:239, *:*]
+SELECT img[*:*,233,*:*]+img[*:*,234,*:*]+img[*:*,235,*:*]+img[*:*,236,*:*]+img[*:*,237,*:*]+img[*:*,238,*:*]+img[*:*,239,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 201:207, *:*]
+SELECT img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]+img[*:*,206,*:*]+img[*:*,207,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 59:65, *:*]
+SELECT img[*:*,59,*:*]+img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]+img[*:*,63,*:*]+img[*:*,64,*:*]+img[*:*,65,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 208:214, *:*]
+SELECT img[*:*,208,*:*]+img[*:*,209,*:*]+img[*:*,210,*:*]+img[*:*,211,*:*]+img[*:*,212,*:*]+img[*:*,213,*:*]+img[*:*,214,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 1:7, *:*]
+SELECT img[*:*,1,*:*]+img[*:*,2,*:*]+img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 4:10, *:*]
+SELECT img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 5:11, *:*]
+SELECT img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]+img[*:*,11,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 98:104, *:*]
+SELECT img[*:*,98,*:*]+img[*:*,99,*:*]+img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]+img[*:*,103,*:*]+img[*:*,104,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 74:80, *:*]
+SELECT img[*:*,74,*:*]+img[*:*,75,*:*]+img[*:*,76,*:*]+img[*:*,77,*:*]+img[*:*,78,*:*]+img[*:*,79,*:*]+img[*:*,80,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 49:55, *:*]
+SELECT img[*:*,49,*:*]+img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]+img[*:*,53,*:*]+img[*:*,54,*:*]+img[*:*,55,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 177:183, *:*]
+SELECT img[*:*,177,*:*]+img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]+img[*:*,181,*:*]+img[*:*,182,*:*]+img[*:*,183,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 146:152, *:*]
+SELECT img[*:*,146,*:*]+img[*:*,147,*:*]+img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 105:111, *:*]
+SELECT img[*:*,105,*:*]+img[*:*,106,*:*]+img[*:*,107,*:*]+img[*:*,108,*:*]+img[*:*,109,*:*]+img[*:*,110,*:*]+img[*:*,111,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 46:52, *:*]
+SELECT img[*:*,46,*:*]+img[*:*,47,*:*]+img[*:*,48,*:*]+img[*:*,49,*:*]+img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 56:62, *:*]
+SELECT img[*:*,56,*:*]+img[*:*,57,*:*]+img[*:*,58,*:*]+img[*:*,59,*:*]+img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 154:160, *:*]
+SELECT img[*:*,154,*:*]+img[*:*,155,*:*]+img[*:*,156,*:*]+img[*:*,157,*:*]+img[*:*,158,*:*]+img[*:*,159,*:*]+img[*:*,160,*:*]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 127:133]
+SELECT img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 79:85]
+SELECT img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]+img[*:*,*:*,82]+img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 134:140]
+SELECT img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 12:18]
+SELECT img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 142:148]
+SELECT img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]+img[*:*,*:*,145]+img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 128:134]
+SELECT img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 75:81]
+SELECT img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 118:124]
+SELECT img[*:*,*:*,118]+img[*:*,*:*,119]+img[*:*,*:*,120]+img[*:*,*:*,121]+img[*:*,*:*,122]+img[*:*,*:*,123]+img[*:*,*:*,124]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 87:93]
+SELECT img[*:*,*:*,87]+img[*:*,*:*,88]+img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 23:29]
+SELECT img[*:*,*:*,23]+img[*:*,*:*,24]+img[*:*,*:*,25]+img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]+img[*:*,*:*,29]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 69:75]
+SELECT img[*:*,*:*,69]+img[*:*,*:*,70]+img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 146:152]
+SELECT img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]+img[*:*,*:*,149]+img[*:*,*:*,150]+img[*:*,*:*,151]+img[*:*,*:*,152]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 99:105]
+SELECT img[*:*,*:*,99]+img[*:*,*:*,100]+img[*:*,*:*,101]+img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 135:141]
+SELECT img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]+img[*:*,*:*,141]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 76:82]
+SELECT img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]+img[*:*,*:*,82]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 26:32]
+SELECT img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]+img[*:*,*:*,29]+img[*:*,*:*,30]+img[*:*,*:*,31]+img[*:*,*:*,32]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 56:62]
+SELECT img[*:*,*:*,56]+img[*:*,*:*,57]+img[*:*,*:*,58]+img[*:*,*:*,59]+img[*:*,*:*,60]+img[*:*,*:*,61]+img[*:*,*:*,62]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 94:100]
+SELECT img[*:*,*:*,94]+img[*:*,*:*,95]+img[*:*,*:*,96]+img[*:*,*:*,97]+img[*:*,*:*,98]+img[*:*,*:*,99]+img[*:*,*:*,100]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 13:19]
+SELECT img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]+img[*:*,*:*,19]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 22:28]
+SELECT img[*:*,*:*,22]+img[*:*,*:*,23]+img[*:*,*:*,24]+img[*:*,*:*,25]+img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]
+FROM comp_cubed_64 as img
diff --git a/rasodmg/test/croll_sliced.ql b/rasodmg/test/croll_sliced.ql
new file mode 100644
index 0000000..90ab35c
--- /dev/null
+++ b/rasodmg/test/croll_sliced.ql
@@ -0,0 +1,180 @@
+// ["x"] comp_sliced [2:8,*:*,*:*]
+SELECT img[2,*:*,*:*]+img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [86:92,*:*,*:*]
+SELECT img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]+img[90,*:*,*:*]+img[91,*:*,*:*]+img[92,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [2:8,*:*,*:*]
+SELECT img[2,*:*,*:*]+img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [104:110,*:*,*:*]
+SELECT img[104,*:*,*:*]+img[105,*:*,*:*]+img[106,*:*,*:*]+img[107,*:*,*:*]+img[108,*:*,*:*]+img[109,*:*,*:*]+img[110,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [236:242,*:*,*:*]
+SELECT img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [145:151,*:*,*:*]
+SELECT img[145,*:*,*:*]+img[146,*:*,*:*]+img[147,*:*,*:*]+img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]+img[151,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [242:248,*:*,*:*]
+SELECT img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]+img[245,*:*,*:*]+img[246,*:*,*:*]+img[247,*:*,*:*]+img[248,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [236:242,*:*,*:*]
+SELECT img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [246:252,*:*,*:*]
+SELECT img[246,*:*,*:*]+img[247,*:*,*:*]+img[248,*:*,*:*]+img[249,*:*,*:*]+img[250,*:*,*:*]+img[251,*:*,*:*]+img[252,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [189:195,*:*,*:*]
+SELECT img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]+img[192,*:*,*:*]+img[193,*:*,*:*]+img[194,*:*,*:*]+img[195,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [136:142,*:*,*:*]
+SELECT img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]+img[141,*:*,*:*]+img[142,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [100:106,*:*,*:*]
+SELECT img[100,*:*,*:*]+img[101,*:*,*:*]+img[102,*:*,*:*]+img[103,*:*,*:*]+img[104,*:*,*:*]+img[105,*:*,*:*]+img[106,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [49:55,*:*,*:*]
+SELECT img[49,*:*,*:*]+img[50,*:*,*:*]+img[51,*:*,*:*]+img[52,*:*,*:*]+img[53,*:*,*:*]+img[54,*:*,*:*]+img[55,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [101:107,*:*,*:*]
+SELECT img[101,*:*,*:*]+img[102,*:*,*:*]+img[103,*:*,*:*]+img[104,*:*,*:*]+img[105,*:*,*:*]+img[106,*:*,*:*]+img[107,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [238:244,*:*,*:*]
+SELECT img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [56:62,*:*,*:*]
+SELECT img[56,*:*,*:*]+img[57,*:*,*:*]+img[58,*:*,*:*]+img[59,*:*,*:*]+img[60,*:*,*:*]+img[61,*:*,*:*]+img[62,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [57:63,*:*,*:*]
+SELECT img[57,*:*,*:*]+img[58,*:*,*:*]+img[59,*:*,*:*]+img[60,*:*,*:*]+img[61,*:*,*:*]+img[62,*:*,*:*]+img[63,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [146:152,*:*,*:*]
+SELECT img[146,*:*,*:*]+img[147,*:*,*:*]+img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]+img[151,*:*,*:*]+img[152,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [212:218,*:*,*:*]
+SELECT img[212,*:*,*:*]+img[213,*:*,*:*]+img[214,*:*,*:*]+img[215,*:*,*:*]+img[216,*:*,*:*]+img[217,*:*,*:*]+img[218,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [172:178,*:*,*:*]
+SELECT img[172,*:*,*:*]+img[173,*:*,*:*]+img[174,*:*,*:*]+img[175,*:*,*:*]+img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 57:63, *:*]
+SELECT img[*:*,57,*:*]+img[*:*,58,*:*]+img[*:*,59,*:*]+img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]+img[*:*,63,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 225:231, *:*]
+SELECT img[*:*,225,*:*]+img[*:*,226,*:*]+img[*:*,227,*:*]+img[*:*,228,*:*]+img[*:*,229,*:*]+img[*:*,230,*:*]+img[*:*,231,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 96:102, *:*]
+SELECT img[*:*,96,*:*]+img[*:*,97,*:*]+img[*:*,98,*:*]+img[*:*,99,*:*]+img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 3:9, *:*]
+SELECT img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 60:66, *:*]
+SELECT img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]+img[*:*,63,*:*]+img[*:*,64,*:*]+img[*:*,65,*:*]+img[*:*,66,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 133:139, *:*]
+SELECT img[*:*,133,*:*]+img[*:*,134,*:*]+img[*:*,135,*:*]+img[*:*,136,*:*]+img[*:*,137,*:*]+img[*:*,138,*:*]+img[*:*,139,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 62:68, *:*]
+SELECT img[*:*,62,*:*]+img[*:*,63,*:*]+img[*:*,64,*:*]+img[*:*,65,*:*]+img[*:*,66,*:*]+img[*:*,67,*:*]+img[*:*,68,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 112:118, *:*]
+SELECT img[*:*,112,*:*]+img[*:*,113,*:*]+img[*:*,114,*:*]+img[*:*,115,*:*]+img[*:*,116,*:*]+img[*:*,117,*:*]+img[*:*,118,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 206:212, *:*]
+SELECT img[*:*,206,*:*]+img[*:*,207,*:*]+img[*:*,208,*:*]+img[*:*,209,*:*]+img[*:*,210,*:*]+img[*:*,211,*:*]+img[*:*,212,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 136:142, *:*]
+SELECT img[*:*,136,*:*]+img[*:*,137,*:*]+img[*:*,138,*:*]+img[*:*,139,*:*]+img[*:*,140,*:*]+img[*:*,141,*:*]+img[*:*,142,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 22:28, *:*]
+SELECT img[*:*,22,*:*]+img[*:*,23,*:*]+img[*:*,24,*:*]+img[*:*,25,*:*]+img[*:*,26,*:*]+img[*:*,27,*:*]+img[*:*,28,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 121:127, *:*]
+SELECT img[*:*,121,*:*]+img[*:*,122,*:*]+img[*:*,123,*:*]+img[*:*,124,*:*]+img[*:*,125,*:*]+img[*:*,126,*:*]+img[*:*,127,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 42:48, *:*]
+SELECT img[*:*,42,*:*]+img[*:*,43,*:*]+img[*:*,44,*:*]+img[*:*,45,*:*]+img[*:*,46,*:*]+img[*:*,47,*:*]+img[*:*,48,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 110:116, *:*]
+SELECT img[*:*,110,*:*]+img[*:*,111,*:*]+img[*:*,112,*:*]+img[*:*,113,*:*]+img[*:*,114,*:*]+img[*:*,115,*:*]+img[*:*,116,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 75:81, *:*]
+SELECT img[*:*,75,*:*]+img[*:*,76,*:*]+img[*:*,77,*:*]+img[*:*,78,*:*]+img[*:*,79,*:*]+img[*:*,80,*:*]+img[*:*,81,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 162:168, *:*]
+SELECT img[*:*,162,*:*]+img[*:*,163,*:*]+img[*:*,164,*:*]+img[*:*,165,*:*]+img[*:*,166,*:*]+img[*:*,167,*:*]+img[*:*,168,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 80:86, *:*]
+SELECT img[*:*,80,*:*]+img[*:*,81,*:*]+img[*:*,82,*:*]+img[*:*,83,*:*]+img[*:*,84,*:*]+img[*:*,85,*:*]+img[*:*,86,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 50:56, *:*]
+SELECT img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]+img[*:*,53,*:*]+img[*:*,54,*:*]+img[*:*,55,*:*]+img[*:*,56,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 174:180, *:*]
+SELECT img[*:*,174,*:*]+img[*:*,175,*:*]+img[*:*,176,*:*]+img[*:*,177,*:*]+img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 33:39, *:*]
+SELECT img[*:*,33,*:*]+img[*:*,34,*:*]+img[*:*,35,*:*]+img[*:*,36,*:*]+img[*:*,37,*:*]+img[*:*,38,*:*]+img[*:*,39,*:*]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 125:131]
+SELECT img[*:*,*:*,125]+img[*:*,*:*,126]+img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 99:105]
+SELECT img[*:*,*:*,99]+img[*:*,*:*,100]+img[*:*,*:*,101]+img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 138:144]
+SELECT img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]+img[*:*,*:*,141]+img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 102:108]
+SELECT img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 89:95]
+SELECT img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]+img[*:*,*:*,94]+img[*:*,*:*,95]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 106:112]
+SELECT img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]+img[*:*,*:*,109]+img[*:*,*:*,110]+img[*:*,*:*,111]+img[*:*,*:*,112]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 38:44]
+SELECT img[*:*,*:*,38]+img[*:*,*:*,39]+img[*:*,*:*,40]+img[*:*,*:*,41]+img[*:*,*:*,42]+img[*:*,*:*,43]+img[*:*,*:*,44]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 11:17]
+SELECT img[*:*,*:*,11]+img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 112:118]
+SELECT img[*:*,*:*,112]+img[*:*,*:*,113]+img[*:*,*:*,114]+img[*:*,*:*,115]+img[*:*,*:*,116]+img[*:*,*:*,117]+img[*:*,*:*,118]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 127:133]
+SELECT img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 71:77]
+SELECT img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 57:63]
+SELECT img[*:*,*:*,57]+img[*:*,*:*,58]+img[*:*,*:*,59]+img[*:*,*:*,60]+img[*:*,*:*,61]+img[*:*,*:*,62]+img[*:*,*:*,63]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 144:150]
+SELECT img[*:*,*:*,144]+img[*:*,*:*,145]+img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]+img[*:*,*:*,149]+img[*:*,*:*,150]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 130:136]
+SELECT img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 101:107]
+SELECT img[*:*,*:*,101]+img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 104:110]
+SELECT img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]+img[*:*,*:*,109]+img[*:*,*:*,110]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 116:122]
+SELECT img[*:*,*:*,116]+img[*:*,*:*,117]+img[*:*,*:*,118]+img[*:*,*:*,119]+img[*:*,*:*,120]+img[*:*,*:*,121]+img[*:*,*:*,122]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 12:18]
+SELECT img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 86:92]
+SELECT img[*:*,*:*,86]+img[*:*,*:*,87]+img[*:*,*:*,88]+img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 44:50]
+SELECT img[*:*,*:*,44]+img[*:*,*:*,45]+img[*:*,*:*,46]+img[*:*,*:*,47]+img[*:*,*:*,48]+img[*:*,*:*,49]+img[*:*,*:*,50]
+FROM comp_sliced as img
diff --git a/rasodmg/test/csel_16.ql b/rasodmg/test/csel_16.ql
new file mode 100644
index 0000000..95399ed
--- /dev/null
+++ b/rasodmg/test/csel_16.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on comp_cubed_16.
+
+// [0.5] cubed_16, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from comp_cubed_16 as img
+
+// [1] cubed_16, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from comp_cubed_16 as img
+
+// [2] cubed_16, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from comp_cubed_16 as img
+
+// [5] cubed_16, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from comp_cubed_16 as img
+
+// [10] cubed_16, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from comp_cubed_16 as img
+
+// [20] cubed_16, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from comp_cubed_16 as img
+
+// [50] cubed_16, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from comp_cubed_16 as img
+
+// [100] cubed_16, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from comp_cubed_16 as img
+
diff --git a/rasodmg/test/csel_32.ql b/rasodmg/test/csel_32.ql
new file mode 100644
index 0000000..aa3466c
--- /dev/null
+++ b/rasodmg/test/csel_32.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on comp_cubed.
+
+// [0.5] cubed, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from comp_cubed as img
+
+// [1] cubed, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from comp_cubed as img
+
+// [2] cubed, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from comp_cubed as img
+
+// [5] cubed, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from comp_cubed as img
+
+// [10] cubed, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from comp_cubed as img
+
+// [20] cubed, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from comp_cubed as img
+
+// [50] cubed, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from comp_cubed as img
+
+// [100] cubed, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from comp_cubed as img
+
diff --git a/rasodmg/test/csel_64.ql b/rasodmg/test/csel_64.ql
new file mode 100644
index 0000000..c81079b
--- /dev/null
+++ b/rasodmg/test/csel_64.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on comp_cubed_64.
+
+// [0.5] cubed_64, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from comp_cubed_64 as img
+
+// [1] cubed_64, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from comp_cubed_64 as img
+
+// [2] cubed_64, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from comp_cubed_64 as img
+
+// [5] cubed_64, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from comp_cubed_64 as img
+
+// [10] cubed_64, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from comp_cubed_64 as img
+
+// [20] cubed_64, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from comp_cubed_64 as img
+
+// [50] cubed_64, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from comp_cubed_64 as img
+
+// [100] cubed_64, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from comp_cubed_64 as img
+
diff --git a/rasodmg/test/csel_sliced.ql b/rasodmg/test/csel_sliced.ql
new file mode 100644
index 0000000..f3d9a0b
--- /dev/null
+++ b/rasodmg/test/csel_sliced.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on comp_sliced.
+
+// [0.5] sliced, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from comp_sliced as img
+
+// [1] sliced, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from comp_sliced as img
+
+// [2] sliced, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from comp_sliced as img
+
+// [5] sliced, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from comp_sliced as img
+
+// [10] sliced, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from comp_sliced as img
+
+// [20] sliced, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from comp_sliced as img
+
+// [50] sliced, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from comp_sliced as img
+
+// [100] sliced, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from comp_sliced as img
+
diff --git a/rasodmg/test/defconv.cc b/rasodmg/test/defconv.cc
new file mode 100644
index 0000000..feee2dc
--- /dev/null
+++ b/rasodmg/test/defconv.cc
@@ -0,0 +1,598 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * defconv.cc
+ *
+ * Covert the DEF source file to another DEF destination file.
+ * Returns 0 for succes, otherwise 1.
+ *
+ * Parameters:
+ *
+ * --inputfilename <src-file>
+ * the filename of the src file, mandatory
+ * --outputfilename <dest-file>
+ * the filename of the dest file, mandatory
+ *
+ * --inputformat name
+ * name of DEF fromat(see data_foramat from mddtypes.hh)
+ * --inputformatparams params
+ * params used by convertFrom methods(see the heder file for you DEF from conversion)
+ * --outputformat name
+ * name of DEF fromat(see data_foramat from mddtypes.hh)
+ * --outputformatparams params
+ * params used by convertFrom methods(see the heder file for you DEF from conversion)
+ *
+ * --help
+ * print usage and exit
+ */
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#ifdef __GNUG__
+#include "raslib/template_inst.hh"
+#endif
+#endif
+
+#include "defutil.hh"
+#include "raslib/miter.hh"
+
+//program data
+const char* paramPrgHelp="--help";
+bool defPrgHelp=false;
+char* prgHelp=NULL;
+
+const char* paramSrcFileName="--srcfilename";
+bool defSrcFileName=false;
+char* srcFileName=NULL;
+
+const char* paramSrcFormat="--srcformat";
+bool defSrcFormat=false;
+char* srcFormatc=NULL;
+r_Data_Format srcFormat=r_Array;
+char *srcIvc=NULL, *srcTypec=NULL;
+r_Minterval srcIv;
+r_Type* srcType=NULL;
+
+const char* paramSrcFormatParams="--srcformatparams";
+bool defSrcFormatParams=false;
+char *srcFormatParams=NULL;
+
+const char* paramDestFileName="--destfilename";
+bool defDestFileName=false;
+char *destFileName=NULL;
+
+const char* paramDestFormat="--destformat";
+bool defDestFormat=false;
+char* destFormatc=NULL;
+r_Data_Format destFormat=r_Array;
+char *destIvc=NULL, *destTypec=NULL;
+r_Minterval destIv;
+r_Type* destType=NULL;
+
+const char* paramDestFormatParams="--destformatparams";
+bool defDestFormatParams=false;
+char *destFormatParams=NULL;
+
+//data used to parase formatparams for format Array
+const char* fpDomain="domain";
+const char* fpType="type";
+
+//structures used for parseParam
+const int paramsNo=7;
+
+const char *paramsName[paramsNo]={ paramPrgHelp, paramSrcFileName, paramSrcFormat, paramSrcFormatParams,
+ paramDestFileName, paramDestFormat, paramDestFormatParams};
+
+bool *paramsPresent[paramsNo]={ &defPrgHelp, &defSrcFileName, &defSrcFormat, &defSrcFormatParams,
+ &defDestFileName, &defDestFormat, &defDestFormatParams};
+
+char **paramsValue[paramsNo]={ &prgHelp, &srcFileName, &srcFormatc, &srcFormatParams,
+ &destFileName, &destFormatc, &destFormatParams};
+
+void printStatus()
+{
+ cout << "defdiff parameters list:" << endl;
+ for (int i=0; i<paramsNo; i++)
+ cout << "--Name='" << paramsName[i]
+ << "' Present=" << ((*paramsPresent[i])? "true": "false")
+ << " Value='" << *paramsValue[i] << "'" << endl;
+}
+
+void printUsage()
+{
+ char* fileNameSrc="test.bmp";
+ char* fileNameDest="test.tiff";
+
+ cout << "defconv v 0.1 - RasDaMan Data Exchange Format Convertor Utility" << endl;
+ cout << "Description: Returns " << EXIT_SUCCESS << " for succes, otherwise " << EXIT_FAILURE << endl;
+ cout << "For " << paramSrcFormat << "/" << paramDestFormat << " Array you have to specify the "
+ << paramSrcFormatParams << "/" << paramDestFormatParams << " as following:" << endl;
+ cout << "\"" << fpDomain << "=<domain_str>," << fpType << "=<type_str>\" (e.g. \""
+ << fpDomain << "=\"[0:477,0:464]\"," << fpType << "=char\")" << endl;
+ cout << "Usage options:" << endl;
+ cout << " " << paramSrcFileName << " <src-file> ... the filename used as src mandatory" << endl;
+ cout << " " << paramSrcFormat << " name ... name of DEF fromat(see data_foramat from mddtypes.hh)," << endl;
+ cout << " default Array" << endl;
+ cout << " " << paramSrcFormatParams << " params ... params used by convertFrom methods(see the header file" << endl;
+ cout << " for you DEF from conversion), default NULL" << endl;
+ cout << " " << paramDestFileName << " <dest-file> ... the filename used as dest mandatory" << endl;
+ cout << " " << paramDestFormat << " name ... name of DEF fromat(see data_foramat from mddtypes.hh)," << endl;
+ cout << " default Array" << endl;
+ cout << " " << paramDestFormatParams << " params ... params used by convertFrom methods(see the header file" << endl;
+ cout << " for you DEF from conversion), default NULL" << endl;
+ cout << " " << paramPrgHelp << " ... this help" << endl;
+ cout << "For example:" << endl;
+ cout << "defconv " << paramSrcFileName << " " << fileNameSrc << " " << paramSrcFormat << " " << format_name_bmp <<" "
+ << paramDestFileName << " " << fileNameDest << " " << paramDestFormat <<" " << format_name_tiff << endl;
+ cout << "Report bugs to liviu.coman@active­knowledge.com" << endl;
+
+}
+
+int checkParam(int& paramIndex, char** param)
+{
+ int i=0;
+ while(i<paramsNo)
+ {
+ if(!strcmp(param[paramIndex], paramsName[i]))
+ break;
+ i++;
+ }
+
+ if(i==paramsNo)
+ {
+ cout << "checkParam(...) error processing parameters: parameter "
+ << param[paramIndex] << " is unknown!" << endl;
+ return EXIT_FAILURE;
+ }
+ if(*paramsPresent[i])
+ {
+ cout << "checkParam(...) error processing parameters: parameter "
+ << param[paramIndex] << " is present more than once!" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(paramsName[i]!=paramPrgHelp)
+ {
+ *paramsPresent[i]=true;
+ paramIndex++;
+ *paramsValue[i]=param[paramIndex];
+ }
+ else
+ *paramsPresent[i]=true;
+
+ return EXIT_SUCCESS;
+}
+
+int parseParams(int argc, char** argv)
+{
+ int argIndex=0;
+ if (argc==1)
+ {
+ cout << "parseParams(...) parameters " << paramSrcFileName << " <src-file> and "
+ << paramDestFileName << " <dest-file> are mandatatory!" << endl;
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ argIndex=1;
+ while(argIndex<argc)
+ {
+ if(checkParam(argIndex, argv)!=EXIT_SUCCESS)
+ break;
+ argIndex++;
+ }
+ if(argIndex<argc)
+ {
+ //error while parsing parameters
+ return EXIT_FAILURE;
+ }
+
+ //check rule
+ if((defSrcFileName && defDestFileName) || (defPrgHelp))
+ return EXIT_SUCCESS;
+ else
+ {
+ cout << "parseParams(...) parameters " << paramSrcFileName << " <src-file> and "
+ << paramDestFileName << " <dest-file> are mandatatory!" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+}
+
+int validateParams()
+{
+
+ //check srcformat
+ if(defSrcFormat)
+ {
+ srcFormat = get_data_format_from_name(srcFormatc);
+ if((srcFormat!=r_Array) &&
+ (!r_Convertor_Factory::is_supported(srcFormat)))
+ {
+ cout << "convertDEFs(...) conversion " << srcFormatc << " not supported" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ //check destformat
+ if(defDestFormat)
+ {
+ destFormat = get_data_format_from_name(destFormatc);
+ if((destFormat!=r_Array) &&
+ (!r_Convertor_Factory::is_supported(destFormat)))
+ {
+ cout << "convertDEFs(...) conversion " << destFormatc << " not supported" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ //check srcFormatParams if srcFormat=r_Array
+ if(srcFormat == r_Array)
+ {
+ if(!defSrcFormatParams)
+ {
+ cout << "convertDEFs(...) for srcformat r_Array is necessary to provide the srcformatparams as described in help" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(parseArrayParams((const char*)srcFormatParams, fpDomain, fpType, srcIvc, srcTypec) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(decodeMinterval(srcIvc, srcIv) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(decodeType(srcTypec, srcType) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ }
+
+ //check destFormatParams if destFormat=r_Array
+ if(destFormat == r_Array)
+ {
+ if(!defDestFormatParams)
+ {
+ cout << "convertDEFs(...) for destformat r_Array is necessary to provide the srcformatparams as described in help" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(parseArrayParams((const char*)destFormatParams, fpDomain, fpType, destIvc, destTypec) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(decodeMinterval(destIvc, destIv) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(decodeType(destTypec, destType) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ }
+}
+
+int setCell(const char* srcCell,
+ const r_Type* srcType,
+ const r_Type* destType,
+ char* destCell,
+ bool rescale=false)
+{
+ r_Double srcTypeMin=0., srcTypeMax=0.;
+ r_Double destTypeMin=0., destTypeMax=0.;
+ r_Double srcVal=0., destVal=0.;
+
+ if(!srcCell)
+ {
+ cout << "setCell(...) srcCell is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(!srcType)
+ {
+ cout << "setCell(...) srcType is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(!destType)
+ {
+ cout << "setCell(...) destType is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(!destCell)
+ {
+ cout << "setCell(...) destCell is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ srcVal=((r_Primitive_Type*)srcType)->get_value(srcCell);
+ if(rescale)
+ {
+ ((r_Primitive_Type*)srcType)->get_limits(srcTypeMin, srcTypeMax);
+ ((r_Primitive_Type*)destType)->get_limits(destTypeMin, destTypeMax);
+ destVal=srcVal*destTypeMax/srcTypeMax;
+ }
+ else
+ destVal=srcVal;
+ ((r_Primitive_Type*)destType)->set_value(destCell,destVal);
+ }
+ catch(r_Error& err)
+ {
+ cout << "setCell(...) error while setting value to dest from src" << endl;
+ cout << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+int convertData(const r_convDesc& descSrc, r_convDesc& descDest)
+{
+ r_Minterval srcIv, destIv, commonIv;
+
+ r_Bytes srcTypeSize=0, destTypeSize=0;
+ char *srcBuffer=NULL, *destBuffer=NULL;
+
+ if(!descSrc.dest)
+ {
+ cout << "convertData(...) descSrc.dest is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!descSrc.destType)
+ {
+ cout << "convertData(...) descSrc.destType is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(descDest.dest)
+ {
+ cout << "convertData(...) descDest.dest is not null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!descDest.destType)
+ {
+ cout << "convertData(...) descDest.destType is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ //translate every interval to zero
+ try
+ {
+ srcIv=descSrc.destInterv.create_reverse_translation(descSrc.destInterv.get_origin());
+ destIv=descDest.destInterv.create_reverse_translation(descDest.destInterv.get_origin());
+ }
+ catch(r_Error& err)
+ {
+ cout << "convertData(...) error while translating to zero the following intervals:" << endl;
+ cout << "descSrc.destInterv=" << descSrc.destInterv << endl;
+ cout << "descDest.destInterv=" << descDest.destInterv << endl;
+ cout << "Error " << err.get_errorno() << ":" << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ //check intersection
+ try
+ {
+ commonIv.intersection_of(srcIv, destIv);
+ }
+ catch(r_Error& err)
+ {
+ cout << "convertData(...) error while doing the intersection of the following intervals:" << endl;
+ cout << "descSrc.destInterv=" << descSrc.destInterv << endl;
+ cout << "descDest.destInterv=" << descDest.destInterv << endl;
+ cout << "Error " << err.get_errorno() << ":" << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ //get type size
+ srcTypeSize=((r_Base_Type*)descSrc.destType)->size();
+ destTypeSize=((r_Base_Type*)descDest.destType)->size();
+
+ //allocate data
+ srcBuffer=new char[srcTypeSize];
+ if(!srcBuffer)
+ {
+ cout << "convertData(...) unable to claim memory for srcBuffer" << endl;
+ return EXIT_FAILURE;
+ }
+ destBuffer=new char[destTypeSize];
+ if(!destBuffer)
+ {
+ cout << "convertData(...) unable to claim memory for destBuffer" << endl;
+ delete[] srcBuffer;
+ srcBuffer=NULL;
+ return EXIT_FAILURE;
+ }
+ descDest.dest=new char[descDest.destInterv.cell_count()*destTypeSize];
+ if(!descDest.dest)
+ {
+ cout << "convertData(...) unable to claim memory for descDest.dest" << endl;
+ delete[] srcBuffer;
+ srcBuffer=NULL;
+ delete[] destBuffer;
+ destBuffer=NULL;
+ return EXIT_FAILURE;
+ }
+ memset(descDest.dest,0, descDest.destInterv.cell_count()*destTypeSize);
+
+ r_Miter srcIter( &commonIv, &srcIv, srcTypeSize, descSrc.dest );
+ r_Miter destIter( &commonIv, &destIv, destTypeSize, descDest.dest );
+ while(!srcIter.isDone() || !destIter.isDone())
+ {
+ memcpy(srcBuffer, srcIter.nextCell(), srcTypeSize);
+ if(setCell(srcBuffer, descSrc.destType, descDest.destType, destBuffer)!=EXIT_SUCCESS)
+ {
+ //abort algorithm
+ break;
+ }
+ memcpy(destIter.nextCell(), destBuffer, destTypeSize);
+ }
+
+ //clean up
+ delete[] srcBuffer;
+ srcBuffer=NULL;
+ delete[] destBuffer;
+ destBuffer=NULL;
+
+ //check algorithm
+ if(!srcIter.isDone() || !destIter.isDone())
+ {
+ cout << "convertData(...) error in algorithm" << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
+
+int convertDEFs()
+{
+ char *dataSrc=NULL, *dataDest=NULL;
+ r_ULong dataSrcSize=0, dataDestSize=0;
+ r_convDesc descSrc, descDest;
+
+ initConvDesc(descSrc);
+ initConvDesc(descDest);
+
+ //read the source file
+ if(readFile(srcFileName, &dataSrc, dataSrcSize)!=EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(!dataSrcSize)
+ {
+ cout << "convertDEFs() size of file " << srcFileName << " is zero" << endl;
+ //clean up
+ delete [] dataSrc;
+ dataSrc=NULL;
+ return EXIT_FAILURE;
+ }
+
+ //what is the input format?
+ if(srcFormat !=r_Array)
+ {
+ //it is safe to use srcType, srcIv because the srcFormat is not r_Array
+ srcType=r_Convertor::get_external_type(r_Convertor::ctype_char);
+ srcIv = r_Minterval(1);
+ srcIv << r_Sinterval((r_Long)0, (r_Long)(dataSrcSize - 1));
+
+ //did conversion work?
+ if(convertFrom(srcFormat, srcFormatParams, dataSrc,
+ srcIv, srcType, descSrc) != EXIT_SUCCESS)
+ {
+ //clean up
+ delete [] dataSrc;
+ dataSrc=NULL;
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ descSrc.dest=dataSrc;
+ descSrc.destInterv=srcIv;
+ descSrc.destType=srcType;
+ }
+
+ //what is the output format?
+ if(destFormat !=r_Array)
+ {
+ if(convertTo(destFormat, destFormatParams, descSrc.dest, descSrc.destInterv, descSrc.destType, descDest) != EXIT_SUCCESS)
+ {
+ //clean up
+ cleanConvDesc(descSrc);
+ return EXIT_FAILURE;
+ }
+ //prepare the data for writing
+ dataDest=descDest.dest;
+ dataDestSize=descDest.destInterv.cell_count() * ((r_Base_Type*)descDest.destType)->size();
+ }
+ else
+ {
+ //prepare for conversion
+ descDest.destType=destType;
+ descDest.destInterv=destIv;
+ descDest.dest=NULL;
+
+ if(descSrc.destType->isPrimitiveType())
+ {
+ if(convertData(descSrc, descDest) != EXIT_SUCCESS)
+ {
+ //clean up
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ //prepare the data for writing
+ dataDest=descDest.dest;
+ dataDestSize=descDest.destInterv.cell_count() * ((r_Base_Type*)descDest.destType)->size();
+ }
+ else
+ {
+ //we store the data as it is
+ dataDest=descSrc.dest;
+ dataDestSize=descSrc.destInterv.cell_count() * ((r_Base_Type*)descSrc.destType)->size();
+ }
+
+ }
+
+
+
+ //write data into destFileName
+ if(writeFile(destFileName, (const char**)&dataDest, dataDestSize)!=EXIT_SUCCESS)
+ {
+ //clean up
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ //clean up
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+
+ return EXIT_SUCCESS;
+}
+
+int processRequest()
+{
+ if(validateParams() != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ return convertDEFs();
+}
+
+int main(int argc, char **argv)
+{
+ if(parseParams(argc, argv) != EXIT_SUCCESS)
+ {
+ printUsage();
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ if(!defPrgHelp)
+ {
+ printStatus();
+ return processRequest();
+ }
+ else
+ {
+ printUsage();
+ return EXIT_SUCCESS;
+ }
+ }
+}
diff --git a/rasodmg/test/defdiff.cc b/rasodmg/test/defdiff.cc
new file mode 100644
index 0000000..953435a
--- /dev/null
+++ b/rasodmg/test/defdiff.cc
@@ -0,0 +1,537 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/*
+ * defdiff.cc
+ *
+ * Compare to DEF files and returns 0 for succes, otherwise 1
+ *
+ * Parameters:
+ *
+ * --inputfilename <src-file>
+ * the filename of the src file, mandatory
+ * --outputfilename <dest-file>
+ * the filename of the dest file, mandatory
+ *
+ * --inputformat name
+ * name of DEF fromat(see data_foramat from mddtypes.hh)
+ * --inputformatparams params
+ * params used by convertFrom methods(see the heder file for you DEF from conversion)
+ * --outputformat name
+ * name of DEF fromat(see data_foramat from mddtypes.hh)
+ * --outputformatparams params
+ * params used by convertFrom methods(see the heder file for you DEF from conversion)
+ *
+ * --help
+ * print usage and exit
+ */
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#ifdef __GNUG__
+#include "raslib/template_inst.hh"
+#endif
+#endif
+
+#include "defutil.hh"
+
+const char* diffFileName = "defdiff.tif";
+
+const char* paramPrgHelp="--help";
+bool defPrgHelp=false;
+char* prgHelp=NULL;
+
+const char* paramSrcFileName="--srcfilename";
+bool defSrcFileName=false;
+char* srcFileName=NULL;
+
+const char* paramSrcFormat="--srcformat";
+bool defSrcFormat=false;
+char* srcFormatc=NULL;
+r_Data_Format srcFormat=r_Array;
+
+const char* paramSrcFormatParams="--srcformatparams";
+bool defSrcFormatParams=false;
+char *srcFormatParams=NULL;
+
+const char* paramDestFileName="--destfilename";
+bool defDestFileName=false;
+char *destFileName=NULL;
+
+const char* paramDestFormat="--destformat";
+bool defDestFormat=false;
+char *destFormatc=NULL;
+r_Data_Format destFormat=r_Array;
+
+const char* paramDestFormatParams="--destformatparams";
+bool defDestFormatParams=false;
+char *destFormatParams=NULL;
+
+//structures used for parseParam
+const int paramsNo=7;
+
+const char *paramsName[paramsNo]={ paramPrgHelp, paramSrcFileName, paramSrcFormat, paramSrcFormatParams,
+ paramDestFileName, paramDestFormat, paramDestFormatParams};
+
+bool *paramsPresent[paramsNo]={ &defPrgHelp, &defSrcFileName, &defSrcFormat, &defSrcFormatParams,
+ &defDestFileName, &defDestFormat, &defDestFormatParams};
+
+char **paramsValue[paramsNo]={ &prgHelp, &srcFileName, &srcFormatc, &srcFormatParams,
+ &destFileName, &destFormatc, &destFormatParams};
+
+void printStatus()
+{
+ cout << "defdiff parameters list:" << endl;
+ for (int i=0; i<paramsNo; i++)
+ cout << "--Name='" << paramsName[i]
+ << "' Present=" << ((*paramsPresent[i])? "true": "false")
+ << " Value='" << (*paramsValue[i]?*paramsValue[i]: "null") << "'" << endl;
+}
+
+void printUsage()
+{
+ char* fileNameSrc="test.bmp";
+ char* fileNameDest="test.tiff";
+
+ cout << "defdiff v 0.1 - RasDaMan Data Exchange Format Difference Utility" << endl;
+ cout << "Description: Returns " << EXIT_SUCCESS << " for succes, otherwise " << EXIT_FAILURE << endl;
+ cout << "If it is possible it will create a tiff file with the difference, called " << diffFileName << endl;
+ cout << "Usage options:" << endl;
+ cout << " " << paramSrcFileName << " <src-file> ... the filename used as src mandatory" << endl;
+ cout << " " << paramSrcFormat << " name ... name of DEF fromat(see data_foramat from mddtypes.hh)," << endl;
+ cout << " default Array" << endl;
+ cout << " " << paramSrcFormatParams << " params ... params used by convertFrom methods(see the header file" << endl;
+ cout << " for you DEF from conversion), default NULL" << endl;
+ cout << " " << paramDestFileName << " <dest-file> ... the filename used as dest mandatory" << endl;
+ cout << " " << paramDestFormat << " name ... name of DEF fromat(see data_foramat from mddtypes.hh)," << endl;
+ cout << " default Array" << endl;
+ cout << " " << paramDestFormatParams << " params ... params used by convertFrom methods(see the header file" << endl;
+ cout << " for you DEF from conversion), default NULL" << endl;
+ cout << " " << paramPrgHelp << " ... this help" << endl;
+ cout << "For example:" << endl;
+ cout << "defdiff " << paramSrcFileName << " " << fileNameSrc << " " << paramSrcFormat << " " << format_name_bmp <<" "
+ << paramDestFileName << " " << fileNameDest << " " << paramDestFormat <<" " << format_name_tiff << endl;
+ cout << "Report bugs to liviu.coman@active­knowledge.com" << endl;
+
+}
+
+int checkParam(int& paramIndex, char** param)
+{
+ int i=0;
+ while(i<paramsNo)
+ {
+ if(!strcmp(param[paramIndex], paramsName[i]))
+ break;
+ i++;
+ }
+
+ if(i==paramsNo)
+ {
+ cout << "checkParam(...) error processing parameters: parameter "
+ << param[paramIndex] << " is unknown!" << endl;
+ return EXIT_FAILURE;
+ }
+ if(*paramsPresent[i])
+ {
+ cout << "checkParam(...) error processing parameters: parameter "
+ << param[paramIndex] << " is present more than once!" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(paramsName[i]!=paramPrgHelp)
+ {
+ *paramsPresent[i]=true;
+ paramIndex++;
+ *paramsValue[i]=param[paramIndex];
+ }
+ else
+ *paramsPresent[i]=true;
+
+ return EXIT_SUCCESS;
+}
+
+int parseParams(int argc, char** argv)
+{
+ int argIndex=0;
+ if (argc==1)
+ {
+ cout << "parseParams(...) parameters " << paramSrcFileName << " <src-file> and "
+ << paramDestFileName << " <dest-file> are mandatatory!" << endl;
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ argIndex=1;
+ while(argIndex<argc)
+ {
+ if(checkParam(argIndex, argv)!=EXIT_SUCCESS)
+ break;
+ argIndex++;
+ }
+ if(argIndex<argc)
+ return EXIT_FAILURE;
+
+ //check rule
+ if((defSrcFileName && defDestFileName) || (defPrgHelp))
+ return EXIT_SUCCESS;
+ else
+ {
+ cout << "parseParams(...) parameters " << paramSrcFileName << " <src-file> and "
+ << paramDestFileName << " <dest-file> are mandatatory!" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+}
+
+int validateParams()
+{
+ if(defSrcFormat)
+ {
+ srcFormat = get_data_format_from_name(srcFormatc);
+ if((srcFormat!=r_Array) &&
+ (!r_Convertor_Factory::is_supported(srcFormat)))
+ {
+ cout << "validateParams() conversion of " << srcFormatc << " not supported" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+ if(defDestFormat)
+ {
+ destFormat = get_data_format_from_name(destFormatc);
+ if((destFormat!=r_Array) &&
+ (!r_Convertor_Factory::is_supported(destFormat)))
+ {
+ cout << "validateParams() conversion " << destFormatc << " not supported" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int compareDEFs()
+{
+ char *dataSrc=NULL, *dataDest=NULL;
+ r_ULong dataSrcSize=0, dataDestSize=0;
+ r_ULong arraySrcSize=0, arrayDestSize=0;
+ r_Bytes basetypeSrcSize=0, basetypeDestSize=0;
+ r_convDesc descSrc, descDest;
+ r_Type::r_Type_Id basetypeSrcId=r_Type::UNKNOWNTYPE, basetypeDestId=r_Type::UNKNOWNTYPE;
+
+ //init conversion result data
+ initConvDesc(descSrc);
+ initConvDesc(descDest);
+
+ //read files
+ if(readFile(srcFileName, &dataSrc, dataSrcSize)!=EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(readFile(destFileName, &dataDest, dataDestSize)!=EXIT_SUCCESS)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ return EXIT_FAILURE;
+ }
+
+ //convert if necessary
+ if(srcFormat !=r_Array)
+ {
+ r_Minterval srcIv(1);
+ r_Type* srcType=NULL;
+
+ srcIv << r_Sinterval((r_Range)0, (r_Range)(dataSrcSize -1));
+ srcType=r_Convertor::get_external_type(r_Convertor::ctype_char);
+
+ if(convertFrom(srcFormat, srcFormatParams, dataSrc,
+ srcIv, srcType, descSrc) != EXIT_SUCCESS)
+ {
+ delete srcType;
+ srcType=NULL;
+ delete [] dataSrc;
+ dataSrc=NULL;
+ delete [] dataDest;
+ dataDest=NULL;
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ //we don't need this anymore
+ delete [] dataSrc;
+ dataSrc=NULL;
+ delete srcType;
+ srcType=NULL;
+ }
+ }
+
+ if(destFormat !=r_Array)
+ {
+ r_Minterval destIv(1);
+ r_Type* destType=NULL;
+
+ destIv << r_Sinterval((r_Range)0, (r_Range)(dataDestSize -1));
+ destType=r_Convertor::get_external_type(r_Convertor::ctype_char);
+
+ if(convertFrom(destFormat, destFormatParams, dataDest,
+ destIv, destType, descDest) != EXIT_SUCCESS)
+ {
+ delete destType;
+ destType=NULL;
+ delete [] dataDest;
+ dataDest=NULL;
+ if(srcFormat==r_Array)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ }
+ else
+ {
+ dataSrc=NULL;
+ cleanConvDesc(descSrc);
+ }
+
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ //we don't need this anymore
+ delete [] dataDest;
+ dataDest=NULL;
+ delete destType;
+ destType=NULL;
+ }
+ }
+
+ //check domain
+ if((srcFormat!=r_Array) &&
+ (destFormat!=r_Array) &&
+ (descSrc.destInterv != descDest.destInterv))
+ {
+ cout << "compareDEFs() source domain " << descSrc.destInterv << " != destination domain " << descDest.destInterv << endl;
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ //check if celltype is a basetype
+ if((srcFormat!=r_Array) &&
+ (!descSrc.destType->isBaseType()))
+ {
+ cout << "compareDEFs() source type " << basetypeSrcId << " is not a base type" << endl;
+ if(destFormat==r_Array)
+ {
+ delete [] dataDest;
+ dataDest=NULL;
+ }
+ else
+ cleanConvDesc(descDest);
+ cleanConvDesc(descSrc);
+ return EXIT_FAILURE;
+ }
+
+ if((destFormat!=r_Array) &&
+ (!descDest.destType->isBaseType()))
+ {
+ cout << "compareDEFs() destination type " << basetypeDestId << " is not a base type" << endl;
+ if(srcFormat==r_Array)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ }
+ else
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ //stoare info about types
+ if(srcFormat!=r_Array)
+ {
+ basetypeSrcId=descSrc.destType->type_id();
+ basetypeSrcSize=((r_Base_Type*)descSrc.destType)->size();
+ }
+ if(destFormat!=r_Array)
+ {
+ basetypeDestId=descDest.destType->type_id();
+ basetypeDestSize=((r_Base_Type*)descDest.destType)->size();
+ }
+
+ if((srcFormat!=r_Array) &&
+ (destFormat!=r_Array))
+ {
+ //FIXME basetypeSrcId!=basetypeDestId to powerfull
+ if(basetypeSrcId!=basetypeDestId)
+ cout << "compareDEFs() warning: source type " << basetypeSrcId
+ << " != destination type " << basetypeDestId << endl;
+
+ if(basetypeSrcSize!=basetypeDestSize)
+ {
+ cout << "comparetDEFs() source type " << descSrc.destType->name() << " != destination type " << descDest.destType->name() << endl;
+ cout << "source type size" << basetypeSrcSize << " != destination type size" << basetypeDestSize << endl;
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ if((basetypeSrcId == r_Type::STRUCTURETYPE) &&
+ (basetypeDestId == r_Type::STRUCTURETYPE) &&
+ (compareStructure((r_Structure_Type*)descSrc.destType, (r_Structure_Type*)descDest.destType) !=EXIT_SUCCESS))
+ {
+ cout << "compareDEFs() source structure type != destination structure type" << endl;
+ cout << "Source type is: " << (*(r_Structure_Type*)(descSrc.destType)) << endl;
+ cout << "Destination type is:" << (*(r_Structure_Type*)(descSrc.destType)) << endl;
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+ }
+
+ if(srcFormat!=r_Array)
+ {
+ arraySrcSize=descSrc.destInterv.cell_count() * basetypeSrcSize;
+ dataSrc=descSrc.dest;
+ }
+ else
+ arraySrcSize=dataSrcSize;
+
+ if(destFormat!=r_Array)
+ {
+ arrayDestSize=descDest.destInterv.cell_count() * basetypeDestSize;
+ dataDest=descDest.dest;
+ }
+ else
+ arrayDestSize=dataDestSize;
+
+ if(arraySrcSize!=arrayDestSize)
+ {
+ cout << "compareDEFs() source data size " << arraySrcSize << " != " << " destination data size " << arrayDestSize << endl;
+ delete [] dataSrc;
+ dataSrc=NULL;
+ delete [] dataDest;
+ dataDest=NULL;
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ if(memcmp(dataSrc, dataDest, arraySrcSize))
+ {
+ cout << "compareDEFs() source and destination data are different" << endl;
+ r_convDesc descDiff;
+ r_ULong diffSize=0;
+ initConvDesc(descDiff);
+ //do diff
+ for(int i=0; i< arraySrcSize; i++)
+ dataDest[i]-=dataSrc[i];
+ if(convertTo(r_TIFF, NULL, dataDest, descDest.destInterv,
+ descDest.destType, descDiff) != EXIT_SUCCESS)
+ {
+ cout << "compareDEFs() error building the difference tiff file" << endl;;
+ }
+ else
+ {
+ diffSize=descDiff.destInterv.cell_count() * ((r_Base_Type*)descDiff.destType)->size();
+ if(writeFile(diffFileName, (const char**)&descDiff.dest, diffSize)!=EXIT_SUCCESS)
+ cout << "compareDEFs() error building the difference tiff file" << endl;;
+ cleanConvDesc(descDiff);
+ }
+
+ //clean up
+ if(srcFormat==r_Array)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ }
+ else
+ {
+ dataSrc=NULL;
+ cleanConvDesc(descSrc);
+ }
+ if(destFormat==r_Array)
+ {
+ delete [] dataDest;
+ dataDest=NULL;
+ }
+ else
+ {
+ dataDest=NULL;
+ cleanConvDesc(descDest);
+ }
+ return EXIT_FAILURE;
+ }
+
+ cout << "compareDEFs() source and destination data are identic" << endl;
+
+ //clean up
+ if(srcFormat==r_Array)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ }
+ else
+ {
+ dataSrc=NULL;
+ cleanConvDesc(descSrc);
+ }
+ if(destFormat==r_Array)
+ {
+ delete [] dataDest;
+ dataDest=NULL;
+ }
+ else
+ {
+ dataDest=NULL;
+ cleanConvDesc(descDest);
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int processRequest()
+{
+ if(validateParams() != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ return compareDEFs();
+}
+
+int main(int argc, char **argv)
+{
+ if(parseParams(argc, argv)!=EXIT_SUCCESS)
+ {
+ printUsage();
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ if(!defPrgHelp)
+ {
+#ifdef RMANDEBUG
+ printStatus();
+#endif
+ return processRequest();
+ }
+ else
+ {
+ printUsage();
+ return EXIT_SUCCESS;
+ }
+ }
+}
diff --git a/rasodmg/test/defutil.hh b/rasodmg/test/defutil.hh
new file mode 100644
index 0000000..b30a8a5
--- /dev/null
+++ b/rasodmg/test/defutil.hh
@@ -0,0 +1,412 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/*
+ * defutil.hh
+ *
+ * COMMENTS
+ * Common functions used by defxxx programs
+*/
+
+
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+using std::cout;
+using std::endl;
+
+#include "raslib/mddtypes.hh"
+#include "raslib/structuretype.hh"
+#include "raslib/odmgtypes.hh"
+#include "raslib/minterval.hh"
+#include "raslib/parseparams.hh"
+#include "conversion/convertor.hh"
+#include "conversion/convfactory.hh"
+
+//--I/O file
+int readFile(const char* fileName, char **data, r_ULong& dataSize)
+{
+ FILE *pFile=NULL;
+
+ if(fileName==NULL)
+ {
+ cout << "readFile(...) fileName is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(*data!=NULL)
+ {
+ cout << "readFile(...) data is not null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ pFile=fopen(fileName, "rb");
+ if(pFile==NULL)
+ {
+ cout << "readFile(...) unable to open file " << fileName << endl;
+ return EXIT_FAILURE;
+ }
+
+ fseek(pFile, 0, SEEK_END);
+ dataSize=ftell(pFile);
+
+ *data=new char[dataSize];
+ if(*data==NULL)
+ {
+ cout << "readFile(...) unable to claim memory for file " << fileName << endl;
+ fclose(pFile);
+ return EXIT_FAILURE;
+ }
+
+ fseek(pFile, 0, SEEK_SET);
+ fread(*data, 1, dataSize, pFile);
+
+ fclose(pFile);
+ return EXIT_SUCCESS;
+}
+
+int writeFile(const char* fileName, const char **data, r_ULong& dataSize)
+{
+ FILE *pFile=NULL;
+
+ if(fileName==NULL)
+ {
+ cout << "writeFile(...) fileName is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(*data==NULL)
+ {
+ cout << "writeFile(...) data is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!dataSize)
+ {
+ cout << "writeFile(...) dataSize is zero" << endl;
+ return EXIT_FAILURE;
+ }
+
+ pFile=fopen(fileName, "wb");
+ if(pFile==NULL)
+ {
+ cout << "writeFile(...) unable to open file" << fileName << endl;
+ return EXIT_FAILURE;
+ }
+
+ fwrite(*data, 1, dataSize, pFile);
+
+ fclose(pFile);
+ pFile=NULL;
+
+ return EXIT_SUCCESS;
+}
+
+//ConvertFrom/To r_Array data
+int convertFrom(r_Data_Format fmt, const char* fmtParams,
+ const char* data, const r_Minterval& dataDom,
+ const r_Type* dataType, r_convDesc& desc)
+{
+ r_Storage_Man_CPP mySM;
+ r_Convertor *conv=NULL;
+
+ if(data==NULL)
+ {
+ cout << "convertFrom(...) data is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(dataType==NULL)
+ {
+ cout << "convertFrom(...) dataType is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ conv=r_Convertor_Factory::create(fmt, data, dataDom, dataType);
+ conv->set_storage_handler(mySM);
+ }
+ catch(r_Error& err)
+ {
+ cout << "convertFrom(...) request for convertor " << fmt << " failed" << endl
+ << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ desc = conv->convertFrom(fmtParams);
+ }
+ catch(r_Error &err)
+ {
+ cout << "convertFrom(...) conversion from " << fmt << " format to r_Array format failed! " << endl
+ << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ if(conv)
+ {
+ delete conv;
+ conv=NULL;
+ }
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int convertTo(r_Data_Format fmt, const char* fmtParams,
+ const char* data, const r_Minterval& dataDom,
+ const r_Type* dataType, r_convDesc& desc)
+{
+ r_Storage_Man_CPP mySM;
+ r_Convertor *conv=NULL;
+
+ if(data==NULL)
+ {
+ cout << "convertTo(...) data is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(dataType==NULL)
+ {
+ cout << "convertTo(...) dataType is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ conv=r_Convertor_Factory::create(fmt, data, dataDom, dataType);
+ conv->set_storage_handler(mySM);
+ }
+ catch(r_Error& err)
+ {
+ cout << "convertTo(...) request for convertor " << fmt << " failed! " << endl
+ << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ desc = conv->convertTo(fmtParams);
+ }
+ catch(r_Error &err)
+ {
+ cout << "convertTo(...) conversion from " << fmt << " format to r_Array format failed! " << endl
+ << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ if(conv)
+ {
+ delete conv;
+ conv=NULL;
+ }
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
+//init/deinit ConvDesc
+void cleanConvDesc(r_convDesc& desc)
+{
+ desc.src=NULL;
+ desc.srcType=NULL;
+ if(desc.dest!=NULL)
+ {
+ delete []desc.dest;
+ desc.dest=NULL;
+ }
+ if(desc.destType!=NULL)
+ {
+ delete desc.destType;
+ desc.destType=NULL;
+ }
+ desc.baseType = r_Convertor::ctype_void;
+}
+
+void initConvDesc(r_convDesc& desc)
+{
+ desc.dest=NULL;
+ desc.src=NULL;
+ desc.srcType=NULL;
+ desc.destType=NULL;
+ desc.baseType = r_Convertor::ctype_void;
+}
+
+//decode a minterval from a string
+int decodeMinterval(const char* src, r_Minterval& srcIv)
+{
+ if(!src)
+ {
+ cout << "decodeMinterval(...) src is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ srcIv=r_Minterval(src);
+ }
+ catch(r_Error& err)
+ {
+ cout << "decodeMinterval(...) error while constructing the minterval from " << src << endl;
+ cout << "Error " << err.get_errorno() << ":" << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+//decode a type from a string
+int decodeType(const char* src, r_Type*& srcType)
+{
+ if(!src)
+ {
+ cout << "decodeType(...) src is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(srcType)
+ {
+ cout << "decodeType(...) src is not null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ srcType=r_Type::get_any_type(src);
+ }
+ catch(r_Error& err)
+ {
+ cout << "decodeType(...) error while constructing the type from " << src << endl;
+ cout << "Error " << err.get_errorno() << ":" << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!srcType)
+ {
+ cout << "decodeType(...) the type retrived with r_Type::get_any_type(...) is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!srcType->isBaseType())
+ {
+ cout << "decodeType(...) the type retrived (" << srcType->type_id() << ") is not a base type" << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+//parse r_Array params 'domain=<domain_str>,type=<type_str>'
+int parseArrayParams(const char* formatparams,
+ const char* fpDomain,
+ const char* fpType,
+ char*& domain,
+ char*& type)
+{
+ const int fpNo=2;
+ r_Parse_Params params(fpNo);
+
+ //parameter validation
+ if(formatparams==NULL) {
+ cout << "parseArrayParams(...) formatparams is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(fpDomain==NULL){
+ cout << "parseArrayParams(...) fpDomain is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(fpType==NULL){
+ cout << "parseArrayParams(...) fpType is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(domain!=NULL){
+ cout << "parseArrayParams(...) domain is not null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(type!=NULL){
+ cout << "parseArrayParams(...) type is not null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ params.add(fpDomain, &domain, r_Parse_Params::param_type_string);
+ params.add(fpType, &type, r_Parse_Params::param_type_string);
+
+ if(params.process(formatparams) != fpNo)
+ {
+ cout << "parseArrayParams(...) error parsing " << formatparams << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+//compare 2 structure type
+int compareStructure(r_Structure_Type* src, r_Structure_Type* dest)
+{
+ r_Structure_Type::attribute_iterator iterSrc, iterDest;
+
+ if(src==NULL)
+ {
+ cout << "compareStructure(...) src is null !"<< endl;
+ return EXIT_FAILURE;
+ }
+
+ if(dest==NULL)
+ {
+ cout << "compareStructure(...) dest is null !"<< endl;
+ return EXIT_FAILURE;
+ }
+
+ iterSrc=src->defines_attribute_begin();
+ iterDest=dest->defines_attribute_begin();
+ while( iterSrc!=src->defines_attribute_end() || iterDest!=dest->defines_attribute_end())
+ {
+ r_Type::r_Type_Id typeSrcId=r_Type::UNKNOWNTYPE, typeDestId=r_Type::UNKNOWNTYPE;
+ typeSrcId=(*iterSrc).type_of().type_id();
+ typeDestId=(*iterDest).type_of().type_id();
+
+ if(typeSrcId!=typeDestId)
+ {
+ cout << "comparaStructure(...) typeSrcId(" << typeSrcId
+ << ") != typeDestId(" << typeDestId << ") !"<< endl;
+ return EXIT_FAILURE;
+ }
+
+ if((typeSrcId== r_Type::STRUCTURETYPE) &&
+ (compareStructure((r_Structure_Type*)(&((*iterSrc).type_of())),
+ (r_Structure_Type*)(&((*iterDest).type_of()))) != EXIT_SUCCESS))
+ return EXIT_FAILURE;
+
+ iterSrc++;
+ iterDest++;
+ }
+ if((iterSrc==src->defines_attribute_end()) &&
+ (iterDest==dest->defines_attribute_end()))
+ return EXIT_SUCCESS;
+ else
+ {
+ if(iterSrc!=src->defines_attribute_end())
+ cout << "compareStructure(...) src has more atributes then dest!" << endl;
+ else
+ cout << "compareStructure(...) dest has more atributes then src!" << endl;
+ return EXIT_FAILURE;
+ }
+}
diff --git a/rasodmg/test/deletecollection.cc b/rasodmg/test/deletecollection.cc
new file mode 100644
index 0000000..6cade1e
--- /dev/null
+++ b/rasodmg/test/deletecollection.cc
@@ -0,0 +1,720 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************
+ *
+ * SOURCE: deletecollection.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE:
+ *
+ *
+ ************************************************************/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream.h>
+#endif
+
+#include <iostream>
+#include <iomanip.h>
+#include <string.h>
+#include <fstream.h>
+
+#include <math.h>
+
+#ifdef __VISUALC__
+ #define __EXECUTABLE__
+#endif
+
+#include "include/basictypes.hh"
+#include "raslib/type.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/alignedtiling.hh"
+
+#ifdef __VISUALC__
+ #undef __EXECUTABLE__
+#endif
+
+static int INIT = 0;
+
+static long minNo = 0;
+static long maxNo = 0;
+static ifstream fileStream;
+
+r_ULong initWithCounter( const r_Point& /*pt*/ )
+{
+ return INIT++;
+}
+
+
+r_Char initWithCounterChar( const r_Point& /*pt*/ )
+{
+ return (r_Char) INIT++;
+}
+
+
+r_UShort initWithCounterUShort( const r_Point& /*pt*/ )
+{
+ return (r_UShort) INIT++;
+}
+
+
+
+r_ULong initWithCrossfoot( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ for( r_Dimension i=0; i< pt.dimension(); i++ )
+ value += (r_ULong)pt[i];
+
+ return value;
+}
+
+
+r_ULong initWithCoordinates( const r_Point& pt )
+{
+ r_ULong value=0;
+ r_ULong factor=1;
+
+ for( int i=pt.dimension()-1; i >= 0; i-- )
+ {
+ value += (r_ULong)(factor * pt[i]);
+ factor *= 100;
+ }
+
+ return value;
+}
+
+
+
+r_Char initWithCurve( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ for( r_Dimension i=0; i < pt.dimension(); i++ )
+ value += (r_Char)( 255* sin( .25 * (float)pt[i] ) );
+
+ return (r_Char)value;
+}
+
+
+
+r_ULong initWithColorCube( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ if( pt.dimension() == 3 )
+ value = ((unsigned long)(pt[0]) << 16) + ((unsigned long)(pt[1]) << 8) + (unsigned long)(pt[2]);
+
+ return value;
+}
+
+
+r_Char initWithRandomChar( const r_Point& /*pt*/ )
+{
+ // rand creates numbers between 0 and 32767
+ unsigned long number = rand();
+ double factor = (maxNo - minNo)/32767.0;
+
+ return (r_Char)(minNo + (number * factor));
+}
+
+r_ULong initWithRandomULong( const r_Point& /*pt*/ )
+{
+ // rand creates numbers between 0 and 32767
+ unsigned long number = rand();
+ double factor = (maxNo - minNo)/32767.0;
+
+ return (r_ULong)(minNo + (number * factor));
+}
+
+
+r_Char initFromFile( const r_Point& /*pt*/ )
+{
+ char ch;
+
+ if( fileStream.get(ch) )
+ return ch;
+ else
+ return 0;
+}
+
+/*
+r_Ref< r_Marray<r_ULong> > readFile( r_Database& db )
+{
+ r_Ref< r_Marray<r_ULong> > image;
+ r_Minterval domain(3);
+ long dx, dy, dz, depth, cx, cy, cz;
+ int i;
+
+ ifstream fileStream( "hw8.full.vol" );
+ if( !fileStream )
+ {
+ cout << "Error: File not found." << endl;
+ exit(-1);
+ }
+
+ // read the first 16 bytes
+ char charDummy;
+ for( i=0; i<16; i++ )
+ fileStream >> charDummy;
+
+ dx = 256;
+ dy = 256;
+ dz = 20;
+ depth = 8;
+
+ domain << r_Sinterval( 0l, (long)(dx-1) ) << r_Sinterval( 0l, (long)(dy-1) ) << r_Sinterval( 0l, (long)(dz-1) );
+
+ cout << domain << "... "; cout.flush();
+
+ image = new( &db ) r_Marray<r_ULong>( domain );
+
+ unsigned long* dataPtr = (unsigned long*)image->get_array();
+
+ r_Point pt(3);
+
+ // for( i=0; i<dx*dy*(221-dz); i++ )
+ // fileStream >> charDummy;
+
+ for( cz = 0; cz < dz; cz++ )
+ {
+ pt[2] = cz;
+ for( cy = 0; cy < dy; cy++ )
+ {
+ pt[1] = cy;
+ for( cx = 0; cx < dx; cx++ )
+ {
+ unsigned char ch;
+ fileStream.get(ch);
+
+ pt[0] = cx;
+ dataPtr[domain.cell_offset(pt)] = ((unsigned long)ch << 16) +
+ ((unsigned long)ch << 8) +
+ ((unsigned long)ch);
+ }
+ }
+ }
+
+ fileStream.close();
+
+ return image;
+}
+*/
+
+
+void printColl( r_Ref< r_Set< r_Ref< r_GMarray > > >& image_set, int output, int hexOutput )
+{
+ cout << "Collection" << endl;
+ cout << " Oid...................: " << image_set->get_oid() << endl;
+ cout << " Type Name.............: " << image_set->get_object_name() << endl;
+ cout << " Type Structure........: "
+ << ( image_set->get_type_structure() ? image_set->get_type_structure() : "<nn>" ) << endl;
+ cout << " Type Schema...........: " << flush;
+ if( image_set->get_type_schema() )
+ image_set->get_type_schema()->print_status( cout );
+ else
+ cout << "<nn>" << flush;
+ cout << endl;
+ cout << " Number of entries.....: " << image_set->cardinality() << endl;
+ cout << " Element Type Schema...: " << flush;
+ if( image_set->get_element_type_schema() )
+ image_set->get_element_type_schema()->print_status( cout );
+ else
+ cout << "<nn>" << flush;
+ cout << endl;
+
+ r_Iterator< r_Ref< r_GMarray > > iter = image_set->create_iterator();
+
+ cout << endl;
+ for ( int i=1 ; iter.not_done(); iter++, i++ )
+ {
+ // do not dereference the object
+ cout << "Image " << i << " oid: " << (*iter).get_oid() << endl;
+
+ if( output )
+ {
+ (*iter)->print_status( cout, hexOutput );
+ cout << endl;
+ }
+ }
+ cout << endl;
+}
+
+
+
+int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex )
+{
+ int found = 0;
+ int i=1;
+
+ while( !found && i<argc )
+ found = !strcmp( searchText, argv[i++] );
+
+ if( found && i<argc && !strchr(argv[i],'-') )
+ optionValueIndex = i;
+ else
+ optionValueIndex = 0;
+
+ return found;
+}
+
+
+
+int main( int argc, char** argv )
+{
+ int optionValueIndex=0;
+ int testbed = 0;
+ unsigned long tileSize=0;
+ r_Minterval tileConfig;
+ int compressed=0;
+
+ char serverName[255];
+ char baseName[255];
+ char collName[255];
+ char setTypeName[255] = "";
+ char mddTypeName[255] = "";
+ char fileName[255]="";
+
+ if( argc < 4 || checkArguments( argc, argv, "-h", optionValueIndex ) )
+ {
+ cout << "Usage: test_insert3 server_name base_name collection_name [options]" << endl << endl;
+ cout << "Options: -h ... this help" << endl;
+ cout << " -settype <typename> ... type name used for creation of a new set." << endl;
+ cout << " -mddtype <typename> ... type name used for creation of a new mdd object." << endl;
+ cout << " -testbed ... turn on output for testbed" << endl;
+ cout << " -tileconf ... tile configuration" << endl;
+ cout << " -tilesize ... tile size" << endl;
+ cout << " -file <filename> ... file name used to read data from a file" << endl;
+ cout << " -compressed ... inserts MDD in compressed format" << endl;
+ cout << endl;
+ return 0;
+ }
+
+ strcpy( serverName, argv[1] );
+ strcpy( baseName, argv[2] );
+ strcpy( collName, argv[3] );
+
+ if( checkArguments( argc, argv, "-settype", optionValueIndex ) && optionValueIndex )
+ strcpy( setTypeName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-mddtype", optionValueIndex ) && optionValueIndex )
+ strcpy( mddTypeName, argv[optionValueIndex] );
+
+ testbed = checkArguments( argc, argv, "-testbed", optionValueIndex );
+
+ if( checkArguments( argc, argv, "-tileconf", optionValueIndex ) && optionValueIndex )
+ tileConfig = r_Minterval( argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-tilesize", optionValueIndex ) && optionValueIndex )
+ tileSize = strtoul( argv[optionValueIndex], (char **)NULL, 10 ) ;
+
+ if( checkArguments( argc, argv, "-file", optionValueIndex ) && optionValueIndex )
+ strcpy( fileName, argv[optionValueIndex] );
+
+ compressed = checkArguments( argc, argv, "-compressed", optionValueIndex );
+
+ cout << endl << endl;
+ cout << "Insertion of one MDD into the database" << endl;
+ cout << "======================================" << endl << endl;
+
+ r_Database db;
+ r_Transaction ta;
+ r_Ref< r_Set< r_Ref< r_GMarray > > > image_set;
+ r_Ref< r_GMarray > image;
+ r_Minterval domain;
+ r_Dimension dim;
+ r_Range low, high;
+ unsigned long initMode, initValue;
+
+ RGBPixel rgbValue = { 1, 2, 3 };
+
+ db.set_servername( serverName );
+
+ try
+ {
+ /*
+ cout << "MDD Initialization: 0 - Marray<r_ULong> with constant" << endl;
+ cout << " 1 - Marray<r_ULong> with counter" << endl;
+ cout << " 2 - Marray<r_ULong> with coordinates" << endl;
+ cout << " 3 - Marray<r_ULong> with crossfoot" << endl;
+ cout << " 4 - Marray<r_ULong> with color cube" << endl << endl;
+
+ cout << " 5 - Marray<r_Char> with constant" << endl;
+ cout << " 6 - insert RGBImage with constant" << endl;
+ cout << " 7 - Marray<r_Char> with 255*( sin(.25*x1) + ... + sin(.25*xn) )" << endl;
+
+ cout << " 8 - Marray<r_ULong> read a file (hw8.full.vol)" << endl;
+ cout << " 9 - Create just an empty collection of type Marray<r_ULong>" << endl;
+ cout << " 10 - Delete collection of type GMarray" << endl;
+ cout << " 11 - Delete an object of collection" << endl;
+
+ cout << " 13 - Marray<r_Char> with counter" << endl;
+ cout << " 14 - Marray<r_Char> with random numbers" << endl;
+ cout << " 15 - Marray<r_UShort> with counter" << endl;
+ cout << " 16 - Marray<r_ULong> with random numbers" << endl;
+ cout << " 17 - Marray<r_Boolean>" << endl;
+ cout << " 18 - Marray<r_Char> from file" << endl;
+
+ cin >> initMode;
+ cout << endl;
+ */
+ initMode = 10;
+
+ if( initMode == 18 )
+ {
+ fileStream.open( fileName );
+ if( !fileStream )
+ {
+ cout << "Error: File " << fileName << " not found." << endl;
+ exit(-1);
+ }
+ }
+
+ if( initMode == 0 || initMode == 5 || initMode == 17 )
+ {
+ cout << "Constant value : ";
+ cin >> initValue;
+ cout << endl;
+ }
+ if( initMode <= 7 || initMode >= 13 )
+ {
+ cout << "Number of dimensions : ";
+ cin >> dim;
+ cout << endl;
+
+ domain = r_Minterval(dim);
+
+ for( r_Dimension i = 1; i<=dim ; i++ )
+ {
+ cout << "Dimension " << setw(2) << i << " lower bound ";
+ cin >> low;
+ cout << " upper bound ";
+ cin >> high;
+
+ domain << r_Sinterval( low, high );
+ }
+
+ cout << endl;
+ }
+
+ if( initMode == 14 || initMode == 16 )
+ {
+ cout << "Minimum number : ";
+ cin >> minNo;
+ cout << endl;
+
+ cout << "Maximum number : ";
+ cin >> maxNo;
+ cout << endl;
+ }
+
+ cout << "Opening Database " << baseName << " on " << serverName << "... "; cout.flush();
+ db.open( baseName );
+ cout << "OK" << endl;
+
+ cout << "Starting Transaction ... " << flush;
+ ta.begin();
+ cout << "OK" << endl;
+
+ cout << "Opening the set ... " << flush;
+
+ if( initMode == 10 || initMode == 11 )
+ {
+ //
+ // get the set
+ //
+
+ try{
+ image_set = db.lookup_object( collName );
+ }
+ catch( r_Error &obj )
+ {
+ cout << "FAILED" << endl;
+ cout << obj.what() << endl;
+ return -1;
+ }
+
+ cout << "OK" << endl;
+
+ if( initMode == 10 )
+ {
+ // delete the set
+
+ if( !image_set.is_null() )
+ image_set.delete_object();
+ // delete image_set; (not implemented yet)
+ }
+ else
+ {
+ int imageNo=0;
+
+ printColl( image_set, 0, 0 );
+
+ cout << "Please enter the image number to delete: ";
+ cin >> imageNo;
+ cout << endl;
+
+ r_Iterator< r_Ref< r_GMarray > > iter = image_set->create_iterator();
+
+ for ( int i=1; iter.not_done() && i<imageNo; iter++, i++ );
+
+ if( imageNo && iter.not_done() )
+ {
+ image_set->remove_element( *iter );
+ cout << "MDD removed." << endl;
+ }
+ else
+ cout << "Number not valid." << endl << endl;
+ }
+ }
+ else
+ {
+ //
+ // get set
+ //
+
+ try{
+ image_set = db.lookup_object( collName );
+ }
+ catch( r_Error& /*obj*/ )
+ {
+ cout << "FAILED" << endl;
+ // cout << obj.what() << endl;
+
+ //
+ // set doesn't exist -> create the set
+ //
+
+ cout << "Create the set ... " << flush;
+
+ if( initMode == 5 || initMode == 7 || initMode == 13 || initMode == 14 || initMode == 18 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "GreySet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_Char> > >;
+ }
+ else if( initMode == 6 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "RGBSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<RGBPixel> > >;
+ }
+ else if( initMode == 15 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "UShortSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_UShort> > >;
+ }
+ else if( initMode == 17 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "BoolSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_Boolean> > >;
+ }
+ else
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "ULongSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_ULong> > >;
+ }
+
+ // create a name for the persistent set in order to be able to look it up again
+ db.set_object_name( *image_set, collName );
+ }
+
+ cout << " with type name " << setTypeName << " ... OK" << endl;
+
+ cout << "OId of the set is " << image_set->get_oid() << " ... " << endl;
+
+ if( initMode <= 9 || initMode >= 13 )
+ {
+ cout << "Creating an image ..." << flush;
+
+ // create storage layout object
+ r_Storage_Layout* stl = 0;
+ if( tileSize )
+ stl = new r_Storage_Layout( new r_Aligned_Tiling( tileConfig, tileSize ) );
+
+ if( compressed )
+ {
+ if( !stl )
+ stl = new r_Storage_Layout();
+
+ db.set_storage_format( r_ZLib );
+ }
+
+ // create the image
+ switch( initMode )
+ {
+ case 0:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, (r_ULong)initValue, stl );
+ break;
+ case 1:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithCounter, stl );
+ break;
+ case 2:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithCoordinates, stl );
+ break;
+ case 3:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithCrossfoot, stl );
+ break;
+ case 4:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithColorCube, stl );
+ break;
+ case 5:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, (r_Char)initValue, stl );
+ break;
+ case 6:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "RGBImage" );
+
+ image = new( &db, mddTypeName ) RGBImage( domain, rgbValue, stl );
+ break;
+ case 7:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initWithCurve, stl );
+ break;
+ case 13:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initWithCounterChar, stl );
+ break;
+ case 14:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initWithRandomChar, stl );
+ break;
+ case 15:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "UShortImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_UShort>( domain, &initWithCounterUShort, stl );
+ break;
+ case 16:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithRandomULong, stl );
+ break;
+ case 17:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "BoolImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Boolean>( domain, (r_Boolean)initValue, stl );
+ break;
+ case 18:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initFromFile, stl );
+ break;
+ default:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, (r_ULong)0, stl );
+ }
+
+ cout << "OId of the new image is " << image->get_oid() << endl;
+
+ cout << "Inserting one image with domain " << domain << " into collection " << collName << "..." << flush;
+ // put in into the persistent list
+ image_set->insert_element( image );
+ cout << "OK" << endl << endl;
+
+ if( testbed )
+ {
+ cout << endl << "Testbed output:" << endl;
+ cout << "-- Testbed: set_oid=" << image_set->get_oid() << endl;
+ cout << "-- Testbed: image_oid=" << image->get_oid() << endl;
+ cout << endl;
+ }
+
+ }
+ }
+
+ try
+ {
+ cout << "Committing Transaction ... " << flush;
+ ta.commit();
+ cout << "OK" << endl;
+ }
+ catch( r_Error &obj )
+ {
+ cerr << obj.what() << endl;
+ return -1;
+ }
+
+ cout << "Closing Database ... " << flush;
+ db.close();
+ cout << "OK" << endl;
+
+ if( initMode == 18 )
+ fileStream.close();
+ }
+ catch( r_Error& errorObj )
+ {
+ cerr << errorObj.what() << endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
diff --git a/rasodmg/test/earth.ql b/rasodmg/test/earth.ql
new file mode 100644
index 0000000..5de6f1d
--- /dev/null
+++ b/rasodmg/test/earth.ql
@@ -0,0 +1,68 @@
+// This test evaluates the effort for internal operations.
+// Run on different servers with optimization of operations and
+// multidimensional operations turned on and off.
+
+// no operation
+
+select img[0:799,0:799]
+from earth1 as img
+
+// one MDD operation
+
+select img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// two MDD operations
+
+select img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// three MDD operations
+
+select img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// four MDD operations
+
+select img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// five MDD operations
+
+select img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// no operation
+
+select img[0:799,0:799]
+from earth1 as img
+
+// one unary operation
+
+select not(img[0:799,0:799])
+from earth1 as img
+
+// no operation
+
+select img[0:799,0:799]
+from earth1 as img
+
+// one binary operation with a constant (+)
+
+select img[0:799,0:799] + 10c
+from earth1 as img
+
+// two binary operations with a constant (+, *)
+
+select (img[0:799,0:799] + 10c) * 10c
+from earth1 as img
+
+// three binary operations with a constant (+, *, -)
+
+select ((img[0:799,0:799] + 10c) * 10c) - 10c
+from earth1 as img
+
+// four binary operations with a constant (+, *, -, /)
+
+select (((img[0:799,0:799] + 10c) * 10c) - 10c) / 10c
+from earth1 as img
diff --git a/rasodmg/test/earth_16.ql b/rasodmg/test/earth_16.ql
new file mode 100644
index 0000000..c53508a
--- /dev/null
+++ b/rasodmg/test/earth_16.ql
@@ -0,0 +1,41 @@
+// Selection of images out of a collection with 15 800x800x8bit
+// images. There is one image each with only 255, 254, 253 as a
+// value. And there is one image each with one value each out of
+// 250, 251, 252. No other image contains value greater than 249.
+
+// one img with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE some_cell ( img = 252c )
+
+// two imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE some_cell ( img = 252c OR img = 251c )
+
+// three imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE some_cell ( img = 252c OR img = 251c OR img = 250c )
+
+// one img with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE all_cell ( img >= 255c )
+
+// two imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE all_cell ( img >= 254c )
+
+// three imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE all_cell ( img >= 253c )
+
diff --git a/rasodmg/test/earth_32.ql b/rasodmg/test/earth_32.ql
new file mode 100644
index 0000000..67145be
--- /dev/null
+++ b/rasodmg/test/earth_32.ql
@@ -0,0 +1,41 @@
+// Selection of images out of a collection with 15 800x800x8bit
+// images. There is one image each with only 255, 254, 253 as a
+// value. And there is one image each with one value each out of
+// 250, 251, 252. No other image contains value greater than 249.
+
+// one img with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE some_cell ( img = 252c )
+
+// two imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE some_cell ( img = 252c OR img = 251c )
+
+// three imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE some_cell ( img = 252c OR img = 251c OR img = 250c )
+
+// one img with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE all_cell ( img >= 255c )
+
+// two imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE all_cell ( img >= 254c )
+
+// three imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE all_cell ( img >= 253c )
+
diff --git a/rasodmg/test/earth_64.ql b/rasodmg/test/earth_64.ql
new file mode 100644
index 0000000..31cec45
--- /dev/null
+++ b/rasodmg/test/earth_64.ql
@@ -0,0 +1,41 @@
+// Selection of images out of a collection with 15 800x800x8bit
+// images. There is one image each with only 255, 254, 253 as a
+// value. And there is one image each with one value each out of
+// 250, 251, 252. No other image contains value greater than 249.
+
+// one img with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE some_cell ( img = 252c )
+
+// two imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE some_cell ( img = 252c OR img = 251c )
+
+// three imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE some_cell ( img = 252c OR img = 251c OR img = 250c )
+
+// one img with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE all_cell ( img >= 255c )
+
+// two imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE all_cell ( img >= 254c )
+
+// three imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE all_cell ( img >= 253c )
+
diff --git a/rasodmg/test/gen_pattern.cc b/rasodmg/test/gen_pattern.cc
new file mode 100644
index 0000000..4ce3abc
--- /dev/null
+++ b/rasodmg/test/gen_pattern.cc
@@ -0,0 +1,248 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: gen_pattern.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: generate patterns for r_StatTiling.
+ *
+ * COMMENTS:
+ * None
+*/
+
+/*
+ ATENTION: The format of the input file for using with this program is:
+
+ number_of_patterns minterval_domain
+ d_dim1 d_dim2 ... d_dimn
+ percentage minterval_pattern
+ ...
+
+ Example:
+
+ 1000 [1:800,1:600]
+ 10 10
+ 0.40 [10:600,30:300]
+ 0.60 [70:500,400:500]
+
+ Creates a file with 1000 patterns on a 800x600 domain.
+ The pixels are generated having borders with a maximum variation of
+ 10 pixels from the specified interest zones. And 2 interest zones
+ are specified, one for 40% of the patterns, another for 60%.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream.h>
+#include <time.h>
+#include "raslib/minterval.hh"
+#include "raslib/sinterval.hh"
+#include "raslib/dlist.hh"
+
+const int BUF_SIZE = 200;
+
+char* in_filename;
+char* out_filename;
+int total_patterns;
+int dim;
+int* delta;
+r_Minterval* domain;
+
+struct IArea
+{
+ r_Minterval iarea;
+ double percent;
+
+ IArea(r_Minterval& area, double percentage)
+ : iarea(area), percent(percentage)
+ {
+ }
+};
+
+DList<IArea*> IAreas;
+
+void parse(int argc, char** argv)
+{
+ if ((argc == 1) || ((argc == 2) && (strcmp(argv[1], "-h") == 0)))
+ {
+ cout << "Usage: " << argv[0] << " [input_filename] [output_filename]"
+ << endl;
+ exit(0);
+ }
+
+ if (argc != 3)
+ {
+ cout << "Usage: " << argv[0] << " [input_filename] [output_filename]"
+ << endl;
+ exit(0);
+ }
+
+ in_filename = argv[1];
+ out_filename = argv[2];
+}
+
+void get_specification()
+{
+ char buf[BUF_SIZE+1], buf2[BUF_SIZE+1];
+ double perc;
+
+ ifstream is(in_filename);
+ if (!is)
+ {
+ cout << "Could not open " << in_filename << "." << endl;
+ exit(0);
+ }
+
+ cout << "Reading parameters... " << endl;
+
+ is >> total_patterns;
+ is.getline(buf, BUF_SIZE);
+ domain = new r_Minterval(buf);
+ dim = domain->dimension();
+
+ if (total_patterns <= 0)
+ {
+ cout << "Invalid number of patterns: " << total_patterns << endl;
+ exit(0);
+ }
+
+ if (dim <= 0)
+ {
+ cout << "Invalid domain: " << *domain << endl;
+ delete domain;
+ exit(0);
+ }
+
+ cout << endl << "Patterns: " << total_patterns << endl;
+ cout << "Domain: " << *domain << endl;
+ cout << "Dimension: " << dim << " (";
+
+ delta = new int[dim];
+
+ for (int i=0; i<dim; i++)
+ {
+ is >> delta[i];
+ cout << "*";
+ }
+
+ cout << ")" << endl;
+ cout << "Reading patterns... (";
+
+ while (!is.eof())
+ {
+ is >> perc;
+ is.getline(buf, BUF_SIZE);
+ if (!is.bad() && sscanf(buf, "%s", buf2) == 1)
+ {
+ r_Minterval area(buf2);
+ IArea* ia = new IArea(area, perc);
+ IAreas += ia;
+
+ cout << "*";
+ }
+ else
+ break;
+ }
+
+ cout << ") -Done- " << endl;
+
+ is.close();
+}
+
+void generate_patterns()
+{
+ srand((unsigned int) time(NULL));
+
+
+ DListIterator<IArea*> it = IAreas.create_iterator();
+
+ ofstream os(out_filename);
+ if (!os)
+ {
+ cout << "Could not open " << out_filename << "." << endl;
+ exit(0);
+ }
+
+ while (it.not_done())
+ {
+ IArea* ia = *it;
+ ++it;
+
+ int total = (int)(ia->percent * total_patterns);
+
+ for (int i=0; i<total; i++)
+ {
+ os << "[";
+
+ for (int j=0; j<dim; j++)
+ {
+ long xmin = ia->iarea[j].low();
+ long xmax = ia->iarea[j].high();
+ long total = xmax-xmin;
+
+ if (delta[j] > total)
+ delta[j] = total;
+
+ long dxmin = (rand() % (2*delta[j] + 1)) - delta[j];
+ long dxmax = (rand() % (2*delta[j] + 1)) - delta[j];
+
+ xmin = xmin + dxmin;
+ if (xmin < (*domain)[j].low())
+ xmin = (*domain)[j].low() + ((*domain)[j].low() - xmin);
+
+ xmax = xmax + dxmax;
+ if (xmax > (*domain)[j].high())
+ xmax = (*domain)[j].high() - (xmax - (*domain)[j].high());
+
+ if (xmin > xmax)
+ {
+ long temp = xmin;
+ xmin = xmax;
+ xmax = temp;
+ }
+
+ os << xmin << ":" << xmax;
+
+ if (j != dim-1)
+ os << ",";
+ }
+
+ os << "]" << endl;
+ }
+ }
+
+ delete [] delta;
+ delete domain;
+}
+
+int main(int argc, char** argv)
+{
+ parse(argc, argv);
+ get_specification();
+ generate_patterns();
+
+ return 0;
+}
diff --git a/rasodmg/test/gen_query.pl b/rasodmg/test/gen_query.pl
new file mode 100644
index 0000000..aa5cf87
--- /dev/null
+++ b/rasodmg/test/gen_query.pl
@@ -0,0 +1,116 @@
+#!/usr/local/dist/bin/perl -w
+# use this one on Linux
+#!/usr/bin/perl -w
+
+# This program generates query files for use with test_benchmark. It
+# generates all files needed for executing the measurements specified
+# in the PhD thesis. It is not too generic, most of the things are
+# hardcoded.
+
+# each query is repeated 20 times
+$repeat = 20;
+# the collections which are used.
+@mdd = ( tomo_cubed, tomo_cubed_16, tomo_cubed_64, tomo_sliced );
+# the file name suffixes used for the collections
+@suffixes = ( _32, _16, _64, _s );
+# the selectivities tested for each collection
+@selectivity = ( .5, 1, 2, 5, 10, 20, 50 );
+# the filenames used to store the results
+
+sub calcQueryBox($$$$$$$$$);
+sub randNum($$);
+# initialize rand()
+srand();
+
+sub randNum($$)
+{
+ my ($l, $h) = @_;
+
+ return int ( $l + rand()*($h-$l) );
+}
+
+# this function calculates a random query box given the spatial
+#
+sub calcQueryBox($$$$$$$$$)
+{
+ my ( $xl, $xh, $yl, $yh, $zl, $zh, $xd, $yd, $zd ) = @_;
+
+ $x1 = randNum( $xl, $xh - $xd + 1);
+ $x2 = $x1 + ( $xd - 1 > 0 ? $xd - 1 : 0 );
+ $y1 = randNum( $yl, $yh - $yd + 1);
+ $y2 = $y1 + ( $yd - 1 > 0 ? $yd - 1 : 0 );
+ $z1 = randNum( $zl, $zh - $zd + 1);
+ $z2 = $z1 + ( $zd - 1 > 0 ? $zd - 1 : 0 );
+
+ return "[$x1:$x2, $y1:$y2, $z1:$z2]";
+}
+
+$headerStr = "
+// Testing acces to tomo_cubed with moving query box on different
+// selectivities.
+";
+
+foreach $tomo (@mdd)
+{
+ $suffix = shift @suffixes;
+ $fName1 = "tcubemov" . $suffix . ".ql";
+ $fName2 = "tcubeavg" . $suffix . ".ql";
+ open(QUERY1,">$fName1");
+ open(QUERY2,">$fName2");
+ print QUERY1 "$headerStr\n\n";
+ print QUERY2 "$headerStr\n\n";
+ foreach $sel (@selectivity)
+ {
+ $dx = $dy = int ( ($sel/100)**(1/3) * 256 );
+ $dz = int ( ($sel/100)**(1/3) * 154 );
+ # adapt query box for better fit
+ if(++$dx * $dy * $dz <= $sel/100*256*256*154) {
+ if($dx * ++$dy * $dz <= $sel/100*256*256*154) {
+ if($dx * $dy * ++$dz <= $sel/100*256*256*154) {
+ }
+ else {
+ $dz--;
+ }
+ }
+ else {
+ $dy--;
+ }
+ }
+ else {
+ $dx--;
+ }
+ for ($i = 1; $i <= $repeat; $i++) {
+ $qBox = calcQueryBox( 0, 255, 0, 255, 0, 153, $dx, $dy, $dz );
+ # print Query
+ print QUERY1 "// [$sel]: $qBox\n";
+ print QUERY2 "// [$sel]: $qBox\n";
+ print QUERY1 "SELECT img$qBox\nFROM $tomo AS img\n";
+ print QUERY2 "SELECT avg_cells(img$qBox)\nFROM $tomo AS img\n";
+ }
+ }
+}
+
+@suffixes = ( _32, _16, _64, _s );
+
+foreach $tomo (@mdd)
+{
+ $suffix = shift @suffixes;
+ $fName1 = "tslicemov" . $suffix . ".ql";
+ $fName2 = "tsliceavg" . $suffix . ".ql";
+ open(QUERY1,">$fName1");
+ open(QUERY2,">$fName2");
+ print QUERY1 "$headerStr\n\n";
+ print QUERY2 "$headerStr\n\n";
+ foreach $sel (@selectivity)
+ {
+ $dx = int ( ($sel/100) * 256 );
+ for ($i = 1; $i <= $repeat; $i++) {
+ $qBox = calcQueryBox( 0, 255, 0, 255, 0, 153, $dx, 256, 154 );
+ # print Query
+ print QUERY1 "// [$sel]: $qBox\n";
+ print QUERY2 "// [$sel]: $qBox\n";
+ print QUERY1 "SELECT img$qBox\nFROM $tomo AS img\n";
+ print QUERY2 "SELECT avg_cells(img$qBox)\nFROM $tomo AS img\n";
+ }
+ }
+}
diff --git a/rasodmg/test/gen_rollup.pl b/rasodmg/test/gen_rollup.pl
new file mode 100644
index 0000000..a3d60e0
--- /dev/null
+++ b/rasodmg/test/gen_rollup.pl
@@ -0,0 +1,209 @@
+#!/usr/local/dist/bin/perl
+
+$repeat = 20;
+
+sub randNum($$);
+# initialize rand()
+srand();
+
+sub randNum
+{
+ my ($l, $h) = @_;
+
+ return int ( $l + rand()*($h-$l) );
+}
+
+sub rollZ
+{
+ my $tomo = @_[0];
+ for ($i = 1; $i <= $repeat; $i++) {
+ $start = randNum(0, 153-6);
+ print "// [\"z\"] $tomo [*:*, *:*, $start:";
+ print $start + 6;
+ print "]\n";
+ print "SELECT img[*:*,*:*,$start]";
+ for ($j = $start + 1; $j <= $start + 6; $j++) {
+ print "+img[*:*,*:*,$j]";
+ }
+ print "\nFROM $tomo as img\n";
+ }
+}
+
+sub rollY
+{
+ my $tomo = @_[0];
+ for ($i = 1; $i <= $repeat; $i++) {
+ $start = randNum(0, 255-6);
+ print "// [\"y\"] $tomo [*:*, $start:";
+ print $start + 6;
+ print ", *:*]\n";
+ print "SELECT img[*:*,$start,*:*]";
+ for ($j = $start + 1; $j <= $start + 6; $j++) {
+ print "+img[*:*,$j,*:*]";
+ }
+ print "\nFROM $tomo as img\n";
+ }
+}
+
+sub rollX
+{
+ my $tomo = @_[0];
+ for ($i = 1; $i <= $repeat; $i++) {
+ $start = randNum(0, 255-6);
+ print "// [\"x\"] $tomo [$start:";
+ print $start + 6;
+ print ",*:*,*:*]\n";
+ print "SELECT img[$start,*:*,*:*]";
+ for ($j = $start + 1; $j <= $start + 6; $j++) {
+ print "+img[$j,*:*,*:*]";
+ }
+ print "\nFROM $tomo as img\n";
+ }
+}
+
+sub SQLrollX
+{
+ my $tomo = shift;
+
+ for($i = 1; $i <= $repeat; $i++)
+ {
+ $start = randNum(0, 153-6);
+ $end = $start + 6;
+ print "
+--#COMMENT BETWEEN $start AND $end
+
+SELECT y, z, sum(val)
+FROM $tomo
+WHERE x BETWEEN $start AND $end
+GROUP BY y, z
+;
+ ";
+
+
+ }
+}
+
+sub SQLrollY
+{
+ my $tomo = shift;
+
+ for($i = 1; $i <= $repeat; $i++)
+ {
+ $start = randNum(0, 255-6);
+ $end = $start + 6;
+ print "
+--#COMMENT BETWEEN $start AND $end
+
+SELECT x, z, sum(val)
+FROM $tomo
+WHERE y BETWEEN $start AND $end
+GROUP BY x, z
+;
+ ";
+
+
+ }
+}
+
+sub SQLrollZ
+{
+ my $tomo = shift;
+
+ for($i = 1; $i <= $repeat; $i++)
+ {
+ $start = randNum(0, 255-6);
+ $end = $start + 6;
+ print "
+--#COMMENT BETWEEN $start AND $end
+
+SELECT x, y, sum(val)
+FROM $tomo
+WHERE z BETWEEN $start AND $end
+GROUP BY x, y
+;
+ ";
+
+
+ }
+}
+
+sub genRollXYZ
+{
+ $headerStr = "
+// Testing roll up operations on different axes. It adds seven
+// consecutive slices along the corresponding Axis with a random
+// starting point on all four tomos..
+
+";
+
+ @mdd = ( tomo_sliced, tomo_cubed_16, tomo_cubed, tomo_cubed_64 );
+ foreach $tomo (@mdd)
+ {
+ rollX($tomo);
+ rollY($tomo);
+ rollZ($tomo);
+ };
+}
+
+sub genRollZ
+{
+ $headerStr = "
+// Testing roll up operations on different tomos. It adds seven
+// consecutive slices along the z-Axis with a random starting
+// point.
+
+";
+
+ @mdd = ( tomo_sliced, tomo_cubed, tomo_cubed_16, tomo_cubed_64 );
+ foreach $tomo (@mdd)
+ {
+ rollZ($tomo);
+ };
+}
+
+sub genSQLRollX
+{
+ $tomo = "tomo";
+
+ $headerStr = "
+-- tomo_rollX.sql
+-- tests rolling up tomo along x-axes.
+
+--#SET PERF_DETAIL 1 ROWS_FETCH -1 ROWS_OUT 0
+
+";
+ print $headerStr;
+ SQLrollX($tomo);
+}
+
+sub genSQLRollY
+{
+ $tomo = "tomo";
+
+ $headerStr = "
+-- tomo_rollY.sql
+-- tests rolling up tomo along y-axes.
+
+--#SET PERF_DETAIL 1 ROWS_FETCH -1 ROWS_OUT 0
+
+";
+ print $headerStr;
+ SQLrollY($tomo);
+}
+
+sub genSQLRollZ
+{
+ $tomo = "tomo";
+
+ $headerStr = "
+-- tomo_rollZ.sql
+-- tests rolling up tomo along z-axes.
+
+--#SET PERF_DETAIL 1 ROWS_FETCH -1 ROWS_OUT 0
+
+";
+ print $headerStr;
+ SQLrollZ($tomo);
+}
+
+genSQLRollX();
diff --git a/rasodmg/test/gen_s2k.pl b/rasodmg/test/gen_s2k.pl
new file mode 100644
index 0000000..6fd6fba
--- /dev/null
+++ b/rasodmg/test/gen_s2k.pl
@@ -0,0 +1,65 @@
+#!/usr/local/dist/bin/perl -w
+# use this one on Linux
+#!/usr/bin/perl -w
+
+# This program is an adaptation of gen_query for Sequoia 2000
+# queries.
+
+# IMPORTANT: At the moment this works only for collections
+# containing only one image. WHERE clauses on the OID have to
+# be added. Question: How do I get the OIDs? Probably have to
+# store them in the insertion program.
+
+# each query is repeated 40 times
+$repeat = 40;
+
+sub calcQueryBox($$$$$$);
+sub randNum($$);
+# initialize rand()
+srand();
+
+sub randNum($$)
+{
+ my ($l, $h) = @_;
+
+ return int ( $l + rand()*($h-$l) );
+}
+
+# this function calculates a random query box given the spatial
+# domain of the MDD and the extent of the query box
+sub calcQueryBox($$$$$$)
+{
+ my ( $xl, $xh, $yl, $yh, $xd, $yd ) = @_;
+
+ $x1 = randNum( $xl, $xh - $xd + 1);
+ $x2 = $x1 + ( $xd - 1 > 0 ? $xd - 1 : 0 );
+ $y1 = randNum( $yl, $yh - $yd + 1);
+ $y2 = $y1 + ( $yd - 1 > 0 ? $yd - 1 : 0 );
+
+ return "[$x1:$x2, $y1:$y2]";
+}
+
+$headerStr = "
+// Testing acces to s2k with a moving query box and a random band
+
+";
+
+open(QUERY1,">s2k.ql");
+
+print QUERY1 $headerStr;
+
+for ($i = 1; $i <= $repeat; $i++) {
+ $qBox = calcQueryBox( 0, 2599, 0, 1599, 200, 200 );
+ $band = randNum(1,5);
+ # print Query
+ print QUERY1 "// [Query 2]: $qBox\n";
+ print QUERY1 "SELECT img$qBox.band$band\nFROM s2k AS img\n";
+}
+
+for ($i = 1; $i <= $repeat; $i++) {
+ $qBox = calcQueryBox( 0, 2599, 0, 1599, 200, 200 );
+ $band = randNum(1,5);
+ # print Query
+ print QUERY1 "// [Query 3]: $qBox\n";
+ print QUERY1 "SELECT (1l*img$qBox.band1 + img$qBox.band2 +\n img$qBox.band3 + img$qBox.band4 +\n img$qBox.band5) / 5\nFROM s2k AS img\n";
+}
diff --git a/rasodmg/test/init_fast_collection.pl b/rasodmg/test/init_fast_collection.pl
new file mode 100644
index 0000000..63b29da
--- /dev/null
+++ b/rasodmg/test/init_fast_collection.pl
@@ -0,0 +1,111 @@
+#!/usr/bin/perl -w
+
+my $COLLECTION="orthorgb";
+my $SERVER="zombie";
+my $YMIN=0;
+my $YMAX=4999;
+my $XMIN=0;
+my $XMAX=4999;
+my $SCALELEVELS=8;
+my $IMGTYPE="RGB";#or "GREY"
+my $STORAGEFORMAT="Array";
+my $TRANSFERFORMAT="Array";
+my $transferWidth=2000;
+$transferWidth=int($transferWidth/(2**$SCALELEVELS))*(2**$SCALELEVELS);
+print "#transfer width $transferWidth\n";
+my $transferHeight=2000;
+$transferHeight=int($transferHeight/(2**$SCALELEVELS))*(2**$SCALELEVELS);
+print "#transfer height $transferHeight\n";
+my $i=0;
+my $currentCollection=$COLLECTION;
+my $currentXMin=$XMIN;
+my $currentYMin=$YMIN;
+my $currentXMax=$XMIN + $transferWidth;
+$currentXMax=min($XMAX, $currentXMax);
+my $currentYMax=$YMIN + $transferHeight;
+$currentYMax=min($YMAX, $currentYMax);
+my $colltype;
+my $mddtype;
+my $conversiontype;
+my $scaleLevel=2;
+my $command;
+my $scaleString;
+my $domain;
+
+sub max {
+ my $currentMax = shift;
+ my $next = shift;
+ if ($currentMax > $next)
+ {
+ return $currentMax;
+ }
+ else {
+ return $next;
+ }
+ };
+
+sub min {
+ my $currentMax = shift;
+ my $next = shift;
+ if ($currentMax > $next)
+ {
+ return $next;
+ }
+ else {
+ return $currentMax;
+ }
+ };
+
+if ($IMGTYPE eq "RGB")
+ {
+ $colltype="RGBSet";
+ $mddtype="RGBImage";
+ $conversiontype="RGBPixel";
+ }
+else {
+ if ($IMGTYPE eq "RGB")
+ {
+ $colltype="GreySet";
+ $mddtype="GreyImage";
+ $conversiontype="char";
+ }
+ else {
+ die "Unknown image type: $IMGTYPE\n";
+ }
+ }
+for ($i=1; $i < $SCALELEVELS + 1; $i++)
+ {
+ $currentCollection = $COLLECTION . "_" . int($i);
+ $scaleString .= "$currentCollection:$scaleLevel";
+ if ($i != $SCALELEVELS)
+ {
+ $scaleString .= ";";
+ }
+ $scaleLevel *= 2;
+ }
+while ($currentXMax <= $XMAX)
+ {
+ while ($currentYMax <= $YMAX)
+ {
+ $domain = "[$currentXMin:" . ($currentXMax - 1) . ",$currentYMin:" . ($currentYMax - 1) . "]";
+ $command = "system_update -s $SERVER --collection $COLLECTION -t --colltype $colltype --mddtype $mddtype --storageformat $STORAGEFORMAT --transferformat $TRANSFERFORMAT --scalelevels \"$scaleString\" --mdddomain \"$domain\"";
+ print "$command\n";
+ if ($currentYMax == $YMAX)
+ {
+ last;
+ }
+ $currentYMax += $transferHeight;
+ $currentYMax = min($currentYMax, $YMAX);
+ $currentYMin += $transferHeight;
+ };
+ if ($currentXMax == $XMAX)
+ {
+ last;
+ }
+ $currentXMin += $transferWidth;
+ $currentXMax += $transferWidth;
+ $currentXMax = min($currentXMax, $XMAX);
+ $currentYMin = $YMIN;
+ $currentYMax = $YMIN + $transferHeight;
+ $currentYMax = min($YMAX, $currentYMax);
+ };
diff --git a/rasodmg/test/polytest.poly b/rasodmg/test/polytest.poly
new file mode 100644
index 0000000..0d1c648
--- /dev/null
+++ b/rasodmg/test/polytest.poly
@@ -0,0 +1,3 @@
+[ 3430000, 5720000];
+[ 3460000, 5750000][ 3460000, 5750000][ 3460000, 5750000];
+
diff --git a/rasodmg/test/rasql.cc b/rasodmg/test/rasql.cc
new file mode 100644
index 0000000..c43eb63
--- /dev/null
+++ b/rasodmg/test/rasql.cc
@@ -0,0 +1,126 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: system_basic.cc
+ *
+ * MODULE: rasodmg/test
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg/test,rasql: $Id: rasql.cc,v 1.5 2002/05/25 14:29:15 coman Exp $";
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <iostream>
+#include <fstream>
+#include <stdio.h>
+#include "readln.hh"
+#include "rasql.hh"
+
+static bool noMore = false;
+
+
+void logo() {
+ std::cout << "RasQL v0.1, (c) 2001 active knowledge GmbH." << std::endl;
+ if(noMore)
+ std::cout << "Option: no more" << std::endl;
+ std::cout << std::endl;
+}
+
+bool toFile(char *s) {
+ std::ofstream os(file_name);
+ if(!os)
+ return false;
+ os << s;
+ return true;
+}
+
+void filter(void) {
+ execlp(filter_prog, filter_prog, filter_params, 0);
+ perror("exec");
+ exit(1);
+}
+
+
+void query(void) {
+ execlp(query_prog, query_prog,
+ server_param, server_name,
+ base_param, base_name,
+ file_param, file_name,
+ 0);
+ perror("exec");
+ exit(1);
+}
+
+bool process(char* s) {
+ int p[2];
+ if(strcmp(s, "exit") == 0)
+ return false;
+ if(strcmp(s, "quit") == 0)
+ return false;
+
+ if(!toFile(s)) {
+ std::cerr << "toFile: error opening file " << file_name << std::endl;
+ return true;
+ }
+
+ if(noMore) {
+ if(!fork())
+ query();
+ }
+ else {
+ pipe(p);
+ if(!fork()) {
+ close(p[1]);
+ dup2(p[0], 0);
+ filter();
+ }
+ else if(!fork()) {
+ close(p[0]);
+ dup2(p[1], 1);
+ query();
+ }
+ else {
+ close(p[0]);
+ close(p[1]);
+ }
+ }
+
+ while(wait(0) > 0);
+ return true;
+}
+
+int main(int argc, char **argv) {
+ if(--argc && strcmp(*(++argv), "-nomore") == 0)
+ noMore = true;
+
+ logo();
+
+ ReadLn l(process, "RasQL> ");
+ l.loop();
+ std::cout << std::endl;
+ return 0;
+} \ No newline at end of file
diff --git a/rasodmg/test/rasql.hh b/rasodmg/test/rasql.hh
new file mode 100644
index 0000000..0f9c1a2
--- /dev/null
+++ b/rasodmg/test/rasql.hh
@@ -0,0 +1,38 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+#ifndef __RASQL_HH__
+#define __RASQL_HH__
+
+const char* query_prog = "test_query";
+const char* server_param = "-server";
+const char* server_name = "localhost";
+const char* base_param = "-base";
+const char* base_name = "RASBASE";
+const char* file_param = "-file";
+const char* file_name = "/tmp/tmp.ql";
+
+const char* filter_prog = "less";
+const char* filter_params = "-Fn";
+
+#endif
diff --git a/rasodmg/test/readln.cc b/rasodmg/test/readln.cc
new file mode 100644
index 0000000..6d2d928
--- /dev/null
+++ b/rasodmg/test/readln.cc
@@ -0,0 +1,64 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+#include "readln.hh"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+extern "C" int beep(int, int);
+
+ReadLn::ReadLn(bool (*f)(char*), char* p, bool useTab): worker(f), prompt(p), line(0) {
+ if(!useTab)
+ rl_bind_key((int)'\t', beep);
+}
+
+ReadLn::~ReadLn() {}
+
+void ReadLn::loop() {
+ do {
+ initLn();
+
+ if((line = readline(prompt)) != 0 && *line) {
+ add_history(line);
+ if(!worker(line))
+ break;
+ }
+
+ } while(line);
+}
+
+void ReadLn::initLn() {
+ if(line) {
+ free(line);
+ line = 0;
+ }
+}
+
+int beep(int, int) {
+ putchar( '\a');
+ return 1; // meaningless, just for prototype
+} \ No newline at end of file
diff --git a/rasodmg/test/readln.hh b/rasodmg/test/readln.hh
new file mode 100644
index 0000000..4f5a1bd
--- /dev/null
+++ b/rasodmg/test/readln.hh
@@ -0,0 +1,45 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+#ifndef __READLN_HH__
+#define __READLN_HH__
+
+class ReadLn {
+public:
+// typedef void (* worker_t)(const char *);
+
+ ReadLn(bool (*f)(char*) = 0, char* p = "> ", bool useTab = false);
+ ~ReadLn();
+ void loop();
+
+protected:
+ void initLn();
+
+private:
+ char* prompt;
+ bool (*worker)(char*);
+ char *line;
+
+};
+
+#endif
diff --git a/rasodmg/test/runbm.sh b/rasodmg/test/runbm.sh
new file mode 100644
index 0000000..e0366fb
--- /dev/null
+++ b/rasodmg/test/runbm.sh
@@ -0,0 +1,94 @@
+#!/usr/bin/ksh
+
+echo "runbm started."
+
+# defaults if no parameters are given
+RUNS='-n 10'
+basename='NorbertBase'
+
+# parse command line
+while [[ 1 -eq 1 ]]; do
+ if [[ $1 = '-n' ]]; then
+ shift; RUNS="-n $1"; shift;
+ elif [[ $1 = '-e' ]]; then
+ shift; RUNS="-e $1"; shift;
+ elif [[ $1 = '-base' ]]; then
+ shift; basename=$1; shift;
+ else
+ break;
+ fi
+done
+
+QLFILES=${@}
+# optionally add different servers here
+RASSERVERS='rasserver'
+
+BMTIME=$(date +%d%b%y_%H-%M)
+
+mkdir bm_$BMTIME
+
+# shutdown server in case it is already running
+$RMANBASE/server/rascontrol $HOST down
+
+for servername in $RASSERVERS; do
+ for qlname in $QLFILES; do
+ echo "$servername $qlname:"
+ # take time when this test started
+ QLTIME=$(date +%d%b%y_%H-%M)
+
+ filename=$(pwd)/bm_$BMTIME/bm${servername#rasserver}_${qlname%\.ql}
+
+ # start server
+
+ # should be like the following line, but rasserver does not like long
+ # filenames :-(
+ # $RMANBASE/server/$servername -bl 4 -l $filename\_server.log -b $filename\_server.bm -d $filename\_server.dbg &
+
+ # workaround
+ $RMANBASE/server/$servername -bl 4 -notimeout &
+ # store PID
+ RMANPID=$!
+
+ # wait till it has finished
+ sleep 30
+
+ # write information file
+ touch $filename\.inf
+ echo "Filename of rasserver used: $servername" > $filename\.inf
+ echo "Host: $HOST" >> $filename\.inf
+ echo "Time: $QLTIME" >> $filename\.inf
+ echo "Output of what on rasserver:" >> $filename\.inf
+ what $RMANBASE/server/$servername >> $filename\.inf
+ echo "Output of what on test_benchmark:" >> $filename\.inf
+ what $RMANBASE/rasodmg/test/test_benchmark >> $filename\.inf
+
+ # run benchmark
+ $RMANBASE/rasodmg/test/test_benchmark $RUNS $HOST $basename $qlname
+
+ # save client information
+ mv client.bm $filename\_client.bm
+ mv client.log $filename\_client.log
+ mv client.dbg $filename\_client.dbg
+
+ # shutdown server
+ $RMANBASE/server/rascontrol $HOST down
+ # just to be sure
+ kill $RMANPID 1>/dev/null 2>&1
+
+ # workaround
+ mv server.log $filename\_server.log
+ mv server.bm $filename\_server.bm
+ mv server.dbg $filename\_server.dbg
+
+ # store queryfile
+ cp $qlname $filename\.ql
+
+ # create slk file for Excel
+ $RMANBASE/utilities/bm2sylk.pl $filename\_client.bm $filename\_server.bm > $filename.slk
+
+ done
+done
+
+echo "runbm finished."
+
+exit
diff --git a/rasodmg/test/small_16.ql b/rasodmg/test/small_16.ql
new file mode 100644
index 0000000..877c6e6
--- /dev/null
+++ b/rasodmg/test/small_16.ql
@@ -0,0 +1,42 @@
+// Selection of images out of a collection with 15 800x800x8bit
+// images. There is one image each with only 255, 254, 253 as a
+// value. And there is one image each with one value each out of
+// 250, 251, 252. No other image contains value greater than 249.
+
+// one img with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE some_cell ( img[700:799,300:399] = 252c )
+
+// two imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE some_cell ( img[700:799,300:399] = 252c OR img[700:799,300:399] = 251c )
+
+// three imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE some_cell ( img[700:799,300:399] = 252c OR img[700:799,300:399] = 251c
+ OR img[700:799,300:399] = 250c )
+
+// one img with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE all_cell ( img[700:799,300:399] >= 255c )
+
+// two imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE all_cell ( img[700:799,300:399] >= 254c )
+
+// three imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE all_cell ( img[700:799,300:399] >= 253c )
+
diff --git a/rasodmg/test/small_32.ql b/rasodmg/test/small_32.ql
new file mode 100644
index 0000000..ddf52b7
--- /dev/null
+++ b/rasodmg/test/small_32.ql
@@ -0,0 +1,42 @@
+// Selection of images out of a collection with 15 800x800x8bit
+// images. There is one image each with only 255, 254, 253 as a
+// value. And there is one image each with one value each out of
+// 250, 251, 252. No other image contains value greater than 249.
+
+// one img with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE some_cell ( img[700:799,300:399] = 252c )
+
+// two imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE some_cell ( img[700:799,300:399] = 252c OR img[700:799,300:399] = 251c )
+
+// three imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE some_cell ( img[700:799,300:399] = 252c OR img[700:799,300:399] = 251c
+ OR img[700:799,300:399] = 250c )
+
+// one img with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE all_cell ( img[700:799,300:399] >= 255c )
+
+// two imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE all_cell ( img[700:799,300:399] >= 254c )
+
+// three imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_32 as img
+WHERE all_cell ( img[700:799,300:399] >= 253c )
+
diff --git a/rasodmg/test/small_64.ql b/rasodmg/test/small_64.ql
new file mode 100644
index 0000000..dea4779
--- /dev/null
+++ b/rasodmg/test/small_64.ql
@@ -0,0 +1,42 @@
+// Selection of images out of a collection with 15 800x800x8bit
+// images. There is one image each with only 255, 254, 253 as a
+// value. And there is one image each with one value each out of
+// 250, 251, 252. No other image contains value greater than 249.
+
+// one img with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE some_cell ( img[700:799,300:399] = 252c )
+
+// two imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE some_cell ( img[700:799,300:399] = 252c OR img[700:799,300:399] = 251c )
+
+// three imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE some_cell ( img[700:799,300:399] = 252c OR img[700:799,300:399] = 251c
+ OR img[700:799,300:399] = 250c )
+
+// one img with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE all_cell ( img[700:799,300:399] >= 255c )
+
+// two imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE all_cell ( img[700:799,300:399] >= 254c )
+
+// three imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_64 as img
+WHERE all_cell ( img[700:799,300:399] >= 253c )
+
diff --git a/rasodmg/test/stat1.dat b/rasodmg/test/stat1.dat
new file mode 100644
index 0000000..520061f
--- /dev/null
+++ b/rasodmg/test/stat1.dat
@@ -0,0 +1,3 @@
+50 0.20 10000 [0:799, 0:599]
+[200:600, 200:400]
+[220:620, 190:440] \ No newline at end of file
diff --git a/rasodmg/test/stat2.dat b/rasodmg/test/stat2.dat
new file mode 100644
index 0000000..b288662
--- /dev/null
+++ b/rasodmg/test/stat2.dat
@@ -0,0 +1,7 @@
+50 0.20 50000 [0:799, 0:599]
+[200:600, 200:400]
+[220:620, 190:440]
+[100:400, 300:580]
+[120:410, 310:570]
+[120:410, 310:569]
+[0:600, 0:500] \ No newline at end of file
diff --git a/rasodmg/test/stat3.dat b/rasodmg/test/stat3.dat
new file mode 100644
index 0000000..8f447b5
--- /dev/null
+++ b/rasodmg/test/stat3.dat
@@ -0,0 +1,4 @@
+50 0.20 50000 [0:799, 0:599]
+[120:410, 310:570]
+[120:410, 310:569]
+[0:600, 0:500] \ No newline at end of file
diff --git a/rasodmg/test/system_basic.cc b/rasodmg/test/system_basic.cc
new file mode 100644
index 0000000..6ba9afb
--- /dev/null
+++ b/rasodmg/test/system_basic.cc
@@ -0,0 +1,1945 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: system_basic.cc
+ *
+ * MODULE: rasodmg/test
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg/test,SystemBasic: $Id: system_basic.cc,v 1.37 2002/10/09 09:58:05 hoefner Exp $";
+
+#ifdef TESTBASIC
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+#endif
+
+#include "system_basic.hh"
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <math.h>
+#include <signal.h>
+#include <unistd.h>
+#ifdef SOLARIS
+#include <strings.h>
+#endif
+
+#include "raslib/rmdebug.hh"
+#include "raslib/rminit.hh"
+#include "raslib/type.hh"
+#include "raslib/complex.hh"
+#include "raslib/structure.hh"
+#include "raslib/basetype.hh"
+#include "raslib/structuretype.hh"
+#include "raslib/collectiontype.hh"
+#include "raslib/marraytype.hh"
+#include "raslib/dlist.hh"
+#include "raslib/primitivetype.hh"
+#include "raslib/miterd.hh"
+#include "raslib/storageman.hh"
+
+#include "rasodmg/marray.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/interesttiling.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/stattiling.hh"
+#include "rasodmg/oqlquery.hh"
+
+#include "conversion/convfactory.hh"
+#include "conversion/convertor.hh"
+
+#include "exportutils/hexcodec.cc"
+#include "exportutils/error.cc"
+
+void
+fast_scale_process_primitive_type(const r_Primitive_Type *primType, char *dest, const char *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &iterDom, unsigned int type_len, unsigned int length, r_Scale_Function func);
+void
+fast_scale_process_structured_type(const r_Structure_Type *primType, char *dest, const char *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &iterDom, unsigned int type_len, unsigned int length, r_Scale_Function func);
+template<class T>
+void
+fast_scale_resample_array(T *dest, const T *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &iterDom, unsigned int type_len, unsigned int length, bool round);
+
+template<class T>
+void
+fast_scale_aggregate_array(T *dest, const T *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &iterDom, unsigned int type_len, unsigned int length);
+
+void
+signalHandler(int sig)
+ {
+ cout << "**CLIENT** signal error " << sig << " ";
+ switch (sig)
+ {
+ case SIGHUP:
+ cout << "Hangup (POSIX). ";
+ break;
+ case SIGINT:
+ cout << "Interrupt (ANSI).";
+ break;
+ case SIGQUIT:
+ cout << "Quit (POSIX).";
+ break;
+ case SIGILL:
+ cout << "Illegal instruction (ANSI).";
+ break;
+ case SIGTRAP:
+ cout << "Trace trap (POSIX).";
+ break;
+ case SIGABRT:
+ cout << "Abort (ANSI) or IOT trap (4.2 BSD).";
+ break;
+ case SIGBUS:
+ cout << "BUS error (4.2 BSD).";
+ break;
+ case SIGFPE:
+ cout << "Floating-point exception (ANSI).";
+ break;
+ case SIGKILL:
+ cout << "Kill, unblockable (POSIX).";
+ break;
+ case SIGUSR1:
+ cout << "User-defined signal 1 (POSIX).";
+ break;
+ case SIGSEGV:
+ cout << "Segmentation violation (ANSI).";
+ break;
+ case SIGUSR2:
+ cout << "User-defined signal 2 (POSIX).";
+ break;
+ case SIGPIPE:
+ cout << "Broken pipe (POSIX).";
+ break;
+ case SIGALRM:
+ cout << "Alarm clock (POSIX).";
+ break;
+ case SIGTERM:
+ cout << "Termination (ANSI).";
+ break;
+#ifndef SOLARIS
+#ifndef DECALPHA
+ case SIGSTKFLT:
+ cout << "Stack fault.";
+ break;
+#endif
+#endif
+ case SIGCLD:
+ cout << "SIGCHLD (System V) or child status has changed (POSIX).";
+ break;
+ case SIGCONT:
+ cout << "Continue (POSIX).";
+ break;
+ case SIGSTOP:
+ cout << "Stop, unblockable (POSIX).";
+ break;
+ case SIGTSTP:
+ cout << "Keyboard stop (POSIX).";
+ break;
+ case SIGTTIN:
+ cout << "Background read from tty (POSIX).";
+ break;
+ case SIGTTOU:
+ cout << "Background write to tty (POSIX).";
+ break;
+ case SIGURG:
+ cout << "Urgent condition on socket (4.2 BSD).";
+ break;
+ case SIGXCPU:
+ cout << "CPU limit exceeded (4.2 BSD).";
+ break;
+ case SIGXFSZ:
+ cout << "File size limit exceeded (4.2 BSD).";
+ break;
+ case SIGVTALRM:
+ cout << "Virtual alarm clock (4.2 BSD).";
+ break;
+ case SIGPROF:
+ cout << "Profiling alarm clock (4.2 BSD).";
+ break;
+ case SIGWINCH:
+ cout << "Window size change (4.3 BSD, Sun).";
+ cout << "Continue with operation.";
+ return;
+ break;
+ case SIGPOLL:
+ cout << "Pollable event occurred (System V) or I/O now possible (4.2 BSD).";
+ break;
+ case SIGPWR:
+ cout << "Power failure restart (System V).";
+ break;
+ case SIGSYS:
+ cout << "Bad system call.";
+ break;
+ default:
+ cout << "Unknown signal.";
+ break;
+ }
+ cout << endl;
+ if (SystemBasic::handleSignal)
+ {
+ SystemBasic::handleSignal = false;
+ try {
+ cout << "Aborting transaction" << endl;;
+ SystemBasic::ta.abort();
+ cout << "Transaction aborted" << endl;
+ cout << "Closing database" << endl;
+ SystemBasic::db.close();
+ cout << "Database closed" << endl;
+ }
+ catch (r_Error& err)
+ {
+ cout << "Error while aborting transaction/closing database: " << err.get_errorno() << " : " << err.what() << endl;
+ }
+ }
+ else {
+ //not doing it
+ }
+ exit(sig);
+ }
+
+void
+installSignalHandlers()
+ {
+ signal(SIGINT, signalHandler);
+ signal(SIGTERM, signalHandler);
+ signal(SIGHUP, signalHandler);
+ signal(SIGPIPE, signalHandler);
+ signal(SIGHUP, signalHandler);
+ signal(SIGINT, signalHandler);
+ signal(SIGQUIT, signalHandler);
+ signal(SIGILL, signalHandler);
+ signal(SIGTRAP, signalHandler);
+ signal(SIGABRT, signalHandler);
+ signal(SIGIOT, signalHandler);
+ signal(SIGBUS, signalHandler);
+ signal(SIGFPE, signalHandler);
+ signal(SIGKILL, signalHandler);
+ signal(SIGUSR1, signalHandler);
+ signal(SIGSEGV, signalHandler);
+ signal(SIGUSR2, signalHandler);
+ signal(SIGPIPE, signalHandler);
+ signal(SIGALRM, signalHandler);
+ signal(SIGTERM, signalHandler);
+#ifndef SOLARIS
+#ifndef DECALPHA
+ signal(SIGSTKFLT, signalHandler);
+#endif
+#endif
+ signal(SIGCLD, signalHandler);
+ signal(SIGCHLD, signalHandler);
+ signal(SIGCONT, signalHandler);
+ signal(SIGSTOP, signalHandler);
+ signal(SIGTSTP, signalHandler);
+ signal(SIGTTIN, signalHandler);
+ signal(SIGTTOU, signalHandler);
+ signal(SIGURG, signalHandler);
+ signal(SIGXCPU, signalHandler);
+ signal(SIGXFSZ, signalHandler);
+ signal(SIGVTALRM, signalHandler);
+ signal(SIGPROF, signalHandler);
+ signal(SIGWINCH, signalHandler);
+ signal(SIGPOLL, signalHandler);
+ signal(SIGIO, signalHandler);
+ signal(SIGPWR, signalHandler);
+ signal(SIGSYS, signalHandler);
+#if !defined SOLARIS
+#if !defined DECALPHA
+ signal(SIGUNUSED, signalHandler);
+#endif
+#endif
+ }
+
+r_Tiling*
+SystemBasic::theTiling = 0;
+
+bool
+SystemBasic::testBed = false;
+
+const char*
+SystemBasic::serverName = "localhost";
+
+r_ULong
+SystemBasic::serverPort = 7001;
+
+const char*
+SystemBasic::baseName = "RASBASE";
+
+const char*
+SystemBasic::userName = "rasguest";
+
+const char*
+SystemBasic::passwd = "rasguest";
+
+bool
+SystemBasic::printText = false;
+
+const char*
+SystemBasic::outputFileName = NULL;
+
+r_Data_Format
+SystemBasic::outputFormat = r_Array;
+
+const char*
+SystemBasic::outputFormatParams = 0;
+
+const char*
+SystemBasic::conversionTypeName = "char";
+
+r_Data_Format
+SystemBasic::inputFormat = r_Array;
+
+const char*
+SystemBasic::inputFormatParams = 0;
+
+r_Data_Format
+SystemBasic::transferFormat = r_Array;
+
+const char*
+SystemBasic::transferFormatParams = 0;
+
+r_Data_Format
+SystemBasic::storageFormat = r_Array;
+
+const char*
+SystemBasic::storageFormatParams = 0;
+
+const char*
+SystemBasic::collName = NULL;
+
+const char*
+SystemBasic::setTypeName = NULL;
+
+const char*
+SystemBasic::mddTypeName = NULL;
+
+r_OId
+SystemBasic::mddOId;
+
+bool
+SystemBasic::mddOIdDef = false;
+
+r_OId
+SystemBasic::collOId;
+
+bool
+SystemBasic::collOIdDef = false;
+
+const char*
+SystemBasic::fileName = NULL;
+
+r_Database
+SystemBasic::db;
+
+r_Transaction
+SystemBasic::ta;
+
+r_Minterval
+SystemBasic::mddDomain;
+
+bool
+SystemBasic::mddDomainDef = false;
+
+bool
+SystemBasic::polygonDefined = false;
+
+r_PolygonCutOut
+SystemBasic::polygon;
+
+int
+SystemBasic::polygonShrinker;
+
+bool
+SystemBasic::transparent = false;
+
+string
+SystemBasic::outsidePatternSel;
+
+bool
+SystemBasic::outsidePatternSelDef = false;
+
+string
+SystemBasic::insidePatternSel;
+
+bool
+SystemBasic::insidePatternSelDef = false;
+
+string
+SystemBasic::outsidePattern;
+
+bool
+SystemBasic::outsidePatternDef = false;
+
+string
+SystemBasic::insidePattern;
+
+bool
+SystemBasic::insidePatternDef = false;
+
+const int
+SystemBasic::queryBufferLength = 512;
+
+std::list<std::pair<double, char*> >*
+SystemBasic::scaleLevels = NULL;
+
+int
+SystemBasic::wrongBytes = 0;
+
+r_Scale_Function
+SystemBasic::scaleFunction = r_SubSampling;
+
+size_t
+SystemBasic::updateBufferSize = 52428800;
+
+const char*
+SystemBasic::defaultUpdateBufferSize = "52428800";
+
+
+std::list<char*>
+SystemBasic:: layerList;
+
+std::list<unsigned int>
+SystemBasic::patternsTrue;
+
+std::list<unsigned int>
+SystemBasic::patternsFalse;
+
+const char*
+SystemBasic::noUsageHeader = "Please set SystemBasic::usageHeader to a meaningful value.\nThen you will help your users : )\n";
+
+const char*
+SystemBasic::usageHeader = SystemBasic::noUsageHeader;
+
+const char*
+SystemBasic::noUsageFooter = "Please set SystemBasic::usageFooter to a meaningful value.\nThen you will help your users : )\n";
+
+const char*
+SystemBasic::usageFooter = SystemBasic::noUsageFooter;
+
+r_Minterval
+SystemBasic::overlayDomain;
+
+bool
+SystemBasic::overlayDomainDef = false;
+
+r_Range
+SystemBasic::align = 0;
+
+bool
+SystemBasic::tiledUpdate = false;
+
+bool
+SystemBasic::force = false;
+
+//--tiling params description
+const string
+SystemBasic::tilingDesc= string("") +
+ "<tiling-name> tiling strategy, specified as:" + CommandLineParameter::descLineSep +
+ " " + tiling_name_notiling + "," + CommandLineParameter::descLineSep +
+ " " + tiling_name_sizetiling + "," + CommandLineParameter::descLineSep +
+ " " + tiling_name_alignedtiling + "," + CommandLineParameter::descLineSep +
+ " " + tiling_name_interesttiling + "," + CommandLineParameter::descLineSep +
+ " " + tiling_name_directionaltiling + "," + CommandLineParameter::descLineSep +
+ " " + tiling_name_statisticaltiling;
+
+const string
+SystemBasic::tilingParamsDesc = string("") +
+ "<params> parameters for tiling strategy, specified as:" + CommandLineParameter::descLineSep +
+ "... for " + tiling_name_notiling + CommandLineParameter::descLineSep +
+ r_No_Tiling::description + CommandLineParameter::descLineSep +
+ "... for " + tiling_name_sizetiling + CommandLineParameter::descLineSep +
+ r_Size_Tiling::description + CommandLineParameter::descLineSep +
+ "... for " + tiling_name_alignedtiling + CommandLineParameter::descLineSep +
+ r_Aligned_Tiling::description + CommandLineParameter::descLineSep +
+ "... for " + tiling_name_interesttiling + CommandLineParameter::descLineSep +
+ r_Interest_Tiling::description + CommandLineParameter::descLineSep +
+ "... for " + tiling_name_directionaltiling + CommandLineParameter::descLineSep +
+ r_Dir_Tiling::description + CommandLineParameter::descLineSep +
+ "... for " + tiling_name_statisticaltiling + CommandLineParameter::descLineSep +
+ r_Stat_Tiling::description;
+
+bool
+SystemBasic::handleSignal = true;
+
+int
+SystemBasic::parseParams(int argc, char** argv)
+ {
+ int retval = 0;
+ //program interface
+ CommandLineParser &cmlInter = CommandLineParser::getInstance();
+ CommandLineParameter &clp_help = cmlInter.addFlagParameter('h', "help", "show command line switches");
+ CommandLineParameter &clp_tiling = cmlInter.addStringParameter(CommandLineParser::noShortName, "tiling", tilingDesc.c_str(), tiling_name_sizetiling);
+ CommandLineParameter &tilingParams = cmlInter.addStringParameter(CommandLineParser::noShortName, "tilingparams", tilingParamsDesc.c_str(), "131072");
+ CommandLineParameter &clp_testbed = cmlInter.addFlagParameter(CommandLineParser::noShortName, "testbed", "testbed output flag.");
+ CommandLineParameter &clp_transparent = cmlInter.addFlagParameter('t', "transparent", "transparent update flag.\n\t\tIf it is specified black data will be treated as transparent");
+ CommandLineParameter &clp_printtext = cmlInter.addFlagParameter(CommandLineParser::noShortName, "printtext", "output of char data will be printed as text - not numbers.\n\t\tUseful for printing the names of all collections/or text stored in mdds");
+ CommandLineParameter &clp_server = cmlInter.addStringParameter('s', "server", "<host-name> host's name where rasmgr runs.", serverName);
+ CommandLineParameter &clp_port = cmlInter.addStringParameter('p', "port", "<nnnn> port number used by rasmgr.", "7001");
+ CommandLineParameter &clp_database = cmlInter.addStringParameter('d', "database", "<db-name> name of database.", baseName);
+ CommandLineParameter &clp_user = cmlInter.addStringParameter(CommandLineParser::noShortName, "user", "<user-name> name of user", userName);
+ CommandLineParameter &clp_passwd = cmlInter.addStringParameter(CommandLineParser::noShortName,"passwd", "<user-passwd> password of user", passwd);
+ CommandLineParameter &clp_storage = cmlInter.addStringParameter(CommandLineParser::noShortName, "storageformat", "<format> storage format.", format_name_array);
+ CommandLineParameter &clp_storageParams = cmlInter.addStringParameter(CommandLineParser::noShortName, "storageformatparams", "<params> parameters used for storing", NULL);
+ CommandLineParameter &clp_transfer = cmlInter.addStringParameter(CommandLineParser::noShortName, "transformat", "<format> transfer format.", format_name_array );
+ CommandLineParameter &clp_transferParams = cmlInter.addStringParameter(CommandLineParser::noShortName, "transformatparams", "<params> parameters used for transfer", NULL);
+ CommandLineParameter &clp_input = cmlInter.addStringParameter(CommandLineParser::noShortName, "inputformat", "<format> input format.", format_name_array );
+ CommandLineParameter &clp_inputParams = cmlInter.addStringParameter(CommandLineParser::noShortName, "inputformatparams", "<params> parameters used for input", NULL);
+ CommandLineParameter &clp_output = cmlInter.addStringParameter(CommandLineParser::noShortName, "outputformat", "<format> output format.", format_name_array );
+ CommandLineParameter &clp_outputParams = cmlInter.addStringParameter(CommandLineParser::noShortName, "outputformatparams", "<params> parameters used for output", NULL);
+ CommandLineParameter &clp_outputFileName = cmlInter.addStringParameter(CommandLineParser::noShortName, "outputfilename", "<name> file name of output file", NULL);
+ CommandLineParameter &clp_polygon = cmlInter.addStringParameter(CommandLineParser::noShortName, "polygon", "<polygon-path> polygon path used for delimiting the data. The polygon has to be given in counter clockwise direction. Do not forget to supply insidepattern and/or outsidepattern", NULL);
+ CommandLineParameter &clp_shrink = cmlInter.addStringParameter(CommandLineParser::noShortName, "shrink", "<number> pixels that will reduce the polygon.", "0");
+ CommandLineParameter &clp_fillinside = cmlInter.addStringParameter(CommandLineParser::noShortName, "outsidepattern", "<pattern> will be used to fill the outside of the polygon.", NULL);
+ CommandLineParameter &clp_filloutside = cmlInter.addStringParameter(CommandLineParser::noShortName, "insidepattern", "<pattern> will be used to fill the inside of the polygon.", NULL);
+ CommandLineParameter &clp_fillinsidesel = cmlInter.addStringParameter(CommandLineParser::noShortName, "outsidepatternbackdrop", "<pattern> will be used to fill the outside of the polygon in the backdrop mdd.", NULL);
+ CommandLineParameter &clp_filloutsidesel = cmlInter.addStringParameter(CommandLineParser::noShortName, "insidepatternbackdrop", "<pattern> will be used to fill the inside of the polygon in the backdrop mdd.", NULL);
+ CommandLineParameter &clp_collType = cmlInter.addStringParameter(CommandLineParser::noShortName, "colltype", "<coll-type> type of collection");
+ CommandLineParameter &clp_mddType = cmlInter.addStringParameter(CommandLineParser::noShortName, "mddtype", "<mdd-type> type of marray");
+ CommandLineParameter &clp_collName = cmlInter.addStringParameter('c', "collname", "<coll-name> name of collection");
+ CommandLineParameter &clp_mddoid = cmlInter.addStringParameter(CommandLineParser::noShortName, "mddoid","<mdd-oid> oid of the marray to work on");
+ CommandLineParameter &clp_colloid = cmlInter.addStringParameter(CommandLineParser::noShortName, "colloid","<coll-oid> oid of the set to work on");
+ CommandLineParameter &clp_mddDomain = cmlInter.addStringParameter(CommandLineParser::noShortName, "mdddomain","<mdd-domain> domain of marray");
+ CommandLineParameter &clp_overlayDomain = cmlInter.addStringParameter(CommandLineParser::noShortName, "overlaydomain","<overlay-domain> domain that is updated in the db in case of an overlay, default is the domain of the image");
+ CommandLineParameter &clp_align = cmlInter.addStringParameter(CommandLineParser::noShortName, "align","<pixels> number of pixels to align the domain to. May be used instead of overlaydomain.", "0");
+ CommandLineParameter &clp_tiledupdate = cmlInter.addFlagParameter(CommandLineParser::noShortName, "tiledupdate","do job in smaller pieces. Use update buffer size to compute the size of each update. May not be used with a file insertion!");
+ CommandLineParameter &clp_read = cmlInter.addStringParameter('r', "read", "<file-name> name of input file");
+ CommandLineParameter &clp_conversiontypename = cmlInter.addStringParameter(CommandLineParser::noShortName, "conversiontype","<type-name> name of type to be passed to the conversion module");
+ CommandLineParameter &clp_scalelevels = cmlInter.addStringParameter(CommandLineParser::noShortName, "scalelevels","<level-spec> list of scale levels: collection:1/scalefactor;...\n\t\te.g. coll:1;coll_1:2;coll_3:4;coll_4:8");
+ string t = string("") + "<function-name> name of the scaling algorithm.\n\t\teither " + scale_function_name_subsampling + " or " + scale_function_name_bitaggregation;
+ CommandLineParameter &clp_updatebuffer = cmlInter.addStringParameter(CommandLineParser::noShortName, "buffersize", "<buffer-size> number of cells that can be written in one go when using tiledupdate. If align is defined then the minimum update size is taken to be the value align in each dimension.", defaultUpdateBufferSize);
+ CommandLineParameter &cml_layerlist = cmlInter.addStringParameter(CommandLineParser::noShortName, "layerlist", "<list> list of files for merging: <\"layer[[;layer]...]\"> \n\t\tlayer: <filename:TruePattern:FalsePattern>\n\t\tTruePattern / FalsePattern:\n\t\tbinary pattern expressed as decimal number(e.g.: 01001 = 9)");
+ CommandLineParameter &clp_scalefunction = cmlInter.addStringParameter(CommandLineParser::noShortName, "scalefunction", t.c_str(), scale_function_name_subsampling);
+ CommandLineParameter &clientcommSleep = cmlInter.addStringParameter(CommandLineParser::noShortName, "clientcommsleep", "<seconds> number of seconds to wait till retry", "1");
+ CommandLineParameter &clientcommMaxRetry= cmlInter.addStringParameter(CommandLineParser::noShortName, "clientcommretry", "<tries> number of retries before giving up", "10");
+ CommandLineParameter &rpcMaxRetry = cmlInter.addStringParameter(CommandLineParser::noShortName, "rpcretry", "<tries> number of retries before giving up", "5");
+ CommandLineParameter &clp_Force = cmlInter.addFlagParameter(CommandLineParser::noShortName, "force", "force writing of files");
+ try {
+ cmlInter.processCommandLine(argc, argv);
+ }
+ catch(CmlException& err)
+ {
+ cout << usageHeader;
+ cmlInter.printHelp();
+ cout << usageFooter;
+ cout << "Error parsing command line:" << endl;
+ cout << err.what() << endl;
+ return ERRORPARSINGCOMMANDLINE;
+ }
+ try {
+ if (cmlInter.isPresent('h'))
+ {
+ cout << usageHeader;
+ cmlInter.printHelp();
+ cout << usageFooter;
+ return ALLDONE;
+ }
+ r_Tiling_Scheme ts = get_tiling_scheme_from_name(cmlInter.getValueAsString("tiling"));
+ switch (ts)
+ {
+ case r_NoTiling:
+ theTiling = new r_No_Tiling();
+ break;
+ case r_StatisticalTiling:
+ theTiling = new r_Stat_Tiling(cmlInter.getValueAsString("tilingparams"));
+ break;
+ case r_InterestTiling:
+ theTiling = new r_Interest_Tiling(cmlInter.getValueAsString("tilingparams"));
+ break;
+ case r_AlignedTiling:
+ theTiling = new r_Aligned_Tiling(cmlInter.getValueAsString("tilingparams"));
+ break;
+ case r_DirectionalTiling:
+ theTiling = new r_Dir_Tiling(cmlInter.getValueAsString("tilingparams"));
+ break;
+ case r_SizeTiling:
+ theTiling = new r_Size_Tiling(cmlInter.getValueAsString("tilingparams"));
+ break;
+ case r_RegularTiling:
+ return TILINGTYPENOTALLOWED;
+ default:
+ return UNKNOWNTILINGTYPE;
+ }
+ if (cmlInter.isPresent("scalelevels"))
+ {
+ retval = readScaleLevels(cmlInter.getValueAsString("scalelevels"));
+ if (retval != 0)
+ return retval;
+ }
+ testBed = cmlInter.isPresent("testbed");
+ force = cmlInter.isPresent("force");
+ transparent = cmlInter.isPresent("transparent");
+ printText = cmlInter.isPresent("printtext");
+ serverName = cmlInter.getValueAsString("server");
+ serverPort = cmlInter.getValueAsLong("port");
+ baseName = cmlInter.getValueAsString("database");
+ userName = cmlInter.getValueAsString("user");
+ passwd = cmlInter.getValueAsString("passwd");
+ storageFormat = get_data_format_from_name(cmlInter.getValueAsString("storageformat"));
+ storageFormatParams = cmlInter.getValueAsString("storageformatparams");
+ transferFormat = get_data_format_from_name(cmlInter.getValueAsString("transformat"));
+ transferFormatParams = cmlInter.getValueAsString("transformatparams");
+ inputFormat = get_data_format_from_name(cmlInter.getValueAsString("inputformat"));
+ inputFormatParams = cmlInter.getValueAsString("inputformatparams");
+ outputFormat = get_data_format_from_name(cmlInter.getValueAsString("outputformat"));
+ outputFormatParams = cmlInter.getValueAsString("outputformatparams");
+ outputFileName = cmlInter.getValueAsString("outputfilename");
+ RMInit::clientcommMaxRetry = clientcommMaxRetry.getValueAsLong();
+ RMInit::logOut << "Clientcomm retry set to " << RMInit::clientcommMaxRetry << endl;
+ RMInit::clientcommSleep = clientcommSleep.getValueAsLong();
+ RMInit::logOut << "Clientcomm sleep set to " << RMInit::clientcommSleep << endl;
+ RMInit::rpcMaxRetry = rpcMaxRetry.getValueAsLong();
+ RMInit::logOut << "RPC retry set to " << RMInit::rpcMaxRetry << endl;
+ if (cmlInter.isPresent("polygon"))
+ {
+ try {
+ r_Polygon p(cmlInter.getValueAsString("polygon"));
+ polygon.addPolygon(p);
+ polygonDefined = true;
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error reading the polygon: " << err.get_errorno() << " " << err.what() << endl;
+ return POLYGONCREATIONFAILED;
+ }
+ }
+ polygonShrinker = cmlInter.getValueAsLong("shrink");
+ if (cmlInter.isPresent("outsidepattern"))
+ {
+ outsidePatternDef = true;
+ outsidePattern = HexCodec::convertTo(cmlInter.getValueAsString("outsidepattern"));
+ }
+ if (cmlInter.isPresent("insidepattern"))
+ {
+ insidePatternDef = true;
+ insidePattern = HexCodec::convertTo(cmlInter.getValueAsString("insidepattern"));
+ }
+ if (cmlInter.isPresent("outsidepatternbackdrop"))
+ {
+ outsidePatternSelDef = true;
+ outsidePatternSel = HexCodec::convertTo(cmlInter.getValueAsString("outsidepatternbackdrop"));
+ }
+ if (cmlInter.isPresent("insidepatternbackdrop"))
+ {
+ insidePatternSelDef = true;
+ insidePatternSel = HexCodec::convertTo(cmlInter.getValueAsString("insidepatternbackdrop"));
+ }
+ setTypeName = cmlInter.getValueAsString("colltype");
+ mddTypeName = cmlInter.getValueAsString("mddtype");
+ collName = cmlInter.getValueAsString("collname");
+ if (cmlInter.isPresent("mddoid"))
+ {
+ mddOIdDef = true;
+ mddOId = r_OId(cmlInter.getValueAsString("mddoid"));
+ }
+ if (cmlInter.isPresent("colloid"))
+ {
+ collOIdDef = true;
+ cmlInter.getValueAsString("colloid");
+ }
+ if (cmlInter.isPresent("mdddomain"))
+ {
+ mddDomainDef = true;
+ mddDomain = r_Minterval(cmlInter.getValueAsString("mdddomain"));
+ }
+ if (cmlInter.isPresent("overlaydomain"))
+ {
+ overlayDomainDef = true;
+ overlayDomain = r_Minterval(cmlInter.getValueAsString("overlaydomain"));
+ }
+ else {
+ overlayDomain = mddDomain;
+ }
+ align = cmlInter.getValueAsLong("align");
+ if (align > 0)
+ {
+ overlayDomainDef = true;
+ for (r_Dimension dim = 0; dim < overlayDomain.dimension(); dim++)
+ {
+ r_Range high = overlayDomain[dim].high();
+ r_Range low = overlayDomain[dim].low();
+
+ r_Range highd = high%align;
+ if (high < 0)
+ high = high - highd - 1;
+ else
+ high = high + align - highd - 1;
+
+ r_Range lowd = overlayDomain[dim].low()%align;
+ if (low < 0)
+ low = low - align - lowd;
+ else
+ low = low - lowd;
+ overlayDomain[dim].set_interval(low, high);
+ }
+ RMInit::logOut << "Alignment changed overlay domain to " << overlayDomain << endl;
+ }
+ fileName = cmlInter.getValueAsString("read");
+ tiledUpdate = cmlInter.isPresent("tiledupdate");
+ if (tiledUpdate && fileName)
+ {
+ return TILEDUPDATEANDFILE;
+ }
+ conversionTypeName = cmlInter.getValueAsString("conversiontype");
+ scaleFunction = get_scale_function_from_name(cmlInter.getValueAsString("scalefunction"));
+ updateBufferSize = cmlInter.getValueAsLong("buffersize");
+ if (cmlInter.isPresent("layerlist"))
+ {
+ const char* endPos = NULL;
+ char* layerName = NULL;
+ const char* patternTName = NULL;
+ unsigned int patternT = 0;
+ unsigned int patternF = 0;
+ bool found = false;
+ size_t length = 0;
+ const char* startPos = cmlInter.getValueAsString("layerlist");
+ while (true)
+ {
+ endPos = index(startPos, ':');
+ if (endPos == NULL)
+ {
+ return LAYERSNOTCORRECT;
+ }
+ length = endPos - startPos;
+ layerName = new char[length + 1];
+ memset(layerName, 0, length + 1);
+ strncpy(layerName, startPos, length);
+ startPos = endPos + 1;
+ endPos = index(startPos, ':');
+ patternT = (unsigned int)atol(startPos);
+ startPos = endPos + 1;
+ endPos = index(startPos, ';');
+ patternF = (unsigned int)atol(startPos);
+ layerList.push_back(layerName);
+ patternsTrue.push_back(patternT);
+ patternsFalse.push_back(patternF);
+ RMInit::logOut << "Layer level : " << layerName << " (" << patternT << "," << patternF << ")" << endl;
+ if (endPos == NULL)
+ {
+ break;
+ }
+ startPos = endPos + 1;
+ }
+ RMInit::logOut << "Layer list : ";
+ std::list<char*>::iterator iterL = layerList.begin();
+ std::list<unsigned int>::iterator iterT = patternsTrue.begin();
+ std::list<unsigned int>::iterator iterF = patternsFalse.begin();
+ while (iterL != layerList.end())
+ {
+ RMInit::logOut << *iterL << "(" << *iterT << "," << *iterF << ") ";
+ iterL++;
+ iterT++;
+ iterF++;
+ }
+ RMInit::logOut << std::endl;
+ if (layerList.size() > (sizeof(r_ULong) * 8))
+ {
+ std::list<char*>::iterator iterL = layerList.begin();
+ while (iterL != layerList.end())
+ {
+ delete[] *iterL;
+ ++iterL;
+ }
+ return TOOMANYLAYERS;
+ }
+ }
+ }
+ catch(CmlException& err)
+ {
+ cout << usageHeader;
+ cmlInter.printHelp();
+ cout << usageFooter;
+ cout << "Error evaluating command line:" << endl;
+ cout << err.what() << endl;
+ return ERRORPARSINGCOMMANDLINE;
+ }
+ return retval;
+ }
+
+int
+SystemBasic::saveData(const char* fileNamePat, const char* data, r_Bytes length, const r_Minterval& dom)
+ {
+ RMInit::logOut << "SystemBasic::saveData(" << fileNamePat << ", DATA, " << length << ", " << dom << ")" << std::endl;
+ r_Primitive_Type* tp = new r_Primitive_Type("Char", r_Type::CHAR);
+ r_Convertor* conv = r_Convertor_Factory::create(r_PNG, data, dom, tp);
+ r_convDesc desc = conv->convertTo(NULL);
+ size_t dtaSize=desc.destInterv.cell_count()*tp->size();
+ std::ofstream o;
+ o.open(fileNamePat);
+ if (!o.is_open())
+ {
+ RMInit::logOut << "unable to open file " << fileNamePat << " for writing" << std::endl;
+ return FILEINACCESSIBLE;
+ }
+ o.write(desc.dest, dtaSize);
+ //fwrite(desc.dest, 1, dtaSize, tfile);
+ o.flush();
+ o.close();
+ free(desc.dest);
+ delete desc.destType;
+ delete conv;
+ delete tp;
+ return 0;
+ }
+
+void
+SystemBasic::openTransaction(bool readwrite) throw (r_Error)
+ {
+ db.set_servername(serverName, serverPort);
+ db.set_useridentification(userName, passwd);
+ db.open(baseName);
+ if (readwrite)
+ ta.begin(r_Transaction::read_write);
+ else
+ ta.begin(r_Transaction::read_only);
+ db.set_transfer_format(transferFormat, transferFormatParams);
+ db.set_storage_format(storageFormat, storageFormatParams);
+ }
+
+void
+SystemBasic::printScalar(const r_Scalar& scalar)
+ {
+ switch (scalar.get_type()->type_id())
+ {
+ case r_Type::BOOL:
+ cout << (((r_Primitive*)&scalar)->get_boolean() ? "T" : "F") << std::flush;
+ break;
+
+ case r_Type::CHAR:
+ cout << (int)((r_Primitive*)&scalar)->get_char() << std::flush;
+ break;
+
+ case r_Type::OCTET:
+ cout << (int)((r_Primitive*)&scalar)->get_octet() << std::flush;
+ break;
+
+ case r_Type::SHORT:
+ cout << ((r_Primitive*)&scalar)->get_short() << std::flush;
+ break;
+
+ case r_Type::USHORT:
+ cout << ((r_Primitive*)&scalar)->get_ushort() << std::flush;
+ break;
+
+ case r_Type::LONG:
+ cout << ((r_Primitive*)&scalar)->get_long() << std::flush;
+ break;
+
+ case r_Type::ULONG:
+ cout << ((r_Primitive*)&scalar)->get_ulong() << std::flush;
+ break;
+
+ case r_Type::FLOAT:
+ cout << ((r_Primitive*)&scalar)->get_float() << std::flush;
+ break;
+
+ case r_Type::DOUBLE:
+ cout << ((r_Primitive*)&scalar)->get_double() << std::flush;
+ break;
+
+ case r_Type::COMPLEXTYPE1:
+ case r_Type::COMPLEXTYPE2:
+ cout << "(" << ((r_Complex*)&scalar)->get_re() << ", " << ((r_Complex*)&scalar)->get_im() << ")" << std::flush;
+ break;
+
+ case r_Type::STRUCTURETYPE:
+ {
+ r_Structure* structValue = (r_Structure*)&scalar;
+ cout << " { " << std::flush;
+ for(int i=0; i<structValue->count_elements(); i++)
+ {
+ printScalar((*structValue)[i]);
+ if (i < structValue->count_elements()-1) cout << ", " << std::flush;
+ }
+ cout << " }" << endl;
+ }
+ break;
+ }
+ }
+
+int
+SystemBasic::convertFrom(r_Data_Format fmt, char*& src, size_t& dtaSize, r_Minterval& interv, r_Base_Type*& tp, const char* options)
+ {
+ int retval = 0;
+
+ r_Minterval tmpInt(1);
+ tmpInt << r_Sinterval((r_Range)0, (r_Range)dtaSize - 1);
+
+ RMInit::logOut << "convertFrom(...) " << endl;
+ RMInit::logOut << "domain in : " << tmpInt << endl;
+ RMInit::logOut << "type in : ";
+ tp->print_status(RMInit::logOut);
+ RMInit::logOut << endl;
+
+ if (fmt != r_Array)
+ {
+ try {
+ r_Convertor* conv = r_Convertor_Factory::create(fmt, src, tmpInt, tp);
+ r_Storage_Man_CPP mySM;
+ conv->set_storage_handler(mySM);
+ r_convDesc desc = conv->convertFrom(options);
+
+ if (desc.destType->isBaseType())
+ {
+ delete tp;
+ tp = (r_Base_Type*)desc.destType;
+ tmpInt = desc.destInterv;
+ dtaSize=tmpInt.cell_count()*tp->size();
+ delete [] src;
+ src = desc.dest;
+ delete conv;
+ conv = 0;
+ if (interv.dimension() != 0)
+ {
+ if (tmpInt.cell_count() != interv.cell_count())
+ {
+ RMInit::logOut << "Domains do not have the same number of cells (mdd " << interv << ", data " << tmpInt << ")" << endl;
+ retval = DOMAINDATAMISMATCH;
+ }
+ else {
+ if (tmpInt.get_extent() != interv.get_extent())
+ {
+ RMInit::logOut << "Domains do not have the same extents (mdd " << interv << ", data " << tmpInt << ")" << endl;
+ retval = DOMAINDATAMISMATCH;
+ }
+ }
+ }
+ else {
+ interv = tmpInt;
+ }
+ }
+ else {
+ RMInit::logOut << "Error conversion type is not a base type" << endl;
+ retval = CONVERSIONRETURNEDWRONGTYPE;
+ }
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error (" << obj.get_errorno() << ") when converting from " << fmt << " : " << obj.what() << endl;
+ retval = CONVERSIONEXCEPTION;
+ }
+ }
+ else {
+ if (dtaSize != (tp->size() * interv.cell_count()))
+ {
+ RMInit::logOut << "base type size " << tp->size() << " cells " << interv.cell_count() << " does not match size " << dtaSize << endl;
+ retval = DOMAINDATAMISMATCH;
+ }
+ }
+
+ RMInit::logOut << "domain out : " << interv << endl;
+ RMInit::logOut << "type out : ";
+ tp->print_status(RMInit::logOut);
+ RMInit::logOut << endl;
+
+ return retval;
+ }
+
+int
+SystemBasic::convertTo(r_Data_Format fmt, char*& src, size_t& dtaSize, r_Minterval& interv, r_Base_Type*& tp, const char* options)
+ {
+ int retval = 0;
+
+ RMInit::logOut << "convertTo(...)" << endl;
+ RMInit::logOut << "domain in : " << interv << endl;
+ RMInit::logOut << "type in : " ;
+ tp->print_status(RMInit::logOut);
+ RMInit::logOut << endl;
+
+ if (fmt != r_Array)
+ {
+ try {
+ r_Convertor* conv = r_Convertor_Factory::create(fmt, src, interv, tp);
+ r_convDesc desc = conv->convertTo(options);
+ RMInit::logOut << "Conversion type : ";
+ desc.destType->print_status(RMInit::logOut);
+ RMInit::logOut << endl;
+ if (desc.destType->isBaseType())
+ {
+ delete tp;
+ tp = (r_Base_Type*)desc.destType;
+ }
+ else {
+ RMInit::logOut << "Error conversion type is not a base type" << endl;
+ throw r_Error();
+ }
+ dtaSize = desc.destInterv.cell_count() * tp->size(); // desc.destInterv[0].high() - desc.destInterv[0].low() + 1;
+ interv=desc.destInterv;
+ delete src;
+ src = desc.dest;
+ delete conv;
+ conv = 0;
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error (" << obj.get_errorno() << ") when converting to " << fmt << " : " << obj.what() << endl;
+ retval = CONVERSIONEXCEPTION;
+ }
+ }
+ else {
+ if (dtaSize != (tp->size() * interv.cell_count()))
+ {
+ RMInit::logOut << "base type size " << tp->size() << " cells " << interv.cell_count() << " does not match size " << dtaSize << endl;
+ retval = DOMAINDATAMISMATCH;
+ }
+ }
+
+ RMInit::logOut << "domain out : " << interv << endl;
+ RMInit::logOut << "type out : " ;
+ tp->print_status(RMInit::logOut);
+ RMInit::logOut << endl;
+
+ return retval;
+ }
+
+FILE*
+SystemBasic::checkFile(const char* fileN, int& retval)
+ {
+ FILE* fileD = NULL;
+ if ((fileD = fopen(fileN, "r")) == NULL)
+ retval = FILEINACCESSIBLE;
+ return fileD;
+ }
+
+char*
+SystemBasic::getData(FILE* file, size_t& dtaSize, int& retval)
+ {
+ char* dta = 0;
+ size_t size = 0;
+ fseek(file, 0, SEEK_END);
+ size = ftell(file);
+ RMInit::logOut << "getData(...)" << endl;
+ RMInit::logOut << "File size : " << size << endl;
+ try {
+ dta = new char[size];
+ }
+ catch(std::bad_alloc) {
+ RMInit::logOut << "Unable to claim memory(" << size << "B)!" << endl;
+ retval = UNABLETOCLAIMRESOURCEFORFILE;
+ return dta;
+ }
+
+ fseek(file, 0, SEEK_SET);
+ fread(dta, 1, size, file);
+ fclose(file);
+ dtaSize = size;
+ return dta;
+ }
+
+int
+SystemBasic::readScaleLevels(const char* startPos)
+ {
+ int retval = 0;
+ scaleLevels = new std::list<std::pair<double, char*> >();
+ const char* endPos = NULL;
+ char* levelName = NULL;
+ const char* factorName = NULL;
+ double factor = 0;
+ bool found = false;
+ size_t length = 0;
+ while (true)
+ {
+ endPos = index(startPos, ':');
+ if (endPos == NULL)
+ {
+ retval = SCALELEVELSINCORRECT;
+ delete scaleLevels;
+ scaleLevels = NULL;
+ break;
+ }
+ length = endPos - startPos;
+ levelName = new char[length + 1];
+ memset(levelName, 0, length + 1);
+ strncpy(levelName, startPos, length);
+ startPos = endPos + 1;
+ endPos = index(startPos, ';');
+ factor = atof(startPos);
+ factor = 1 / factor;
+ scaleLevels->push_back(std::pair<double, char*>(factor, levelName));
+ RMInit::logOut << "Scale level : " << levelName << " (" << factor << ")" << endl;
+ if (endPos == NULL)
+ {
+ break;
+ }
+ startPos = endPos + 1;
+ }
+ return retval;
+ }
+
+void
+SystemBasic::explainRetval(int retval)
+ {
+ switch (retval)
+ {
+ case EXCEPTIONEXECUTEQUERY:
+ cout << "An exception occured during execution of the query" << endl;
+ cout << "Check the RasDaMan exception." << endl;
+ break;
+ case TILINGPATAMETERSINCORRECT:
+ cout << "Tiling parameters incorrect" << endl;
+ cout << "Check the specification of the tiling parameters for the tiling strategy you chose." << endl;
+ break;
+ case UNKNOWNTILINGTYPE:
+ cout << "Unknown tiling type specified" << endl;
+ cout << "Please review your --tiling option." << endl;
+ break;
+ case TILINGPARAMETERSMISSING:
+ cout << "You specified a tiling option which requires additional parameters" << endl;
+ cout << "Please specify a --tilingparameter option. For information on the format consult the --help option. For information on the meaning of the parameters consult the RasDaMan c++ documentation of the apropriate tiling." << endl;
+ break;
+ case CONVERSIONEXCEPTION:
+ cout << "An exception occured during conversion" << endl;
+ break;
+ case CONVERSIONNOTSUPPORTED:
+ cout << "The specified conversion format is not supported" << endl;
+ break;
+ case NOQUERY:
+ cout << "Cannot read query from file" << endl;
+ break;
+ case ARGUMENTSMISSING:
+ cout << "There are arguments missing" << endl;
+ cout << "You must specify --arg1 in order to specify --arg2 ..." << endl;
+ break;
+ case ARGUMENTSINCOMPLETE:
+ cout << "There are arguments missing" << endl;
+ cout << "You must specify --arg? --arg?domain --arg?type, where ? can be 1, 2, 3 or 4" << endl;
+ break;
+ case CREATEANDNOCREATE:
+ cout << "You specified create and no create" << endl;
+ cout << "Please decide on one." << endl;
+ break;
+ case NOVALIDDOMAIN:
+ cout << "No valid domain" << endl;
+ cout << "Please use something like \"[0:*,-2:9]\"." << endl;
+ break;
+ case FILEINACCESSIBLE:
+ cout << "Cannot access one of the files" << endl;
+ break;
+ case FILENAMETOLONG:
+ cout << "File name too long" << endl;
+ break;
+ case NOCREATECREATECOLL:
+ cout << "You specified to not create a collection, but want to create one" << endl;
+ break;
+ case NOCOLLTYPE:
+ cout << "No collection type specified" << endl;
+ break;
+ case COLLOIDANDCOLLNAME:
+ cout << "Do not specify collection name and collection oid" << endl;
+ break;
+ case CREATECOLLWITHOID:
+ cout << "Cannot use user specified oid to create collection" << endl;
+ break;
+ case CREATEMDDWITHOID:
+ cout << "Cannot use user specified oid to create marray" << endl;
+ break;
+ case INVALIDTILESIZE:
+ cout << "Tile size is invalid" << endl;
+ break;
+ case DOMAINDATAMISMATCH:
+ cout << "Domain extent does not match size of data file" << endl;
+ break;
+ case MDDDOMAINNOTSPECIFIED:
+ cout << "Domain for marray not specified" << endl;
+ break;
+ case FILENAMENOTSPECIFIED:
+ cout << "File name not specified" << endl;
+ break;
+ case NOCOLLNAMENOCOLLOID:
+ cout << "Neither collection name nor collection oid specified" << endl;
+ break;
+ case MDDTYPEINVALID:
+ cout << "Marray type not valid" << endl;
+ break;
+ case NOBASETYPE:
+ cout << "No base type in marray type" << endl;
+ break;
+ case EXCEPTIONCREATECOLL:
+ cout << "Exception while creating collection" << endl;
+ break;
+ case EXCEPTIONADMIN:
+ cout << "Exception while performing administrativ action" << endl;
+ break;
+ case COLLECTIONINACCESSIBLE:
+ cout << "Collection not accessible" << endl;
+ break;
+ case OIDINVALID:
+ cout << "Specified oid is invalid" << endl;
+ cout << "Please use something like \"Oracle|RASBASE|1025\"." << endl;
+ break;
+ case MDDINACCESSIBLE:
+ cout << "Marray not accessible" << endl;
+ break;
+ case MDDOIDANDCOLL:
+ cout << "MDD oid and collection specified" << endl;
+ cout << "I can either update a whole collection or just one marray." << endl;
+ break;
+ case CONVERSIONTYPENOTABASETYPE:
+ cout << "Conversion type is not a base type." << endl;
+ cout << "Please supply a valid base type as a conversion type." << endl;
+ break;
+ case CONVERSIONRETURNEDWRONGTYPE:
+ cout << "The conversion module returned a type that was not a base type." << endl;
+ cout << "Please contact customer support." << endl;
+ break;
+ case POLYGONCREATIONFAILED:
+ cout << "The string passed to the polygon switch was wrong." << endl;
+ break;
+ case OVERLAYDOMAINSDONOTMATCH:
+ cout << "The domains of the MDD objects to overlay do not match." << endl;
+ break;
+ case OVERLAYTYPESIZESDONOTMATCH:
+ cout << "The type sizes of the MDD objects to overlay do not match." << endl;
+ break;
+ case POLYGONDOMAINTOOLARGE:
+ cout << "The domain of the MDD object does not cover the bounding box of the polygon." << endl;
+ break;
+ case NOCOLLNAMEDEFINED:
+ cout << "No collection name defined." << endl;
+ break;
+ case NOMDDTYPEDEFINED:
+ cout << "No mdd type defined." << endl;
+ break;
+ case MDDTYPEOFGMARRAYNOTINITIALISED:
+ cout << "MDD type of GMarray not initialised." << endl;
+ break;
+ case SCALEDOMAINISNOTCORRECT:
+ cout << "Scale domain is not correct." << endl;
+ break;
+ case SCALELEVELSINCORRECT:
+ cout << "Scale levels are not correct." << endl;
+ break;
+ case GMARRAYSARENOTEQUAL:
+ cout << "The GMarrays were not equal." << endl;
+ break;
+ case UNKNOWNSCALEFUNCTION:
+ cout << "The supplied scale function is unknown." << endl;
+ break;
+ case UNABLETOCLAIMRESOURCEFORFILE:
+ cout << "Unable to claim memory for the input files." << endl;
+ break;
+ case ERRORPARSINGCOMMANDLINE:
+ cout << "Error parsing the command line." << endl;
+ break;
+ case TILINGTYPENOTALLOWED:
+ cout << "The tiling type is not allowed." << endl;
+ break;
+ case LAYERSNOTCORRECT:
+ cout << "The layer parameter is not correct." << endl;
+ break;
+ case TOOMANYLAYERS:
+ cout << "There are too many layers defined for the merging." << endl;
+ break;
+ case OVERLAYDOMAINDOESNOTMATCH:
+ cout << "The overlay domain does not cover the domain of the input file." << endl;
+ break;
+ case TILEDUPDATEANDFILE:
+ cout << "Option tiledupdate and file specified." << endl;
+ break;
+ case NOCOMPAREDESTINATION:
+ cout << "Need either a file or a collection name to get the source data for the compare operation." << endl;
+ break;
+ case CONVERSIONTYPEMISSING:
+ cout << "Conversion type is missing." << endl;
+ break;
+ default :
+ cout << "Unknown execution code: " << retval << endl;
+ break;
+ case ALLDONE:
+ case 0:
+ cout << "No errors" << endl;
+ }
+ delete theTiling;
+ theTiling = NULL;
+ if (scaleLevels != NULL)
+ {
+ std::list<std::pair<double, char*> >::iterator iter = scaleLevels->begin();
+ std::list<std::pair<double, char*> >::iterator end = scaleLevels->end();
+ for (; iter != end; iter++)
+ {
+ delete [] (*iter).second;
+ (*iter).second = NULL;
+ }
+ delete scaleLevels;
+ scaleLevels = NULL;
+ }
+ }
+
+int
+SystemBasic::initGMarray(r_Ref<r_GMarray>& tempMDD, FILE* tempFile, r_Data_Format conversionFormat, r_Minterval& tempDataDomain, const char* conversionParams) throw (r_Error)
+ {
+ int retval = 0;
+ char* mddData = NULL;
+ size_t mddDataSize = 0;
+ r_Type* tempType = NULL;
+ r_Base_Type* conversionType = NULL;
+ const r_Base_Type* tempBaseType = (r_Base_Type*)tempMDD->get_base_type_schema();
+ if (tempBaseType != NULL)
+ {
+ mddData = getData(tempFile, mddDataSize, retval);
+ if (retval != 0)
+ return retval;
+ try {
+ tempType = r_Type::get_any_type(conversionTypeName);
+ }
+ catch (const r_Error& err)
+ {
+ RMInit::logOut << "Resolving conversion type: Exception in get_any_type: " << err.get_errorno() << " " << err.what() << endl;
+ delete tempType;
+ tempType = NULL;
+ retval = CONVERSIONTYPENOTABASETYPE;
+ }
+ if (!tempType->isBaseType())
+ {
+ retval = CONVERSIONTYPENOTABASETYPE;
+ delete tempType;
+ tempType = NULL;
+ }
+ else {
+ conversionType = (r_Base_Type*)tempType;
+ retval = convertFrom(conversionFormat, mddData, mddDataSize, tempDataDomain, conversionType, conversionParams);
+ if (retval == 0)
+ {
+ tempMDD->set_array_size(mddDataSize);
+ tempMDD->set_type_length(conversionType->size());
+ delete [] tempMDD->get_array();
+ tempMDD->set_array(mddData);
+ mddData = 0;
+ if (polygonDefined)
+ {
+/* should be done in r_PolygonCutOut
+ if (tempMDD->spatial_domain().covers(polygon.getBoundingBox()))
+ {
+*/
+ polygon.setMArray(*tempMDD);
+ if (insidePatternDef)
+ polygon.fillMArrayInside(insidePattern);
+ if (outsidePatternDef)
+ polygon.fillMArrayOutside(outsidePattern);
+/* should be done in r_PolygonCutOut
+ }
+ else {
+ RMInit::logOut << "Polygon Bounding Box " << polygon.getBoundingBox() << " GMarray Bounding Box " << tempMDD->spatial_domain() << std::endl;
+ retval = POLYGONDOMAINTOOLARGE;
+ }
+*/
+ }
+ }
+ else {
+ delete [] mddData;
+ mddData = 0;
+ }
+ delete conversionType;
+ conversionType = NULL;
+ }
+ }
+ else {
+ retval = MDDTYPEOFGMARRAYNOTINITIALISED;
+ }
+ return retval;
+ }
+
+int
+SystemBasic::compareGMarrays(const r_Ref<r_GMarray>& baseMDD, r_Ref<r_GMarray>& topMDD)
+ {
+ int retval = 0;
+ //r_GMarray* baseMDD = (r_GMarray*)&(*baseMDD2);
+ const r_Minterval& tempDomain = baseMDD->spatial_domain();
+ char* topMDDCells = topMDD->get_array();
+ const char* baseMDDCells = baseMDD->get_array();
+ wrongBytes = 0;
+
+ RMInit::logOut << "compareGMarrays: " << std::endl;
+ RMInit::logOut << "baseMDD domain: " << baseMDD->spatial_domain() << " type length: " << baseMDD->get_type_length() << std::endl;
+ RMInit::logOut << "topMDD domain: " << topMDD->spatial_domain() << " type length: " << topMDD->get_type_length() << std::endl;
+ if (tempDomain == topMDD->spatial_domain())
+ {
+ r_Bytes typeLen = baseMDD->get_type_length();
+ if (typeLen == topMDD->get_type_length())
+ {
+ r_Area numberCells = tempDomain.cell_count();
+
+ for (size_t elemNum = 0; elemNum < numberCells; elemNum++)
+ {
+ if (memcmp(&(baseMDDCells[elemNum * typeLen]), &(topMDDCells[elemNum * typeLen]), typeLen) != 0)
+ {
+ wrongBytes++;
+ }
+ }
+ wrongBytes*=typeLen;
+ }
+ else {
+ retval = OVERLAYTYPESIZESDONOTMATCH;
+ }
+ }
+ else {
+ retval = OVERLAYDOMAINSDONOTMATCH;
+ }
+ if (wrongBytes != 0)
+ {
+ retval = GMARRAYSARENOTEQUAL;
+ }
+ return retval;
+ }
+
+int
+SystemBasic::overlayGMarrays(r_Ref<r_GMarray>& targetMDD, const r_Ref<r_GMarray>& replaceBlackMDD, const r_Ref<r_GMarray>& backgroundMDD)
+ {
+ int retval = 0;
+
+ const r_Minterval& backgroundDomain = backgroundMDD->spatial_domain();
+ const r_Minterval& replaceBlackDomain = replaceBlackMDD->spatial_domain();
+ const r_Minterval& targetDomain = targetMDD->spatial_domain();
+
+ const char* replaceBlackMDDCells = replaceBlackMDD->get_array();
+ const char* backgroundMDDCells = backgroundMDD->get_array();
+ char* targetMDDCells = targetMDD->get_array();
+
+ RMInit::logOut << "overlayGMarrays: " << std::endl;
+ RMInit::logOut << "background MDD domain : " << backgroundMDD->spatial_domain() << " type length: " << backgroundMDD->get_type_length() << std::endl;
+ RMInit::logOut << "replace black MDD domain: " << replaceBlackMDD->spatial_domain() << " type length: " << replaceBlackMDD->get_type_length() << std::endl;
+ RMInit::logOut << "target MDD domain : " << targetMDD->spatial_domain() << " type length: " << replaceBlackMDD->get_type_length() << std::endl;
+
+ r_Bytes typeLen = backgroundMDD->get_type_length();
+ if ((typeLen == replaceBlackMDD->get_type_length()) && (typeLen == targetMDD->get_type_length()))
+ {
+ char* reference = new char[typeLen];
+ memset(reference, 0, typeLen);
+ if (backgroundDomain.get_extent() == targetDomain.get_extent())
+ //if ((backgroundDomain.get_extent() == replaceBlackDomain.get_extent()) && ((backgroundDomain.get_extent() == targetDomain.get_extent())))
+ {
+ if (backgroundDomain.get_extent() == replaceBlackDomain.get_extent())
+ {//background and target and transparent are equal
+ RMInit::logOut << "Overlay using fast method" << endl;
+ r_Area numberCells = backgroundDomain.cell_count();
+ for (size_t elemNum = 0; elemNum < numberCells; elemNum++)
+ {
+ if (memcmp(reference, &(replaceBlackMDDCells[elemNum * typeLen]), typeLen) == 0)
+ {
+ memcpy(&(targetMDDCells[elemNum * typeLen]), &(backgroundMDDCells[elemNum * typeLen]), typeLen);
+ }
+ else {
+ memcpy(&(targetMDDCells[elemNum * typeLen]), &(replaceBlackMDDCells[elemNum * typeLen]), typeLen);
+ }
+ }
+ }
+ else {//background and target are equal in size, but not equal to transparent
+ if (backgroundMDDCells == targetMDDCells)
+ {
+ RMInit::logOut << "Overlay background and target not neccessary" << endl;
+ }
+ else {
+ RMInit::logOut << "Overlay background and target using very fast method" << endl;
+ memcpy(targetMDDCells, backgroundMDDCells, backgroundDomain.cell_count() * typeLen);
+ }
+ //overlay target and transparent
+ r_Minterval overlayOn = replaceBlackDomain.create_intersection(backgroundDomain);
+ RMInit::logOut << "Overlay using slow method on " << overlayOn << endl;
+ r_Dimension dim = targetDomain.dimension();
+ r_Range width = overlayOn[dim - 1].get_extent();
+ r_MiterDirect replaceBlackIter((char*)replaceBlackMDDCells, replaceBlackDomain, overlayOn, typeLen);
+ r_MiterDirect targetIter((char*)targetMDDCells, targetDomain, overlayOn, typeLen);
+ while (!replaceBlackIter.isDone())
+ {
+ replaceBlackMDDCells = (const char*)replaceBlackIter.getData();
+ targetMDDCells = (char*)targetIter.getData();
+ for (size_t elemNum = 0; elemNum < width; elemNum++)
+ {
+ if (memcmp(reference, &(replaceBlackMDDCells[elemNum * typeLen]), typeLen) != 0)
+ {
+ memcpy(&(targetMDDCells[elemNum * typeLen]), &(replaceBlackMDDCells[elemNum * typeLen]), typeLen);
+ }
+ }
+ replaceBlackIter.id[dim-1].pos += width;
+ targetIter.id[dim-1].pos += width;
+ ++replaceBlackIter;
+ ++targetIter;
+ }
+ }
+ }
+ else {//background and target are not the same size. it does not matter if transparent is same as background
+ //need to use a miter, done as in Tile::copyTile, res is replaceBlack, op is background
+ r_Minterval overlayOn = replaceBlackDomain.create_intersection(backgroundDomain);
+ if (targetDomain.covers(overlayOn))
+ {//first copy background on top of target
+ RMInit::logOut << "Overlay using slow method on " << overlayOn << endl;
+ r_Minterval copyBackgroundDomain = targetDomain.create_intersection(backgroundDomain);
+ r_Dimension dim = copyBackgroundDomain.dimension();
+ r_Range backgroundWidth = copyBackgroundDomain[dim - 1].get_extent();
+ r_MiterDirect backgroundIter((char*)backgroundMDDCells, backgroundDomain, overlayOn, typeLen);
+ r_MiterDirect targetIter((char*)targetMDDCells, targetDomain, overlayOn, typeLen);
+ while (!targetIter.isDone())
+ {
+ backgroundMDDCells = (const char*)backgroundIter.getData();
+ targetMDDCells = (char*)targetIter.getData();
+
+ memcpy(targetMDDCells, backgroundMDDCells, typeLen * backgroundWidth);
+
+ backgroundIter.id[dim-1].pos += backgroundWidth;
+ targetIter.id[dim-1].pos += backgroundWidth;
+ ++backgroundIter;
+ ++targetIter;
+ }
+ targetMDDCells = targetMDD->get_array();
+
+ //overlay transparent over target
+ r_Range width = overlayOn[dim - 1].get_extent();
+ r_MiterDirect replaceBlackIter((char*)replaceBlackMDDCells, replaceBlackDomain, overlayOn, typeLen);
+ r_MiterDirect targetIter2((char*)targetMDDCells, targetDomain, overlayOn, typeLen);
+ while (!replaceBlackIter.isDone())
+ {
+ replaceBlackMDDCells = (const char*)replaceBlackIter.getData();
+ targetMDDCells = (char*)targetIter2.getData();
+ for (size_t elemNum = 0; elemNum < width; elemNum++)
+ {
+ if (memcmp(reference, &(replaceBlackMDDCells[elemNum * typeLen]), typeLen) != 0)
+ {
+ memcpy(&(targetMDDCells[elemNum * typeLen]), &(replaceBlackMDDCells[elemNum * typeLen]), typeLen);
+ }
+ }
+ replaceBlackIter.id[dim-1].pos += width;
+ targetIter2.id[dim-1].pos += width;
+ ++replaceBlackIter;
+ ++targetIter2;
+ }
+ }
+ else {
+ RMInit::logOut << "Target domain does not cover the overlay domain" << endl;
+ retval = OVERLAYDOMAINDOESNOTMATCH;
+ }
+ }
+ delete [] reference;
+ reference = NULL;
+ }
+ else {
+ retval = OVERLAYTYPESIZESDONOTMATCH;
+ }
+ return retval;
+ }
+
+int
+SystemBasic::scaleDomain(const r_Minterval& baseDomain, const r_Point& origin, double factor, r_Minterval& scaledDomain, r_Minterval& clipDomain, unsigned int& length)
+ {
+ int retval = 0;
+ r_Dimension dim = origin.dimension();
+ r_Dimension i = 0;
+ scaledDomain = r_Minterval(dim);
+ clipDomain = r_Minterval(dim);
+ r_Range low = 0;
+ r_Range high = 0;
+ r_Range baseSteps = 0;
+ r_Range scaleSteps = 0;
+ r_Range originVal = 0;
+ length = floor(1.0 / factor + 0.5);
+ if (baseDomain.dimension() == dim)
+ {
+ try {
+ for (; i < dim; i++)
+ {
+ const r_Sinterval& baseSinterval = baseDomain[i];
+ originVal = origin[i];
+ // simple trafo of low coordinate
+ low = (r_Range)(originVal + floor((baseSinterval.low() - originVal) * factor));
+ // for the high coordinate use the low coordinate of the _next_ tile
+ // ( = baseDomain[i].high() + 1 ) and subtract 1 ==> seamless tilingfactor
+ high = (r_Range)(originVal + floor((baseSinterval.high() + 1 - originVal) * factor) - 1);
+ // number of steps in base interval
+ baseSteps = floor((baseSinterval.high() - baseSinterval.low() + length) / length);
+ // number of steps in scaled interval
+ scaleSteps = high - low + 1;
+ if (baseSteps == scaleSteps)
+ {// everything is ok
+ scaledDomain << r_Sinterval(low, high);
+ clipDomain << baseSinterval;
+ }
+ else {
+ if (baseSteps < scaleSteps)
+ {// the base is too small -> shrink the scale interval
+ RMInit::logOut << "WARNING: " << baseDomain << " * " << factor << " : clipping the scale interval" << endl;
+ scaledDomain << r_Sinterval(low, low + baseSteps - 1);
+ clipDomain << baseSinterval;
+ }
+ else {// the scale is too small -> shrink the clip interval
+ RMInit::logOut << "WARNING: " << baseDomain << " * " << factor << " : clipping the base interval" << endl;
+ scaledDomain << r_Sinterval(low, high);
+ clipDomain << r_Sinterval(baseSinterval.low(), (r_Range)(baseSinterval.low() + scaleSteps * length - 1));
+ }
+ }
+ }
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "SystemBasic::scaleDomain(" << baseDomain << ", " << scaleDomain << ", " << factor << ", " << origin << ") caught error : " << err.get_errorno() << " " << err.what() << endl;
+ retval = SCALEDOMAINISNOTCORRECT;
+ }
+ }
+ else {
+ retval = SCALEDOMAINISNOTCORRECT;
+ }
+ return retval;
+ }
+
+int
+SystemBasic::updateScaledMDD(const r_Ref<r_GMarray>& baseMDD, const r_Minterval& clipDomain, const r_Minterval& downScaleDomain, unsigned int length, const char* collectionName) throw (r_Error)
+ {
+ RMInit::logOut << "SystemBasic::updateScaledMDD(MDD, " << clipDomain << ", " << downScaleDomain << ", " << length << ", " << collectionName << ")" << endl;
+ int retval = 0;
+ const r_Minterval& baseDomain = baseMDD->spatial_domain();
+ if (retval == 0)
+ {
+ size_t tlen = baseMDD->get_type_length();
+ r_Ref<r_GMarray> scaledMDD = new (baseMDD->get_type_name())r_GMarray(downScaleDomain, tlen);
+ const r_Type* type = scaledMDD->get_base_type_schema();
+ if (type != NULL)
+ {
+ if (type->isPrimitiveType())
+ {
+ fast_scale_process_primitive_type((const r_Primitive_Type*)type, scaledMDD->get_array(), baseMDD->get_array(), downScaleDomain, baseDomain, clipDomain, tlen, length, scaleFunction);
+ }
+ else {
+ if (type->isStructType())
+ {
+ fast_scale_process_structured_type((const r_Structure_Type*)type, scaledMDD->get_array(), baseMDD->get_array(), downScaleDomain, baseDomain, clipDomain, tlen, length, scaleFunction);
+ }
+ else {
+ retval = NOBASETYPE;
+ }
+ }
+ }
+ else {
+ retval = NOBASETYPE;
+ }
+ if (retval == 0)
+ {//update the collection
+ std::ostringstream stream;
+ stream << "UPDATE " << collectionName << " AS A SET A" << downScaleDomain << " ASSIGN $1";
+ r_OQL_Query query(stream.str().c_str());
+ query << *scaledMDD;
+ RMDBGIF(20, RMDebug::module_tools, "WAITBEFOREQL", \
+ RMInit::dbgOut << "Waiting 10 sec before execute\n" << std::endl; \
+ sleep(10); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ r_oql_execute(query);
+ RMDBGIF(20, RMDebug::module_tools, "WAITAFTERQL", \
+ RMInit::dbgOut << "Waiting 10 sec after execute\n" << std::endl; \
+ sleep(10); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ }
+ scaledMDD.destroy();
+ }
+ return retval;
+ }
+
+int
+SystemBasic::compareScaledMDD(const r_Ref<r_GMarray>& baseMDD, const r_Minterval& clipDomain, const r_Minterval& downScaleDomain, unsigned int length, const char* collectionName) throw (r_Error)
+ {
+ RMInit::logOut << "SystemBasic::compareScaledMDD(MDD, " << clipDomain << ", " << downScaleDomain << ", " << length << ", " << collectionName << ")" << endl;
+ int retval = 0;
+ const r_Minterval& baseDomain = baseMDD->spatial_domain();
+ if (retval == 0)
+ {
+ size_t tlen = baseMDD->get_type_length();
+ r_Ref<r_GMarray> scaledMDD = new (baseMDD->get_type_name())r_GMarray(downScaleDomain, tlen);
+ const r_Type* type = ((r_GMarray*)&*baseMDD)->get_base_type_schema();
+ if (type != NULL)
+ {
+ if (type->isPrimitiveType())
+ {
+ fast_scale_process_primitive_type((const r_Primitive_Type*)type, scaledMDD->get_array(), baseMDD->get_array(), downScaleDomain, baseDomain, clipDomain, tlen, length, scaleFunction);
+ }
+ else {
+ if (type->isStructType())
+ {
+ fast_scale_process_structured_type((const r_Structure_Type*)type, scaledMDD->get_array(), baseMDD->get_array(), downScaleDomain, baseDomain, clipDomain, tlen, length, scaleFunction);
+ }
+ else {
+ RMInit::logOut << "scaledMDD returned a type (" << type->name() << ") which is neither primitive nor structured" << endl;
+ retval = NOBASETYPE;
+ }
+ }
+ }
+ else {
+ RMInit::logOut << "scaledMDD returned no base type schema" << endl;
+ retval = NOBASETYPE;
+ }
+ if (retval == 0)
+ {//update the collection
+ std::ostringstream stream;
+ stream << "SELECT A" << downScaleDomain << " FROM " << collectionName << " AS A";
+ r_OQL_Query query(stream.str().c_str());
+ r_Set< r_Ref_Any > result;
+ r_oql_execute(query, result);
+ r_Iterator< r_Ref_Any > iter = result.create_iterator();
+ r_Ref<r_GMarray> selectedMDD = r_Ref<r_GMarray>(*iter);
+ if (retval == 0)
+ {
+ retval = compareGMarrays(selectedMDD, scaledMDD);
+ if ((outputFileName != NULL) && ((retval != 0) || (force)))
+ {
+ char* tempName = new char[strlen(outputFileName) + strlen("image.png") + strlen(collectionName) + 1];
+ strcpy(tempName, outputFileName);
+ strcat(tempName, collectionName);
+ strcat(tempName, ".db.png");
+ saveData(tempName, selectedMDD->get_array(), selectedMDD->get_array_size(), selectedMDD->spatial_domain());
+ strcpy(tempName, outputFileName);
+ strcat(tempName, collectionName);
+ strcat(tempName, ".scaled.png");
+ saveData(tempName, scaledMDD->get_array(), scaledMDD->get_array_size(), scaledMDD->spatial_domain());
+ delete [] tempName;
+ tempName = NULL;
+ }
+ }
+ selectedMDD.destroy();
+ }
+ scaledMDD.destroy();
+ }
+ return retval;
+ }
+
+void
+fast_scale_process_primitive_type(const r_Primitive_Type *primType, char *dest, const char *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &srcIter, unsigned int type_len, unsigned int length, r_Scale_Function func)
+ {
+ if (func == r_BitAggregation)
+ {
+ switch (primType->type_id())
+ {
+ case r_Primitive_Type::BOOL:
+ case r_Primitive_Type::CHAR:
+ case r_Primitive_Type::OCTET:
+ fast_scale_aggregate_array((char*)dest, (const char*)src, destIv, srcIv, srcIter, type_len, length);
+ break;
+ case r_Primitive_Type::SHORT:
+ case r_Primitive_Type::USHORT:
+ fast_scale_aggregate_array((short*)dest, (const short*)src, destIv, srcIv, srcIter, type_len, length);
+ break;
+ case r_Primitive_Type::LONG:
+ case r_Primitive_Type::ULONG:
+ case r_Primitive_Type::FLOAT:
+ fast_scale_aggregate_array((int*)dest, (const int*)src, destIv, srcIv, srcIter, type_len, length);
+ break;
+ case r_Primitive_Type::DOUBLE:
+ fast_scale_aggregate_array((long long*)dest, (const long long*)src, destIv, srcIv, srcIter, type_len, length);
+ break;
+ default:
+ RMInit::logOut << "Resample Array: unknown primitive type " << primType->type_id() << endl;
+ break;
+ }
+ }
+ else {
+ switch (primType->type_id())
+ {
+ case r_Primitive_Type::BOOL:
+ fast_scale_resample_array((r_Boolean*)dest, (const r_Boolean*)src, destIv, srcIv, srcIter, type_len, length, true);
+ break;
+ case r_Primitive_Type::CHAR:
+ fast_scale_resample_array((r_Char*)dest, (const r_Char*)src, destIv, srcIv, srcIter, type_len, length, true);
+ break;
+ case r_Primitive_Type::OCTET:
+ fast_scale_resample_array((r_Octet*)dest, (const r_Octet*)src, destIv, srcIv, srcIter, type_len, length, true);
+ break;
+ case r_Primitive_Type::SHORT:
+ fast_scale_resample_array((r_Short*)dest, (const r_Short*)src, destIv, srcIv, srcIter, type_len, length, true);
+ break;
+ case r_Primitive_Type::USHORT:
+ fast_scale_resample_array((r_UShort*)dest, (const r_UShort*)src, destIv, srcIv, srcIter, type_len, length, true);
+ break;
+ case r_Primitive_Type::LONG:
+ fast_scale_resample_array((r_Long*)dest, (const r_Long*)src, destIv, srcIv, srcIter, type_len, length, true);
+ break;
+ case r_Primitive_Type::ULONG:
+ fast_scale_resample_array((r_ULong*)dest, (const r_ULong*)src, destIv, srcIv, srcIter, type_len, length, true);
+ break;
+ case r_Primitive_Type::FLOAT:
+ fast_scale_resample_array((r_Float*)dest, (const r_Float*)src, destIv, srcIv, srcIter, type_len, length, false);
+ break;
+ case r_Primitive_Type::DOUBLE:
+ fast_scale_resample_array((r_Double*)dest, (const r_Double*)src, destIv, srcIv, srcIter, type_len, length, false);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+void
+fast_scale_process_structured_type(const r_Structure_Type *structType, char *dest, const char *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &srcIter, unsigned int type_len, unsigned int length, r_Scale_Function func)
+ {
+ r_Structure_Type::attribute_iterator iter(structType->defines_attribute_begin());
+ while (iter != structType->defines_attribute_end())
+ {
+ r_Type *newType;
+ unsigned long offset;
+
+ newType = (*iter).type_of().clone();
+ offset = (*iter).offset();
+
+ if (newType->isStructType())
+ {
+ r_Structure_Type *newStructType = (r_Structure_Type*)newType;
+ fast_scale_process_structured_type(newStructType, dest + offset, src + offset, destIv, srcIv, srcIter, type_len, length, func);
+ }
+ else
+ {
+ r_Primitive_Type *newPrimType = (r_Primitive_Type*)newType;
+ fast_scale_process_primitive_type(newPrimType, dest + offset, src + offset, destIv, srcIv, srcIter, type_len, length, func);
+ }
+ delete newType;
+ iter++;
+ }
+ }
+
+
+// always iterate over the full dest domain, but not over the full src domain.
+template<class T>
+void fast_scale_resample_array(T *dest, const T *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &iterDom, unsigned int type_len, unsigned int length, bool round)
+ {
+ //cout << "here " << destIv << srcIv << iterDom << ", " << type_len << " " << length << endl;
+ r_MiterDirect destIter((void*)dest, destIv, destIv, type_len, 1);
+ r_MiterDirect subIter((void*)src, srcIv, iterDom, type_len, 1);
+ r_MiterDirect srcIter((void*)src, srcIv, iterDom, type_len, length);
+ unsigned int dim = (unsigned int)srcIv.dimension();
+ unsigned int i;
+
+ for (i=0; i<dim; i++)
+ {
+ subIter.id[i].low = 0;
+ }
+ while (srcIter.done == 0)
+ {
+ double sum = 0;
+ unsigned int count = 1;
+
+ // init sub iterator
+ subIter.done = 0;
+ for (i=0; i<dim; i++)
+ {
+ long rest;
+
+ subIter.id[i].pos = 0;
+ subIter.id[i].data = srcIter.getData();
+ rest = srcIter.id[i].high - srcIter.id[i].pos;
+ if (rest >= (long)length)
+ rest = (long)length-1;
+ subIter.id[i].high = rest;
+ count *= rest+1;
+ }
+ while (subIter.done == 0)
+ {
+ sum += *((const T*)(subIter.getData()));
+ ++subIter;
+ }
+ // use round to nearest
+ if (round)
+ *((T*)(destIter.getData())) = (T)(sum / count + 0.5);
+ else
+ *((T*)(destIter.getData())) = (T)(sum / count);
+ //cout << (long)(((const T*)(srcIter.getData())) - src) << " , " << (long)(((T*)(destIter.getData())) - dest) << endl;
+ ++srcIter;
+ ++destIter;
+ }
+ }
+
+// always iterate over the full dest domain, but not over the full src domain.
+template<class T>
+void fast_scale_aggregate_array(T *dest, const T *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &iterDom, unsigned int type_len, unsigned int length)
+ {
+ //cout << "here " << destIv << srcIv << iterDom << ", " << type_len << " " << length << endl;
+ r_MiterDirect destIter((void*)dest, destIv, destIv, type_len, 1);
+ r_MiterDirect subIter((void*)src, srcIv, iterDom, type_len, 1);
+ r_MiterDirect srcIter((void*)src, srcIv, iterDom, type_len, length);
+ unsigned int dim = (unsigned int)srcIv.dimension();
+ unsigned int i;
+
+ for (i=0; i<dim; i++)
+ {
+ subIter.id[i].low = 0;
+ }
+ while (srcIter.done == 0)
+ {
+ T sum = 0;
+ unsigned int count = 1;
+
+ // init sub iterator
+ subIter.done = 0;
+ for (i=0; i<dim; i++)
+ {
+ long rest;
+
+ subIter.id[i].pos = 0;
+ subIter.id[i].data = srcIter.getData();
+ rest = srcIter.id[i].high - srcIter.id[i].pos;
+ if (rest >= (long)length)
+ rest = (long)length-1;
+ subIter.id[i].high = rest;
+ count *= rest+1;
+ }
+ while (subIter.done == 0)
+ {
+ sum |= *((const T*)(subIter.getData()));
+ ++subIter;
+ }
+ *((T*)(destIter.getData())) = sum;
+ //cout << (long)(((const T*)(srcIter.getData())) - src) << " , " << (long)(((T*)(destIter.getData())) - dest) << endl;
+ ++srcIter;
+ ++destIter;
+ }
+ }
+
+#ifdef TESTBASIC
+int
+main(int argc, const char** argv)
+ {
+ r_Minterval baseDomain("[0:1024]");
+ r_Point origin("[0]");
+ r_Point translation("[256]");
+ double factor = 0.5;
+ r_Minterval scaledDomain;
+ r_Minterval clipDomain;
+ unsigned int length = 0;
+ for (int o = 0; o < 1024; o++)
+ {
+ for (int i = 0; i < 1024; i++)
+ {
+ for (int a = 0; a < 8; a++)
+ {
+ SystemBasic::scaleDomain(baseDomain, origin, factor, scaledDomain, clipDomain, length);
+ if (clipDomain != baseDomain)
+ {
+ cout << "ERROR clip != base (" << factor << "): " << clipDomain << " " << baseDomain << endl;
+ }
+ factor = factor /2;
+ }
+ factor = 0.5;
+ baseDomain.translate(translation);
+ }
+ baseDomain = r_Minterval("[256:511]");
+ baseDomain[0].set_high(256 * (o + 2) - 1);
+ }
+ }
+#endif
diff --git a/rasodmg/test/system_basic.hh b/rasodmg/test/system_basic.hh
new file mode 100644
index 0000000..ef7d083
--- /dev/null
+++ b/rasodmg/test/system_basic.hh
@@ -0,0 +1,210 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+#ifndef _SYSTEMBASIC_HH_
+#define _SYSTEMBASIC_HH_
+
+class r_Tiling;
+
+// fopen, getc
+#include <stdio.h>
+#include <list>
+#include "raslib/mddtypes.hh"
+#include "raslib/minterval.hh"
+#include "raslib/scalar.hh"
+#include "raslib/odmgtypes.hh"
+#include "raslib/oid.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/ref.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/gmarray.hh"
+#include "rasodmg/polycutout.hh"
+#include "cmlparser.hh"
+
+class SystemBasic
+ {
+ public:
+ static char* getData(FILE* file, size_t& dtaSize, int& retval);
+
+ static void printScalar(const r_Scalar& scalar);
+
+ static int checkArguments(int argc, const char** argv, const char* searchText, int& optionValueIndex);
+
+ static void explainRetval(int retval);
+
+ static void printOptions();
+
+ static int parseParams(int argc, char** argv);
+
+ static FILE* checkFile(const char* fileArg, int& retval);
+
+ static int convertTo(r_Data_Format fmt, char*& src, size_t& size, r_Minterval& interv, r_Base_Type*& tp, const char* options);
+
+ static int convertFrom(r_Data_Format fmt, char*& src, size_t& size, r_Minterval& interv, r_Base_Type*& tp, const char* options);
+
+ static int readScaleLevels(const char* argv);
+
+ static int initGMarray(r_Ref<r_GMarray>& tempMDD, FILE* tempFile, r_Data_Format conversionFormat, r_Minterval& tempDataDomain, const char* conversionParams) throw (r_Error);
+
+ static int overlayGMarrays(r_Ref<r_GMarray>& target, const r_Ref<r_GMarray>& replaceBlackMDD, const r_Ref<r_GMarray>& backgroundMDD);
+
+ static int compareGMarrays(const r_Ref<r_GMarray>& baseMDD, r_Ref<r_GMarray>& topMDD);
+
+ static void openTransaction(bool readwrite = true) throw (r_Error);
+
+ static int compareScaledMDD(const r_Ref<r_GMarray>& baseMDD, const r_Minterval& clipDom, const r_Minterval& downScaledDomain, unsigned int length, const char* collectionName) throw (r_Error);
+
+ static int updateScaledMDD(const r_Ref<r_GMarray>& baseMDD, const r_Minterval& clipDom, const r_Minterval& downScaledDomain, unsigned int length, const char* collectionName) throw (r_Error);
+
+ static int scaleDomain(const r_Minterval& baseDomain, const r_Point& origin, double factor, r_Minterval& scaledDomain, r_Minterval& clipDomain, unsigned int& length);
+
+ static int saveData(const char* fileNamePat, const char* data, r_Bytes length, const r_Minterval& mddDomain);
+
+ static const char* serverName;
+ static r_ULong serverPort;
+ static const char* baseName;
+ static const char* userName;
+ static const char* passwd;
+ static bool printText;
+ static const char* outputFileName;
+ static const char* conversionTypeName;
+ static r_Data_Format inputFormat;
+ static const char* inputFormatParams;
+ static r_Data_Format outputFormat;
+ static const char* outputFormatParams;
+ static r_Data_Format transferFormat;
+ static const char* transferFormatParams;
+ static r_Data_Format storageFormat;
+ static const char* storageFormatParams;
+ static const char* collName;
+ static const char* setTypeName;
+ static const char* mddTypeName;
+ static r_OId mddOId;
+ static bool mddOIdDef;
+ static r_OId collOId;
+ static bool collOIdDef;
+ static const char* fileName;
+ static r_Database db;
+ static r_Transaction ta;
+ static r_Minterval mddDomain;
+ static bool mddDomainDef;
+ static bool testBed;
+ static r_Tiling* theTiling;
+ static bool polygonDefined;
+ static r_PolygonCutOut polygon;
+ static int polygonShrinker;
+ static bool transparent;
+ static string outsidePatternSel;
+ static bool outsidePatternSelDef;
+ static string insidePatternSel;
+ static bool insidePatternSelDef;
+ static string outsidePattern;
+ static bool outsidePatternDef;
+ static string insidePattern;
+ static bool insidePatternDef;
+ static const int queryBufferLength;
+ static std::list<std::pair<double, char*> >* scaleLevels;
+ static int wrongBytes;
+ static r_Scale_Function scaleFunction;
+ static const string tilingDesc;
+ static const string tilingParamsDesc;
+ static const char* noUsageHeader;
+ static const char* usageHeader;
+ static const char* noUsageFooter;
+ static const char* usageFooter;
+ static size_t updateBufferSize;
+ static const char* defaultUpdateBufferSize;
+ static std::list<char*> layerList;
+ static std::list<unsigned int> patternsTrue;
+ static std::list<unsigned int> patternsFalse;
+ static r_Minterval overlayDomain;
+ static bool overlayDomainDef;
+ static r_Range align;
+ static bool tiledUpdate;
+ static bool handleSignal;
+ static bool force;
+ };
+
+void signalHandler(int sig);
+
+void installSignalHandlers();
+
+#define QUERYBUFFERLENGTH 512
+
+#define ALLDONE -1
+#define OK 0
+#define CREATEANDNOCREATE 1
+#define NOVALIDDOMAIN 2
+#define FILEINACCESSIBLE 3
+#define FILENAMETOLONG 4
+#define NOCREATECREATECOLL 5
+#define NOCOLLTYPE 6
+#define COLLOIDANDCOLLNAME 7
+#define CREATECOLLWITHOID 8
+#define CREATEMDDWITHOID 9
+#define INVALIDTILESIZE 10
+#define DOMAINDATAMISMATCH 11
+#define MDDDOMAINNOTSPECIFIED 12
+#define FILENAMENOTSPECIFIED 13
+#define NOCOLLNAMENOCOLLOID 14
+#define MDDTYPEINVALID 15
+#define NOBASETYPE 16
+#define EXCEPTIONCREATECOLL 17
+#define EXCEPTIONADMIN 18
+#define COLLECTIONINACCESSIBLE 19
+#define MDDINACCESSIBLE 20
+#define OIDINVALID 21
+#define MDDOIDANDCOLL 22
+#define ARGUMENTSMISSING 23
+#define ARGUMENTSINCOMPLETE 24
+#define EXCEPTIONEXECUTEQUERY 25
+#define NOQUERY 26
+#define CONVERSIONNOTSUPPORTED 27
+#define CONVERSIONEXCEPTION 28
+#define UNKNOWNTILINGTYPE 29
+#define TILINGPARAMETERSMISSING 30
+#define TILINGPATAMETERSINCORRECT 31
+#define CONVERSIONTYPENOTABASETYPE 32
+#define CONVERSIONRETURNEDWRONGTYPE 33
+#define POLYGONCREATIONFAILED 34
+#define OVERLAYDOMAINSDONOTMATCH 35
+#define OVERLAYTYPESIZESDONOTMATCH 36
+#define POLYGONDOMAINTOOLARGE 37
+#define NOCOLLNAMEDEFINED 38
+#define NOMDDTYPEDEFINED 39
+#define MDDTYPEOFGMARRAYNOTINITIALISED 40
+#define SCALEDOMAINISNOTCORRECT 41
+#define SCALELEVELSINCORRECT 42
+#define GMARRAYSARENOTEQUAL 43
+#define UNKNOWNSCALEFUNCTION 44
+#define UNABLETOCLAIMRESOURCEFORFILE 45
+#define ERRORPARSINGCOMMANDLINE 46
+#define TILINGTYPENOTALLOWED 47
+#define LAYERSNOTCORRECT 48
+#define TOOMANYLAYERS 49
+#define OVERLAYDOMAINDOESNOTMATCH 50
+#define TILEDUPDATEANDFILE 51
+#define NOCOMPAREDESTINATION 52
+#define CONVERSIONTYPEMISSING 53
+#endif
diff --git a/rasodmg/test/system_compare.cc b/rasodmg/test/system_compare.cc
new file mode 100644
index 0000000..1dbc507
--- /dev/null
+++ b/rasodmg/test/system_compare.cc
@@ -0,0 +1,273 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: system_compare.cc
+ *
+ * MODULE: rasodmg/test
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg/test,SystemCompare: $Id: system_compare.cc,v 1.3 2002/07/16 07:42:36 hoefner Exp $";
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include "system_compare.hh"
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/primitivetype.hh"
+#include "raslib/marraytype.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/stattiling.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/oqlquery.hh"
+#include "clientcomm/clientcomm.hh"
+
+int main(int argc, const char** argv)
+ {
+ SystemBasic::usageHeader = "system_compare version 0.9\n\t\tProgram for checking data in RasDaMan\n";
+ SystemBasic::usageFooter = "Required information:\n\t\tMDD type\n\t\tCollection name\n\t\tMDD domain\n\t\tScale levels or file name\n";
+ int retval = 0;
+ try {
+ retval = SystemCompare::doStuff(argc, argv);
+ }
+ catch (r_Error& e)
+ {
+ cout << "Caught Exception at top level: " << e.get_errorno() << " " << e.what() << endl;
+ }
+ }
+
+int
+SystemCompare::doStuff(int argc, const char** argv)
+ {
+ installSignalHandlers();
+ int retval = 0;
+ retval = parseParams(argc, (char**)argv);
+ if (retval == 0)
+ {
+ if (mddTypeName)
+ {
+ if (mddDomainDef)
+ {
+ if (collName)
+ {
+ if (fileName)
+ {//compare given file with database
+ retval = doCompare();
+ }
+ else {
+ if (scaleLevels != NULL)
+ {//compare scalelevels
+ retval = doCompare();
+ }
+ else {
+ retval = NOCOMPAREDESTINATION;
+ }
+ }
+ }
+ else {
+ retval = NOCOLLNAMEDEFINED;
+ }
+ }
+ else {
+ retval = MDDDOMAINNOTSPECIFIED;
+ }
+ }
+ else {
+ retval = NOMDDTYPEDEFINED;
+ }
+ }
+ explainRetval(retval);
+ return retval;
+ }
+
+//SystemUpdate::doUpdate(const char* queryString, const char* queryStringS, const char* mddTypeName, const r_Marray_Type mddType, const r_Minterval& mddDomain, const char* inputFormatParams, )
+int
+SystemCompare::doCompare()
+ {
+ int retval = 0;
+ char queryBufferS[QUERYBUFFERLENGTH];
+ memset(queryBufferS, 0, QUERYBUFFERLENGTH * sizeof(char));
+ if (mddOIdDef)
+ {
+ std::ostrstream stream(queryBufferS, QUERYBUFFERLENGTH);
+ stream << "SELECT A" << mddDomain << " FROM " << collName << " AS A WHERE oid(A) = " << mddOId;
+ }
+ else {
+ std::ostrstream stream(queryBufferS, QUERYBUFFERLENGTH);
+ stream << "SELECT A" << mddDomain << " FROM " << collName << " AS A";
+ }
+ r_Storage_Layout* stl = new r_Storage_Layout(theTiling->clone());
+ char* typeStructure = NULL;
+ r_Ref<r_GMarray> selectedMDD;
+ r_Set< r_Ref_Any > result;
+ r_Marray_Type* mddType = NULL;
+ try {
+ openTransaction(false);
+ typeStructure = db.communication->getTypeStructure(mddTypeName, ClientComm::r_MDDType_Type);
+ ta.abort();
+ db.close();
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error during type retrieval from database: " << err.get_errorno() << " " << err.what() << endl;
+ typeStructure = new char[strlen(mddTypeName) + 1];
+ strcpy(typeStructure, mddTypeName);
+ }
+ try {
+ r_Type* tempType = r_Type::get_any_type(typeStructure);
+ if (tempType->isMarrayType())
+ {
+ mddType = (r_Marray_Type*)tempType;
+ }
+ else {
+ RMInit::logOut << "The type (" << typeStructure << ") is not an marray type." << endl;
+ retval = MDDTYPEINVALID;
+ }
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error during type retrieval from type structure (" << typeStructure << "): " << err.get_errorno() << " " << err.what() << endl;
+ retval = MDDTYPEINVALID;
+ }
+ if (retval == 0)
+ {
+ size_t baseTypeLength = mddType->base_type().size();
+ if (fileName)
+ {//check if file corresponds to collection
+ r_Storage_Layout* stl = new r_Storage_Layout(theTiling->clone());
+ r_Ref<r_GMarray> tempMDD = new (mddTypeName)r_GMarray(mddDomain, baseTypeLength, stl);
+ tempMDD->set_type_schema(mddType);
+ FILE* filePointer = checkFile(fileName, retval);
+ if (retval != 0)
+ {
+ tempMDD.destroy();
+ return retval;
+ }
+ retval = initGMarray(tempMDD, filePointer, inputFormat, mddDomain, inputFormatParams);
+ fclose(filePointer);
+ if (retval == 0)
+ {
+ try {
+ r_OQL_Query query(queryBufferS);
+ openTransaction(false);
+ r_oql_execute(query, result);
+ r_Iterator< r_Ref_Any > iter = result.create_iterator();
+ selectedMDD = r_Ref<r_GMarray>(*iter);
+ if (polygonDefined)
+ {
+ polygon.setMArray(*selectedMDD);
+ if (foreGroundDef)
+ polygon.fillMArrayInside(foreGround);
+ if (backGroundDef)
+ polygon.fillMArrayOutside(backGround);
+ }
+ if (retval == 0)
+ {
+ retval = compareGMarrays(selectedMDD, tempMDD);
+ if (((retval != 0) || (force)) && (outputFileName != NULL))
+ {
+ char* tempName = new char[strlen(outputFileName) + strlen("image.png") + 1];
+ strcpy(tempName, outputFileName);
+ strcat(tempName, ".db.png");
+ saveData(tempName, selectedMDD->get_array(), selectedMDD->get_array_size(), selectedMDD->spatial_domain());
+ strcpy(tempName, outputFileName);
+ strcat(tempName, ".image.png");
+ saveData(tempName, tempMDD->get_array(), tempMDD->get_array_size(), tempMDD->spatial_domain());
+ delete [] tempName;
+ tempName = NULL;
+ }
+ }
+ ta.abort();
+ db.close();
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error during administrative action: " << err.get_errorno() << " " << err.what() << endl;
+ retval = EXCEPTIONADMIN;
+ ta.abort();
+ }
+ if (db.get_status() != r_Database::not_open)
+ db.close();
+ }
+ }
+ if (scaleLevels != NULL)
+ {
+ try {
+ //initialise selectedMDD
+ r_OQL_Query query(queryBufferS);
+ openTransaction(false);
+ r_oql_execute(query, result);
+ r_Iterator< r_Ref_Any > iter = result.create_iterator();
+ selectedMDD = r_Ref<r_GMarray>(*iter);
+ if (polygonDefined)
+ {
+ polygon.setMArray(*selectedMDD);
+ if (foreGroundDef)
+ polygon.fillMArrayInside(foreGround);
+ if (backGroundDef)
+ polygon.fillMArrayOutside(backGround);
+ }
+ if (retval == 0)
+ {//read the scaled mdds from db and scale down the selected MDD and compare
+ std::list<std::pair<double, char*> >::iterator iter = scaleLevels->begin();
+ std::list<std::pair<double, char*> >::iterator end = scaleLevels->end();
+ r_Minterval scaledDomain;
+ r_Minterval clipDomain;
+ unsigned int length = 0;
+ r_Dimension maxDim = mddDomain.dimension();
+ r_Point origin(maxDim);
+ double factor = 0;
+ for (r_Dimension i = 0; i < maxDim; i++)
+ origin[i] = 0;
+ while ((iter != end) && (retval == 0))
+ {
+ factor = iter->first;
+ retval = scaleDomain(overlayDomain, origin, factor, scaledDomain, clipDomain, length);
+ RMInit::logOut << "scaled: " << iter->second << " scaled domain " << scaledDomain << " clip domain " << clipDomain << " result=" << retval << endl;
+ const r_Type* type = selectedMDD->get_base_type_schema();
+ size_t tlen = selectedMDD->get_type_length();
+ retval = compareScaledMDD(selectedMDD, clipDomain, scaledDomain, length, iter->second);
+ iter++;
+ }
+ }
+ ta.abort();
+ db.close();
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error during administrative action: " << err.get_errorno() << " " << err.what() << endl;
+ retval = EXCEPTIONADMIN;
+ ta.abort();
+ }
+ if (db.get_status() != r_Database::not_open)
+ db.close();
+ }
+ }
+ return retval;
+ }
+
diff --git a/rasodmg/test/system_compare.hh b/rasodmg/test/system_compare.hh
new file mode 100644
index 0000000..f2d0136
--- /dev/null
+++ b/rasodmg/test/system_compare.hh
@@ -0,0 +1,40 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+#ifndef _SYSTEMCOMPARE_HH_
+#define _SYSTEMCOMPARE_HH_
+
+#include "system_basic.hh"
+
+class SystemCompare : public SystemBasic
+ {
+ public:
+ static int doStuff(int argc, const char** argv);
+
+ static void printUsage();
+
+ static int doCompare();
+
+ };
+
+#endif
diff --git a/rasodmg/test/system_insert.cc b/rasodmg/test/system_insert.cc
new file mode 100644
index 0000000..f290778
--- /dev/null
+++ b/rasodmg/test/system_insert.cc
@@ -0,0 +1,384 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: system_insert.cc
+ *
+ * MODULE: rasodmg/test
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg/test,SystemInsert: $Id: system_insert.cc,v 1.10 2002/03/13 13:48:17 coman Exp $";
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include "system_insert.hh"
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/primitivetype.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/stattiling.hh"
+#include "rasodmg/storagelayout.hh"
+
+int main(int argc, const char** argv)
+ {
+ return SystemInsert::doStuff(argc, argv);
+ }
+
+int
+SystemInsert::doStuff(int argc, const char** argv)
+ {
+ RMInit::logOut.rdbuf(cout.rdbuf());
+ RMInit::dbgOut.rdbuf(cout.rdbuf());
+ RMDebug::level = 10;
+ r_Base_Type* conversionType = 0;
+ int retval = 0;
+
+ if ((argc == 1) || checkArguments(argc, argv, "-h", optionValueIndex) || checkArguments(argc, argv, "--help", optionValueIndex))
+ {
+ printUsage();
+ }
+ else {
+ retval = readArgs(argc, argv);
+ /*
+ what can we do:
+ create mdd:
+ requires
+ mddType
+ optional
+ collName ok
+ collOId ok
+ create coll:
+ requires
+ settype ok
+ optional
+ collName ok
+ insert existing mdd into coll:
+ requires
+ mddOId
+ collName/collOId
+ */
+ if (retval == 0)
+ {
+ if (mddTypeDef)
+ {//create mdd
+ if (mddOIdDef)
+ {//cannot create mdd with a user specified oid
+ retval = CREATEMDDWITHOID;
+ }
+ else {
+ if (fileNameDef)
+ {
+ if (mddDomainDef)
+ {
+ if (collNameDef)
+ {//create mdd, lookup coll by name, insert mdd into coll
+ //open stuff
+ try {
+ openTransaction();
+ //get collection
+ try {
+ collection = db.lookup_object(collName);
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error (" << obj.get_errorno() << ") accessing collection " << collName << ": " << obj.what() << endl;
+ retval = COLLECTIONINACCESSIBLE;
+ }
+ //create mddObject
+ if (retval == 0)
+ {
+ r_Storage_Layout* stl = new r_Storage_Layout(theTiling->clone());
+ //stl->set_storage_format(storageFormat, storageFormatParams);
+ mddObject = new (&db, mddTypeName) r_GMarray(mddDomain, 0, stl);
+ retval = initGMarray(mddObject, filePointer, inputFormat, mddDomain, inputFormatParams);
+ if (retval == 0)
+ {
+ collection->insert_element(mddObject);
+ ta.commit();
+ }
+ else
+ ta.abort();
+ }
+ else {
+ ta.abort();
+ }
+ db.close();
+ }
+ catch (r_Error& obj)
+ {
+ cout << "Exception (" << obj.get_errorno() << ") at administrative action: " << obj.what() << endl;
+ retval = EXCEPTIONADMIN;
+ ta.abort();
+ db.close();
+ }
+ }
+ else {//no collname
+ if (collOIdDef)
+ {//create mdd, lookup coll by oid, insert mdd into coll
+ try {
+ openTransaction();
+ //get collection
+ try {
+ collection = db.lookup_object(collOId);
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error (" << obj.get_errorno() << ") accessing collection " << collOId << ": " << obj.what() << endl;
+ retval = COLLECTIONINACCESSIBLE;
+ }
+ //create mddObject
+ if (retval == 0)
+ {
+ r_Storage_Layout* stl = new r_Storage_Layout(theTiling->clone());
+ //stl->set_storage_format(dataFormat, dataFormatParams);
+ mddObject = new (&db, mddTypeName) r_GMarray(mddDomain, 0, stl);
+ retval = initGMarray(mddObject, filePointer, inputFormat, mddDomain, inputFormatParams);
+ if (retval == 0)
+ {
+ collection->insert_element(mddObject);
+ ta.commit();
+ }
+ else
+ ta.abort();
+ }
+ else {
+ ta.abort();
+ }
+ db.close();
+ }
+ catch (r_Error& obj)
+ {
+ cout << "Exception (" << obj.get_errorno() << ") at administrative action: " << obj.what() << endl;
+ retval = EXCEPTIONADMIN;
+ ta.abort();
+ db.close();
+ }
+ }
+ else {//no collname, no collOId, create mdd
+ try {
+ openTransaction();
+ r_Storage_Layout* stl = new r_Storage_Layout(theTiling->clone());
+ //stl->set_storage_format(storageFormat, storageFormatParams);
+ mddObject = new (&db, mddTypeName) r_GMarray(mddDomain, 0, stl);
+ retval = initGMarray(mddObject, filePointer, inputFormat, mddDomain, inputFormatParams);
+ if (retval == 0)
+ {
+ collection->insert_element(mddObject);
+ ta.commit();
+ }
+ else
+ ta.abort();
+ db.close();
+ }
+ catch (r_Error& obj)
+ {
+ cout << "Exception (" << obj.get_errorno() << ") at administrative action: " << obj.what() << endl;
+ retval = EXCEPTIONADMIN;
+ ta.abort();
+ db.close();
+ }
+ }
+ }
+ }
+ else {
+ retval = MDDDOMAINNOTSPECIFIED;
+ }
+ }
+ else {
+ retval = FILENAMENOTSPECIFIED;
+ }
+ }
+ }
+ else {//create coll or insert existing mdd into existing coll
+ if (mddOIdDef)
+ {//insert existing mdd into existing coll
+ if (collOIdDef)
+ {//lookup mdd by oid, lookup coll by oid, insert mdd into coll
+ try {
+ openTransaction();
+ //get collection
+ try {
+ collection = db.lookup_object(collOId);
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error (" << obj.get_errorno() << ") accessing collection " << collOId << ": " << obj.what() << endl;
+ retval = COLLECTIONINACCESSIBLE;
+ }
+ if (retval == 0)
+ {
+ //lookup mddObject
+ try {
+ mddObject = db.lookup_object(mddOId);
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error (" << obj.get_errorno() << ") accessing mdd " << mddOId << ": " << obj.what() << endl;
+ retval = MDDINACCESSIBLE;
+ }
+ if (retval == 0)
+ {
+ collection->insert_element(mddObject);
+ ta.commit();
+ }
+ else {
+ ta.abort();
+ }
+ }
+ else {
+ ta.abort();
+ }
+ db.close();
+ }
+ catch (r_Error& obj)
+ {
+ cout << "Exception (" << obj.get_errorno() << ") at administrative action: " << obj.what() << endl;
+ retval = EXCEPTIONADMIN;
+ ta.abort();
+ db.close();
+ }
+ }
+ else {
+ if (collNameDef)
+ {//lookup mdd by oid, lookup coll by name
+ try {
+ openTransaction();
+ //get collection
+ try {
+ collection = db.lookup_object(collName);
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error (" << obj.get_errorno() << ") accessing collection " << collName << ": " << obj.what() << endl;
+ retval = COLLECTIONINACCESSIBLE;
+ }
+ if (retval == 0)
+ {
+ //lookup mddObject
+ try {
+ mddObject = db.lookup_object(mddOId);
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error (" << obj.get_errorno() << ") accessing mdd " << mddOId << ": " << obj.what() << endl;
+ retval = MDDINACCESSIBLE;
+ }
+ if (retval == 0)
+ {
+ collection->insert_element(mddObject);
+ ta.commit();
+ }
+ else {
+ ta.abort();
+ }
+ }
+ else {
+ ta.abort();
+ }
+ db.close();
+ }
+ catch (r_Error& obj)
+ {
+ cout << "Exception (" << obj.get_errorno() << ") at administrative action: " << obj.what() << endl;
+ retval = EXCEPTIONADMIN;
+ ta.abort();
+ db.close();
+ }
+ }
+ else {//no coll name, no coll oid, error
+ retval = NOCOLLNAMENOCOLLOID;
+ }
+ }
+ }
+ else {//do not create mdd, do not insert mdd into coll
+ if (setTypeDef)
+ {//create coll
+ //open stuff
+ try {
+ openTransaction();
+ try {
+ collection = new (&db, setTypeName) r_Set< r_Ref< r_GMarray > >;
+ if (collNameDef)
+ {//object.cc insert in db will throw r_error without name
+ db.set_object_name(*collection, collName);
+ }
+ ta.commit();
+ }
+ catch (r_Error& obj)
+ {
+ cout << "Exception (" << obj.get_errorno() << ") at creating collection: " << obj.what() << endl;
+ retval = EXCEPTIONCREATECOLL;
+ ta.abort();
+ }
+ //create mddObject
+ db.close();
+ }
+ catch (r_Error& obj)
+ {
+ cout << "Exception (" << obj.get_errorno() << ") at administrative action: " << obj.what() << endl;
+ retval = EXCEPTIONADMIN;
+ ta.abort();
+ db.close();
+ }
+ }
+ else {
+ retval = NOCOLLTYPE;
+ }
+ }
+ }
+ }
+ else {
+ //errors occured in check arguments
+ }
+ }
+ explainRetval(retval);
+ return retval;
+ }
+
+void
+SystemInsert::printUsage()
+ {
+ cout << "Insert program for extended systemtest" << endl << endl;
+ SystemBasic::printOptions();
+ cout << "Actions: Create and insert MDD object" << endl;
+ cout << " required information: MDD type" << endl;
+ cout << " Collection name or oid" << endl;
+ cout << " MDD domain" << endl;
+ cout << " File name with data" << endl;
+ cout << " Create MDD object (is not supported by rasdaman)" << endl;
+ cout << " required information: MDD type" << endl;
+ cout << " MDD domain" << endl;
+ cout << " File name with data" << endl;
+ cout << " Create Collection object" << endl;
+ cout << " required information: Collection type" << endl;
+ cout << " optional information: Collection name" << endl;
+ cout << " Insert existing MDD in existing Collection (is not supported by rasdaman)" << endl;
+ cout << " required information: MDD oid" << endl;
+ cout << " Collection name or oid" << endl;
+ cout << endl;
+ }
diff --git a/rasodmg/test/system_insert.hh b/rasodmg/test/system_insert.hh
new file mode 100644
index 0000000..97b5a17
--- /dev/null
+++ b/rasodmg/test/system_insert.hh
@@ -0,0 +1,43 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+#ifndef _SYSTEMINSERT_HH_
+#define _SYSTEMINSERT_HH_
+
+#include "system_basic.hh"
+
+class SystemInsert : public SystemBasic
+ {
+ public:
+ static int doStuff(int argc, const char** argv);
+
+ static void printUsage();
+
+ static void createMDD();
+
+ static void createColl();
+
+ static void insertMDDIntoColl();
+ };
+
+#endif
diff --git a/rasodmg/test/system_query.cc b/rasodmg/test/system_query.cc
new file mode 100644
index 0000000..d04c658
--- /dev/null
+++ b/rasodmg/test/system_query.cc
@@ -0,0 +1,400 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: system_query.cc
+ *
+ * MODULE: rasodmg/test
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg/test,SystemQuery: $Id: system_query.cc,v 1.11 2002/07/30 07:16:23 hoefner Exp $";
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <unistd.h>
+#include "system_query.hh"
+#include "raslib/complex.hh"
+#include "raslib/structure.hh"
+#include "raslib/primitive.hh"
+#include "raslib/primitivetype.hh"
+#include "rasodmg/oqlquery.hh"
+#include "rasodmg/storagelayout.hh"
+
+int
+main(int argc, char** argv)
+ {
+ SystemBasic::usageHeader = "system_compare version 0.9\n\t\tProgram for executing queries against RasDaMan\n";
+ SystemBasic::usageFooter = "Required information:\n\t\tQuery file\n";
+ int retval = 0;
+ try {
+ retval = SystemQuery::doStuff(argc, argv);
+ }
+ catch (r_Error& e)
+ {
+ cout << "Caught Exception at top level: " << e.get_errorno() << " " << e.what() << endl;
+ }
+ }
+
+int
+SystemQuery::doStuff(int argc, char** argv)
+ {
+ installSignalHandlers();
+ int retval = 0;
+ retval = parseParams(argc, argv);
+ if (retval == 0)
+ {
+ if (fileName)
+ {
+ r_Storage_Layout* stl = 0;
+ db.set_servername(serverName);
+ db.set_useridentification(userName, passwd);
+ try {
+ db.open(baseName);
+ FILE* filePointer = checkFile(fileName, retval);
+ if (retval != 0)
+ return retval;
+ size_t dataSize = 0;
+ char* data = getData(filePointer, dataSize, retval);
+ if(retval != 0)
+ return retval;
+ char* myQuery = new char[dataSize + 1];
+ memcpy(myQuery, data, dataSize);
+ delete data;
+ data = 0;
+ myQuery[dataSize - 1] = '\0';
+ RMInit::logOut << "Query " << myQuery << endl;
+ r_OQL_Query q1(myQuery);
+ RMInit::logOut << "OQL " << q1.get_query() << endl;
+ if (q1.is_update_query())
+ {
+ cout << "Starting Update Transaction" << endl;
+ ta.begin();
+ db.set_storage_format(storageFormat, storageFormatParams);
+ db.set_transfer_format(transferFormat, transferFormatParams);
+ if (retval == 0)
+ {
+ try {
+ RMDBGIF(20, RMDebug::module_tools, "WAITBEFOREQL", \
+ RMInit::dbgOut << "Waiting 100 sec before query\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ r_oql_execute(q1);
+ RMDBGIF(20, RMDebug::module_tools, "WAITAFTERQL", \
+ RMInit::dbgOut << "Waiting 100 sec before query\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ }
+ catch (r_Error& errorObj)
+ {
+ cout << "FAILED" << endl << errorObj.what() << endl;
+ ta.abort();
+ retval = EXCEPTIONEXECUTEQUERY;
+ }
+ }
+ if (retval == 0)
+ ta.commit();
+ }
+ else {
+ cout << "Starting Read Only Transaction ... "; cout.flush();
+ ta.begin(r_Transaction::read_only);
+ db.set_storage_format(storageFormat, storageFormatParams);
+ db.set_transfer_format(transferFormat, transferFormatParams);
+ cout << "OK" << endl;
+ r_Set< r_Ref_Any > result_set;
+ cout << "Executing query ... "; cout.flush();
+ try {
+ RMDBGIF(20, RMDebug::module_tools, "WAITBEFOREQL", \
+ RMInit::dbgOut << "Waiting 100 sec before query\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ r_oql_execute(q1, result_set);
+ RMDBGIF(20, RMDebug::module_tools, "WAITAFTERQL", \
+ RMInit::dbgOut << "Waiting 100 sec before query\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ }
+ catch(r_Error& errorObj)
+ {
+ cout << "FAILED" << endl << errorObj.what() << endl;
+ ta.abort();
+ retval = EXCEPTIONEXECUTEQUERY;
+ }
+ if (retval == 0)
+ {
+ cout << "OK" << endl;
+ cout << "Collection" << endl;
+ cout << " Oid...................: " << result_set.get_oid() << endl;
+ cout << " Type Structure........: " << (result_set.get_type_structure() ? result_set.get_type_structure() : "<nn>") << endl;
+ cout << " Type Schema...........: " << flush;
+ if (result_set.get_type_schema())
+ result_set.get_type_schema()->print_status(cout);
+ else
+ cout << "<nn>" << flush;
+ cout << endl;
+ cout << " Number of entries.....: " << result_set.cardinality() << endl;
+ cout << " Element Type Schema...: " << flush;
+ if (result_set.get_element_type_schema())
+ result_set.get_element_type_schema()->print_status(cout);
+ else
+ cout << "<nn>" << flush;
+ cout << endl;
+ if (testBed)
+ {
+ cout << "-- Testbed line: result_type=" << result_set.get_type_structure() << endl;
+ cout << "-- Testbed line: result_elements=" << result_set.cardinality() << endl;
+ cout << endl;
+ }
+
+ r_Iterator< r_Ref_Any > iter = result_set.create_iterator();
+ cout << endl;
+ if (testBed)
+ cout << "-- Testbed start block:" << endl;
+ for (int i=1 ; iter.not_done(); iter++, i++)
+ {
+ switch (result_set.get_element_type_schema()->type_id())
+ {
+ case r_Type::MARRAYTYPE:
+ {
+ const char *defExt=NULL;
+ r_Data_Format mafmt = r_Ref<r_GMarray>(*iter)->get_current_format();
+ r_Data_Format tmpfmt = r_Data_Format_NUMBER;
+ if(outputFormat)
+ tmpfmt = outputFormat;
+ else
+ tmpfmt = mafmt;
+ // special treatment only for DEFs
+ switch (tmpfmt)
+ {
+ case r_TOR:
+ defExt = "tor"; break;
+ case r_DEM:
+ defExt = "dem"; break;
+ case r_VFF:
+ defExt = "vff"; break;
+ case r_TIFF:
+ defExt = "tif"; break;
+ case r_JPEG:
+ defExt = "jpg"; break;
+ case r_HDF:
+ defExt = "hdf"; break;
+ case r_PNG:
+ defExt = "png"; break;
+ case r_BMP:
+ defExt = "bmp"; break;
+ default:
+ defExt = NULL;
+ }
+ if (outputFormat && (defExt == NULL))
+ defExt = "raw";
+ if (defExt == NULL)
+ {
+ if (printText)
+ {
+ int numCells = r_Ref<r_GMarray>(*iter)->get_array_size();
+ const char* theStuff = r_Ref<r_GMarray>(*iter)->get_array();
+ for (int cnt = 0; cnt < numCells; cnt++)
+ cout << theStuff[cnt];
+ }
+ else {
+ cout << "Image " << i << endl;
+ r_Ref<r_GMarray>(*iter)->print_status(cout, 0);
+ }
+ cout << endl;
+ }
+ else{
+
+ if(outputFormat && mafmt!=outputFormat)
+ {
+ r_Base_Type* conversionType=NULL;
+ r_Minterval* mddDomain=NULL;
+ if(mafmt!=r_Array)
+ {
+ data=r_Ref<r_GMarray>(*iter)->get_array();
+ dataSize=r_Ref<r_GMarray>(*iter)->get_array_size();
+ mddDomain=(r_Minterval*)&(r_Ref<r_GMarray>(*iter)->spatial_domain());
+ conversionType=(r_Base_Type*)r_Ref<r_GMarray>(*iter)->get_base_type_schema();
+ //convert this from currentformat(DEF) to r_Array
+ if (convertFrom(mafmt, data, dataSize, *mddDomain, conversionType, NULL) == 0)
+ {
+ r_Ref<r_GMarray>(*iter)->set_array_size(dataSize);
+ r_Ref<r_GMarray>(*iter)->set_type_length(conversionType->size());
+ r_Ref<r_GMarray>(*iter)->set_array(data);
+ r_Ref<r_GMarray>(*iter)->set_current_format(r_Array);
+ r_Ref<r_GMarray>(*iter)->set_spatial_domain(*mddDomain);
+ data = 0;
+ }
+ else
+ {
+ cout << "Error while converting to " << r_Array << " from " << mafmt << endl;
+ retval=CONVERSIONEXCEPTION;
+ }
+ }
+ //convert this from r_Array to outputFormat
+ data=r_Ref<r_GMarray>(*iter)->get_array();
+ dataSize=r_Ref<r_GMarray>(*iter)->get_array_size();
+ mddDomain=(r_Minterval*)&(r_Ref<r_GMarray>(*iter)->spatial_domain());
+ conversionType=(r_Base_Type*)r_Ref<r_GMarray>(*iter)->get_base_type_schema();
+ if (convertTo(outputFormat, data, dataSize, *mddDomain, conversionType, outputFormatParams) == 0)
+ {
+ r_Ref<r_GMarray>(*iter)->set_array_size(dataSize);
+ r_Ref<r_GMarray>(*iter)->set_type_length(conversionType->size());
+ r_Ref<r_GMarray>(*iter)->set_array(data);
+ r_Ref<r_GMarray>(*iter)->set_current_format(outputFormat);
+ r_Ref<r_GMarray>(*iter)->set_spatial_domain(*mddDomain);
+ data = 0;
+ }
+ else
+ {
+ cout << "Error while converting to " << outputFormat << " from " << r_Array << endl;
+ retval=CONVERSIONEXCEPTION;
+ }
+ }
+
+ char defFileName[256];
+ sprintf(defFileName, "%s%d.%s", outputFileName, i, defExt);
+ cout << "Marray " << i << " will write " << r_Ref<r_GMarray>(*iter)->get_array_size() << " bytes to " << defFileName << endl;
+
+ FILE *tfile = fopen(defFileName, "wb");
+ fwrite((void*)r_Ref<r_GMarray>(*iter)->get_array(), 1, r_Ref<r_GMarray>(*iter)->get_array_size(), tfile);
+ fclose(tfile);
+ }
+ }
+ break;
+
+ case r_Type::POINTTYPE:
+ cout << "Element " << i << ": " << *(r_Ref<r_Point>(*iter)) << endl;
+ break;
+
+ case r_Type::SINTERVALTYPE:
+ cout << "Element " << i << ": " << *(r_Ref<r_Sinterval>(*iter)) << endl;
+ break;
+
+ case r_Type::MINTERVALTYPE:
+ cout << "Element " << i << ": " << *(r_Ref<r_Minterval>(*iter)) << endl;
+ break;
+
+ case r_Type::OIDTYPE:
+ cout << "Element " << i << ": " << *(r_Ref<r_OId>(*iter)) << endl;
+ break;
+
+ default:
+ cout << "Element " << i << ": " << flush;
+ printScalar( *(r_Ref<r_Scalar>(*iter)) );
+ cout << endl;
+ }
+ }
+ }
+ if (testBed)
+ cout << "-- Testbed end block:" << endl;
+ if (retval == 0)
+ ta.commit();
+ else
+ ta.abort();
+ }
+ delete myQuery;
+ myQuery = 0;
+ db.close();
+ }
+ catch (r_Error& obj)
+ {
+ cout << "Exception (" << obj.get_errorno() << ") : " << obj.what() << endl;
+ ta.abort();
+ db.close();
+ retval = EXCEPTIONADMIN;
+ }
+ }
+ else {
+ retval = FILENAMENOTSPECIFIED;
+ }
+ }
+ explainRetval(retval);
+ return retval;
+ }
+
+void SystemQuery::printScalar( const r_Scalar& scalar )
+{
+ switch( scalar.get_type()->type_id() )
+ {
+ case r_Type::BOOL:
+ cout << ( ((r_Primitive*)&scalar)->get_boolean() ? "T" : "F" ) << flush;
+ break;
+
+ case r_Type::CHAR:
+ cout << (int)((r_Primitive*)&scalar)->get_char() << flush;
+ break;
+
+ case r_Type::OCTET:
+ cout << (int)((r_Primitive*)&scalar)->get_octet() << flush;
+ break;
+
+ case r_Type::SHORT:
+ cout << ((r_Primitive*)&scalar)->get_short() << flush;
+ break;
+
+ case r_Type::USHORT:
+ cout << ((r_Primitive*)&scalar)->get_ushort() << flush;
+ break;
+
+ case r_Type::LONG:
+ cout << ((r_Primitive*)&scalar)->get_long() << flush;
+ break;
+
+ case r_Type::ULONG:
+ cout << ((r_Primitive*)&scalar)->get_ulong() << flush;
+ break;
+
+ case r_Type::FLOAT:
+ cout << ((r_Primitive*)&scalar)->get_float() << flush;
+ break;
+
+ case r_Type::DOUBLE:
+ cout << ((r_Primitive*)&scalar)->get_double() << flush;
+ break;
+
+ case r_Type::COMPLEXTYPE1:
+ case r_Type::COMPLEXTYPE2:
+ cout << "(" << ((r_Complex*)&scalar)->get_re() << ", " << ((r_Complex*)&scalar)->get_im() << ")" << flush;
+ break;
+
+ case r_Type::STRUCTURETYPE:
+ {
+ r_Structure* structValue = (r_Structure*)&scalar;
+
+ cout << "{ " << flush;
+
+ for( int i=0; i<structValue->count_elements(); i++ )
+ {
+ printScalar( (*structValue)[i] );
+
+ if( i < structValue->count_elements()-1 ) cout << ", " << flush;
+ }
+ cout << " }" << endl;
+ }
+ break;
+ }
+}
diff --git a/rasodmg/test/system_query.hh b/rasodmg/test/system_query.hh
new file mode 100644
index 0000000..b5cafdb
--- /dev/null
+++ b/rasodmg/test/system_query.hh
@@ -0,0 +1,37 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+#ifndef _SYSTEMQUERY_HH_
+#define _SYSTEMQUERY_HH_
+
+#include "system_basic.hh"
+
+class SystemQuery : public SystemBasic
+ {
+ public:
+ static int doStuff(int argc, char** argv);
+
+ static void printScalar(const r_Scalar& scalar);
+ };
+
+#endif
diff --git a/rasodmg/test/system_update.cc b/rasodmg/test/system_update.cc
new file mode 100644
index 0000000..daf6a06
--- /dev/null
+++ b/rasodmg/test/system_update.cc
@@ -0,0 +1,399 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: system_update.cc
+ *
+ * MODULE: rasodmg/test
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg/test,SystemUpdate: $Id: system_update.cc,v 1.21 2003/12/27 23:02:58 rasdev Exp $";
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <unistd.h>
+#include <math.h>
+
+#include "system_update.hh"
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/primitivetype.hh"
+#include "raslib/marraytype.hh"
+#include "raslib/mitera.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/stattiling.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/oqlquery.hh"
+#include "clientcomm/clientcomm.hh"
+
+
+
+int main(int argc, char** argv)
+ {
+ SystemBasic::usageHeader = "system_update version 0.9.4\n\t\tProgram for writing data into RasDaMan\n";
+ SystemBasic::usageFooter = "Required information:\n\t\t MDD type\n\t\tCollection name\n\t\tMDD domain\n\t\tFile name with data\n";
+ int retval = 0;
+ try {
+ retval = SystemUpdate::doStuff(argc, argv);
+ }
+ catch (const r_Error& e)
+ {
+ cout << "Caught Exception at top level: " << e.get_errorno() << " " << e.what() << endl;
+ retval = -1;
+ }
+ catch (const std::exception& e2)
+ {
+ cout << "Caught Exception at top level: " << e2.what() << endl;
+ retval = -1;
+ }
+ catch (...)
+ {
+ cout << "Caught Unknown Exception at top level!" << endl;
+ retval = -1;
+ }
+ return retval;
+ }
+
+int
+SystemUpdate::doStuff(int argc, char** argv)
+ {
+#ifndef RMANDEBUG
+ installSignalHandlers();
+#endif
+ int retval = 0;
+ retval = parseParams(argc, argv);
+ if (retval == 0)
+ {
+ if (mddTypeName)
+ {
+ if (mddDomainDef)
+ {
+ if (fileName && (conversionTypeName == NULL))
+ {
+ retval = CONVERSIONTYPEMISSING;
+ }
+ else {
+ if (fileName || (!fileName && transparent))
+ {
+ if (collName)
+ {
+ r_MiterArea* iter = NULL;
+ r_Minterval tempDom;
+ r_Minterval tileDom;
+ if (tiledUpdate)
+ {
+ tempDom = overlayDomain;
+ //taken from tiling.cc r_Size_Tiling
+ r_Dimension dim = tempDom.dimension();
+ r_Range edgeLength = (r_Range)std::max((r_Range)floor(pow(updateBufferSize, 1/(double)dim)), 1);
+ if (align)
+ {
+ edgeLength = edgeLength - edgeLength%align;
+ if (edgeLength < align)
+ edgeLength = align;
+ }
+ tileDom = r_Minterval(dim);
+ for (r_Dimension dimcnt = 0; dimcnt < dim; dimcnt++)
+ tileDom << r_Sinterval(0, edgeLength - 1);
+ iter = new r_MiterArea(&tileDom, &tempDom);
+ RMInit::logOut << "Tiling domain " << tileDom << " complete domain " << tempDom << endl;
+ //nextArea()
+ //isDone()
+ }
+ do {
+ std::ostringstream selstream;
+ std::ostringstream updstream;
+ if (tiledUpdate)
+ {
+ mddDomain = iter->nextArea();
+ overlayDomain = mddDomain;
+ tiledUpdate = !iter->isDone();
+ RMInit::logOut << "Doing now " << mddDomain << " " << overlayDomain << " done " << tiledUpdate << endl;
+ }
+ if (mddOIdDef)
+ {
+ updstream << "UPDATE " << collName << " AS a SET a" << overlayDomain << " ASSIGN $1 WHERE oid(a)=" << mddOId;
+ }
+ else {
+ updstream << "UPDATE " << collName << " AS a SET a" << overlayDomain << " ASSIGN $1";
+ }
+ if (transparent || !fileName)
+ {
+ if (overlayDomainDef)
+ {
+ if (overlayDomain.covers(mddDomain))
+ {
+ selstream << "SELECT A" << overlayDomain << " FROM " << collName << " AS A";
+ }
+ else {
+ RMInit::logOut << "Overlay domain " << overlayDomain << " does not cover MDD domain " << mddDomain << endl;
+ retval = OVERLAYDOMAINDOESNOTMATCH;
+ }
+ }
+ else {
+ selstream << "SELECT A" << mddDomain << " FROM " << collName << " AS A";
+ }
+ }
+ if (retval == 0)
+ {
+ retval = doUpdate(updstream.str().c_str(), selstream.str().c_str());
+ }
+ }
+ while (tiledUpdate && (retval == 0));
+ delete iter;
+ iter = NULL;
+ }
+ else {
+ retval = NOCOLLNAMEDEFINED;
+ }
+ }
+ else {
+ retval = FILENAMENOTSPECIFIED;
+ }
+ }
+ }
+ else {
+ retval = MDDDOMAINNOTSPECIFIED;
+ }
+ }
+ else {
+ retval = NOMDDTYPEDEFINED;
+ }
+ }
+ explainRetval(retval);
+ return retval;
+ }
+
+//SystemUpdate::doUpdate(const char* queryString, const char* queryStringS, const char* mddTypeName, const r_Marray_Type mddType, const r_Minterval& mddDomain, const char* inputFormatParams, )
+int
+SystemUpdate::doUpdate(const char* queryString, const char* queryStringS)
+ {
+ int retval = 0;
+ char* typeStructure = NULL;
+ r_Ref<r_GMarray> selectedMDD;
+ r_Set< r_Ref_Any > result;
+ r_Marray_Type* mddType = NULL;
+ try {
+ openTransaction(false);
+ typeStructure = db.getComm()->getTypeStructure(mddTypeName, ClientComm::r_MDDType_Type);
+ ta.abort();
+ db.close();
+ }
+ catch (r_Error& err)
+ {
+ if (err.get_kind() == r_Error::r_Error_DatabaseClassUndefined)
+ {
+ RMInit::logOut << "Type is not a well known type" << endl;
+ typeStructure = new char[strlen(mddTypeName) + 1];
+ strcpy(typeStructure, mddTypeName);
+ }
+ else {
+ RMInit::logOut << "Error during type retrieval from database: " << err.get_errorno() << " " << err.what() << endl;
+ throw;
+ }
+ }
+ try {
+ r_Type* tempType = r_Type::get_any_type(typeStructure);
+ if (tempType->isMarrayType())
+ {
+ mddType = (r_Marray_Type*)tempType;
+ tempType = NULL;
+ }
+ else {
+ RMInit::logOut << "The type (" << typeStructure << ") is not an marray type." << endl;
+ delete tempType;
+ tempType = NULL;
+ retval = MDDTYPEINVALID;
+ }
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error during type retrieval from type structure (" << typeStructure << "): " << err.get_errorno() << " " << err.what() << endl;
+ retval = MDDTYPEINVALID;
+ }
+ delete [] typeStructure;
+ typeStructure = NULL;
+ if (retval == 0)
+ {
+ size_t baseTypeLength = mddType->base_type().size();
+ r_Storage_Layout* stl = new r_Storage_Layout(theTiling->clone());
+ r_Ref<r_GMarray> fileMDD = new (mddTypeName)r_GMarray(mddDomain, baseTypeLength, stl);
+ fileMDD->set_type_schema(mddType);
+ stl = new r_Storage_Layout(theTiling->clone());
+ r_Ref<r_GMarray> targetMDD = new (mddTypeName)r_GMarray(overlayDomain, baseTypeLength, stl);
+ targetMDD->set_type_schema(mddType);
+ if (fileName)
+ {
+ FILE* filePointer = checkFile(fileName, retval);
+ if (retval != 0)
+ {
+ fileMDD.destroy();
+ targetMDD.destroy();
+ delete mddType;
+ mddType = NULL;
+ return retval;
+ }
+ retval = initGMarray(fileMDD, filePointer, inputFormat, mddDomain, inputFormatParams);
+ }
+ else {
+ RMInit::logOut << "Will not read from file" << endl;
+ }
+ if (retval == 0)
+ {
+ try {
+ openTransaction();
+ if (strlen(queryStringS))
+ {//do transparent update
+ r_OQL_Query query(queryStringS);
+ RMDBGIF(20, RMDebug::module_tools, "WAITBEFOREQL", \
+ RMInit::dbgOut << "Waiting 100 sec before execute\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ bool dataFound = true;
+ try {
+ r_oql_execute(query, result);
+ }
+ catch (r_Error& err)
+ {
+ dataFound = false;
+ if (err.get_kind() != r_Error::r_Error_TransferFailed)
+ {
+ throw;
+ }
+ }
+ RMDBGIF(20, RMDebug::module_tools, "WAITAFTERQL", \
+ RMInit::dbgOut << "Waiting 100 sec after execute\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ if (dataFound)
+ {
+ r_Iterator< r_Ref_Any > iter = result.create_iterator();
+ selectedMDD = r_Ref<r_GMarray>(*iter);
+ if (polygonDefined)
+ {
+ polygon.setMArray(*selectedMDD);
+ if (insidePatternSelDef)
+ polygon.fillMArrayInside(insidePatternSel);
+ if (outsidePatternSelDef)
+ polygon.fillMArrayOutside(outsidePatternSel);
+ }
+ if (fileName)
+ {
+ retval = overlayGMarrays(targetMDD, fileMDD, selectedMDD);
+ }
+ else {//just copy selected over target
+ retval = overlayGMarrays(targetMDD, selectedMDD, targetMDD);
+ }
+ }
+ else {
+ retval = overlayGMarrays(targetMDD, fileMDD, targetMDD);
+ }
+ }
+ else {
+ retval = overlayGMarrays(targetMDD, fileMDD, targetMDD);
+ }
+ if (retval == 0)
+ {
+ if (scaleLevels == NULL)
+ {
+ r_OQL_Query query(queryString);
+ query << *targetMDD;
+ RMDBGIF(20, RMDebug::module_tools, "WAITBEFOREQL", \
+ RMInit::dbgOut << "Waiting 100 sec before execute\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ r_oql_execute(query);
+ RMDBGIF(20, RMDebug::module_tools, "WAITAFTERQL", \
+ RMInit::dbgOut << "Waiting 100 sec after execute\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ }
+ else {
+ std::list<std::pair<double, char*> >::iterator iter = scaleLevels->begin();
+ std::list<std::pair<double, char*> >::iterator end = scaleLevels->end();
+ r_Minterval scaledDomain;
+ r_Minterval clipDomain;
+ unsigned int length = 0;
+ r_Dimension maxDim = mddDomain.dimension();
+ r_Point origin(maxDim);
+ double factor = 0;
+ for (r_Dimension i = 0; i < maxDim; i++)
+ origin[i] = 0;
+ while ((iter != end) && (retval == 0))
+ {
+ factor = iter->first;
+ if (factor == 1)
+ {
+ r_OQL_Query query(queryString);
+ query << *targetMDD;
+ RMDBGIF(20, RMDebug::module_tools, "WAITBEFOREQL", \
+ RMInit::dbgOut << "Waiting 100 sec before execute\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ r_oql_execute(query);
+ RMDBGIF(20, RMDebug::module_tools, "WAITAFTERQL", \
+ RMInit::dbgOut << "Waiting 100 sec after execute\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ }
+ else {
+ retval = scaleDomain(overlayDomain, origin, factor, scaledDomain, clipDomain, length);
+ RMInit::logOut << "scaled: " << iter->second << " scaled domain " << scaledDomain << " clip domain " << clipDomain << " result=" << retval << endl;
+ if (retval == 0)
+ retval = updateScaledMDD(targetMDD, clipDomain, scaledDomain, length, iter->second);
+ }
+ iter++;
+ }
+ }
+ RMDBGIF(20, RMDebug::module_tools, "WAITCOMMIT", \
+ RMInit::dbgOut << "Waiting 100 sec before commit\n" << std::endl; \
+ sleep(100); \
+ RMInit::dbgOut << "Continue now\n" << std::endl; );
+ }
+ if (retval == 0)
+ ta.commit();
+ else
+ ta.abort();
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error during administrative action: " << err.get_errorno() << " " << err.what() << endl;
+ retval = EXCEPTIONADMIN;
+ ta.abort();
+ }
+ if (db.get_status() != r_Database::not_open)
+ db.close();
+ }
+ fileMDD.destroy();
+ targetMDD.destroy();
+ }
+ delete mddType;
+ mddType = NULL;
+ return retval;
+ }
+
diff --git a/rasodmg/test/system_update.hh b/rasodmg/test/system_update.hh
new file mode 100644
index 0000000..74d1fc6
--- /dev/null
+++ b/rasodmg/test/system_update.hh
@@ -0,0 +1,40 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+#ifndef _SYSTEMUPDATE_HH_
+#define _SYSTEMUPDATE_HH_
+
+#include "system_basic.hh"
+
+class SystemUpdate : public SystemBasic
+ {
+ public:
+ static int doStuff(int argc, char** argv);
+
+ static void printUsage();
+
+ static int doUpdate(const char* Query, const char* TransparentSelectQuery);
+
+ };
+
+#endif
diff --git a/rasodmg/test/test_alignedtiling.cc b/rasodmg/test/test_alignedtiling.cc
new file mode 100644
index 0000000..636a3c1
--- /dev/null
+++ b/rasodmg/test/test_alignedtiling.cc
@@ -0,0 +1,126 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_alignedtiling.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <iostream>
+#include <string.h>
+
+#ifdef __VISUALC__
+ #define __EXECUTABLE__
+#endif
+// #include "clientcomm/clientcomm.hh"
+#include "rasodmg/ref.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/odmgtypes.hh"
+#include "raslib/minterval.hh"
+#include "rasodmg/alignedtiling.hh"
+#ifdef __VISUALC__
+ #undef __EXECUTABLE__
+#endif
+
+
+int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex )
+{
+ int found = 0;
+ int i=1;
+
+ while( !found && i<argc )
+ found = !strcmp( searchText, argv[i++] );
+
+ if( found && i<argc && !strchr(argv[i],'-') )
+ optionValueIndex = i;
+ else
+ optionValueIndex = 0;
+
+ return found;
+}
+
+
+int main( int argc, char** argv )
+{
+
+ int optionValueIndex;
+ if( argc < 5 || checkArguments( argc, argv, "-h", optionValueIndex ) )
+ {
+ cout << "Usage: test_alignedtiling tile_config tile_size cell_size domain" << endl << endl;
+ cout << "Options: -h ... this help" << endl;
+ cout << endl;
+ return 0;
+ }
+
+ r_Minterval* tile_config = 0;
+ r_Minterval* domain = 0;
+
+ try {
+ tile_config = new r_Minterval( argv[1] );
+ domain = new r_Minterval( argv[4] );
+ }
+ catch (...)
+ {
+ return -1;
+ }
+
+ unsigned cell_size = strtoul( argv[3], (char **)NULL, 10 );
+ unsigned long tile_size = strtoul( argv[2], (char **)NULL, 10 );
+
+ cout << "Tile Config " << *tile_config << endl;
+ r_Aligned_Tiling storeOptions( *tile_config, tile_size );
+
+ cout << endl;
+
+ cout << "Tiling Options : ts - " << storeOptions.get_tile_size( )
+ << ", tc - " << storeOptions.get_tile_config( ) << endl;
+
+ cout << "Object domain : " << *domain << ", cell size " << cell_size << endl;
+
+
+ r_Aligned_Tiling newSL(storeOptions);
+
+ cout << "Testing copy constructor. Newly constructed object..." << endl;
+ cout << "Tiling Options : ts - " << storeOptions.get_tile_size( )
+ << ", tc - " << storeOptions.get_tile_config( ) << endl;
+
+ cout << "Object domain : " << *domain << ", cell size " << cell_size << endl;
+
+ r_Minterval result_tile =
+ storeOptions.compute_tile_domain(cell_size, *domain);
+
+ cout << "Tiling Options resulting tile :" << result_tile << endl;
+
+
+ delete domain;
+ delete tile_config;
+
+ return 0;
+}
+
diff --git a/rasodmg/test/test_all.sh b/rasodmg/test/test_all.sh
new file mode 100644
index 0000000..dfff5fd
--- /dev/null
+++ b/rasodmg/test/test_all.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/ksh
+
+runbm.sh -e 20 tmov_16.ql tmov_32.ql tmov_64.ql
+runbm.sh -n 10 tsel_sliced.ql tsel_16.ql tsel_32.ql tsel_64.ql
+runbm.sh -e 20 troll_sliced.ql troll_16.ql troll_32.ql troll_64.ql
+runbm.sh -e 20 cmov_16.ql cmov_32.ql cmov_64.ql
+runbm.sh -n 10 csel_sliced.ql csel_16.ql csel_32.ql csel_64.ql
+runbm.sh -e 20 croll_sliced.ql croll_16.ql croll_32.ql croll_64.ql
+runbm.sh -n 5 earth_16.ql earth_32.ql earth_64.ql small_16.ql small_32.ql small_64.ql
diff --git a/rasodmg/test/test_benchmark.cc b/rasodmg/test/test_benchmark.cc
new file mode 100644
index 0000000..2997d68
--- /dev/null
+++ b/rasodmg/test/test_benchmark.cc
@@ -0,0 +1,273 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_benchmark.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream.h>
+#endif
+
+#include <iostream>
+#include <fstream.h>
+#include <string.h>
+
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/ref.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/iterator.hh"
+#include "rasodmg/oqlquery.hh"
+
+#include "raslib/type.hh"
+#include "raslib/shhopt.h"
+#include "raslib/rmdebug.hh"
+
+#include <sys/time.h>
+
+static int numExec = 1; // number of repetitions for each query
+static int readEach = 0; // number of repeated queries in query file
+static int qNum = 0; // counter for current query
+
+RMTimer execTimer("test_benchmark", "r_oql_execute()");
+RMTimer wholeTimer("test_benchmark", "execQuery()");
+
+int checkArguments( int argc, char** argv, const char* searchText,
+ int& optionValueIndex )
+{
+ int found = 0;
+ int i=1;
+
+ while( !found && i<argc )
+ found = !strcmp( searchText, argv[i++] );
+
+ if( found && i<argc && !strchr(argv[i],'-') )
+ optionValueIndex = i;
+ else
+ optionValueIndex = 0;
+
+ return found;
+}
+
+void execQuery( char* serverName, char* baseName, char* queryBuffer )
+{
+}
+
+static void
+printUsage(void)
+{
+ cout << "Usage: test_benchmark [options] server_name base_name file_name"
+ << endl;
+ cout << " -h, --help Print this message and exit." << endl;
+ cout << " -n, --nrepeat Followed by number of repeated" << endl
+ << " executions for each query in file_name."
+ << endl;
+ cout << " -e, --readeach Followed by number of queries read from"
+ << endl
+ << " the query file treated as variations of"
+ << endl
+ << " the same query." << endl;
+ exit(0);
+}
+
+void execQuery(char* serverName, char* baseName, char* comment, char* query)
+{
+ int i;
+ r_Database db;
+ r_Transaction ta;
+
+ RMInit::bmOut << comment;
+ RMInit::bmOut << "Query " << (qNum/numExec)+1 << "." << (qNum%numExec)+1
+ << ": " << query;
+ qNum++;
+
+ wholeTimer.start();
+
+ r_Set< r_Ref_Any > image_set;
+ db.set_servername( serverName );
+
+ try
+ {
+ r_OQL_Query q1( query );
+
+ db.open( baseName );
+
+ if( q1.is_update_query() )
+ ta.begin();
+ else
+ ta.begin( r_Transaction::read_only );
+
+ // here the query is executed and times are taken
+
+ try
+ {
+ execTimer.start();
+ if( q1.is_update_query() )
+ r_oql_execute( q1 );
+ else
+ r_oql_execute( q1, image_set );
+ execTimer.stop();
+ }
+
+ catch( r_Error& errorObj )
+ {
+ execTimer.stop();
+ cerr << endl << "QUERY FAILED" << endl << errorObj.what() << endl;
+ ta.commit();
+ db.close();
+ }
+
+ ta.commit();
+ db.close();
+
+ wholeTimer.stop();
+ }
+ catch( r_Error& errorObj )
+ {
+ wholeTimer.stop();
+ cerr << endl << "FAILED" << endl << errorObj.what() << endl;
+ }
+}
+
+void execQueries(char* serverName, char* baseName, char* comment, char* query)
+{
+ if(!readEach) {
+ for(int i = 0; i < numExec; i++)
+ execQuery(serverName, baseName, comment, query);
+ }
+ else {
+ execQuery(serverName, baseName, comment, query);
+ }
+}
+
+void parseFile(ifstream& fileStream, char* serverName, char* baseName)
+{
+ enum legalStates { FIRSTCOMMENT, COMMENT, QUERY };
+ legalStates parseState = FIRSTCOMMENT;
+ ostrstream commentStream;
+ ostrstream queryStream;
+ char buf[256];
+ char dummy;
+
+ while( fileStream.get( buf, 255, '\n' ) ) {
+ // read end of line
+ fileStream.get(dummy);
+ // checking for empty line
+ if(buf[0] == 0) {
+ if(parseState == FIRSTCOMMENT) {
+ // end of first comment, print it and switch to normal comment
+ commentStream << ends;
+ RMInit::bmOut << commentStream.str() << endl;
+ commentStream.rdbuf()->freeze(0);
+ commentStream.seekp(0, ios::beg);
+ parseState = COMMENT;
+ }
+ }
+ // checking for comment
+ else if(buf[0] == '/' && buf[1] == '/') {
+ if(parseState == QUERY) {
+ // execute the query, reset buffers
+ queryStream << endl << ends;
+ commentStream << ends;
+ execQueries(serverName, baseName, commentStream.str(),
+ queryStream.str());
+ queryStream.rdbuf()->freeze(0);
+ queryStream.seekp(0, ios::beg);
+ commentStream.rdbuf()->freeze(0);
+ commentStream.seekp(0, ios::beg);
+ parseState = COMMENT;
+ }
+ commentStream << buf << endl;
+ }
+ // must be a query
+ else {
+ parseState = QUERY;
+ queryStream << buf;
+ queryStream << " ";
+ }
+ }
+ // last query
+ if(parseState == QUERY) {
+ // execute the query, reset buffers
+ queryStream << endl << ends;
+ commentStream << ends;
+ execQueries(serverName, baseName, commentStream.str(),
+ queryStream.str());
+ queryStream.rdbuf()->freeze(0);
+ queryStream.seekp(0, ios::beg);
+ commentStream.rdbuf()->freeze(0);
+ commentStream.seekp(0, ios::beg);
+ }
+}
+
+int main( int argc, char** argv )
+{
+ int optionValueIndex;
+ char serverName[255];
+ char baseName[255];
+ char fileName[255];
+
+ optStruct testBenchmarkOpt[] = {
+ /* short long type var/func special */
+ { 'h', "help", OPT_FLAG, printUsage, OPT_CALLFUNC },
+ { 'n', "nrepeat", OPT_INT, &numExec, 0 },
+ { 'e', "readeach", OPT_INT, &readEach, 0 },
+ { 0, 0, OPT_END, 0, 0 } /* no more options */
+ };
+
+ /* parse all options */
+ optParseOptions(&argc, argv, testBenchmarkOpt, 0);
+
+ if( argc < 4 )
+ printUsage();
+
+ if(readEach)
+ numExec = readEach;
+
+ strcpy( serverName, argv[argc-3] );
+ strcpy( baseName, argv[argc-2] );
+ strcpy( fileName, argv[argc-1] );
+
+ ifstream fileStream( fileName );
+ if( !fileStream )
+ {
+ cout << "Error: File not found." << endl;
+ return -1;
+ }
+
+ parseFile(fileStream, serverName, baseName);
+ return 0;
+}
diff --git a/rasodmg/test/test_bmark_dir.cc b/rasodmg/test/test_bmark_dir.cc
new file mode 100644
index 0000000..04535c8
--- /dev/null
+++ b/rasodmg/test/test_bmark_dir.cc
@@ -0,0 +1,257 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_bmark_dir.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: benchmark dirtiling
+ *
+ * COMMENTS:
+ * This program creates a 3D datacube for benchmarking
+ * the directional tiling method
+ *
+*/
+
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rasodmg/ref.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/odmgtypes.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/storagelayout.hh"
+#include "raslib/oid.hh"
+
+#define TOTAL_DAYS (365L * 2L)
+#define TOTAL_PRODUCTS (60L)
+#define TOTAL_STORES (100L)
+
+#define MAX_SALES 500
+
+#define S_32K (32 * 1024L)
+#define S_64K (64 * 1024L)
+#define S_128K (128 * 1024L)
+#define S_256K (256 * 1024L)
+
+#define TOTAL_CUBES 9
+
+
+char* server_name;
+char* dbase_name;
+char* colect_name;
+
+void parse(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ cout << "Usage: " << argv[0] << " [server name] [db name] [colection name]"
+ << endl;
+
+ exit(0);
+ }
+
+ server_name = argv[1];
+ dbase_name = argv[2];
+ colect_name = argv[3];
+}
+
+r_ULong init(const r_Point&)
+{
+ return (long)(rand() % MAX_SALES);
+}
+
+void insert_datacube()
+{
+
+ r_Ref< r_Set< r_Ref< r_Marray<r_ULong> > > > cube_set;
+ // r_Ref< r_Marray<r_ULong> > cube[TOTAL_CUBES];
+ r_Minterval domain, block_config;
+ r_Domain_Storage_Layout* dsl[TOTAL_CUBES];
+ r_OId oid[TOTAL_CUBES];
+
+ domain = r_Minterval(3);
+ domain << r_Sinterval(1L, TOTAL_DAYS)
+ << r_Sinterval(1L, TOTAL_PRODUCTS)
+ << r_Sinterval(1L, TOTAL_STORES);
+
+
+ // For alligned tiling (Regular tiling)
+
+ block_config = r_Minterval(3);
+ block_config << r_Sinterval(0L, TOTAL_DAYS)
+ << r_Sinterval(0L, TOTAL_PRODUCTS)
+ << r_Sinterval(0L, TOTAL_STORES);
+
+ r_Aligned_Tiling* til_reg_32k = new r_Aligned_Tiling(block_config, S_32K);
+ r_Aligned_Tiling* til_reg_64k = new r_Aligned_Tiling(block_config, S_64K);
+ r_Aligned_Tiling* til_reg_128k = new r_Aligned_Tiling(block_config, S_128K);
+ r_Aligned_Tiling* til_reg_256k = new r_Aligned_Tiling(block_config, S_256K);
+
+
+ // For directional tiling
+
+ r_Dir_Decompose decomp[3];
+ decomp[0] << 1 << 365 << 730;
+ decomp[1] << 1 << 27 << 42 << 60;
+ decomp[2] << 1 << 27 << 35 << 41 << 59 << 73 << 89 << 97 << 100;
+
+ r_Dir_Tiling* til_dir_32k = new r_Dir_Tiling(3, decomp, S_32K);
+ r_Dir_Tiling* til_dir_64k = new r_Dir_Tiling(3, decomp, S_64K);
+ r_Dir_Tiling* til_dir_128k = new r_Dir_Tiling(3, decomp, S_128K);
+ r_Dir_Tiling* til_dir_256k = new r_Dir_Tiling(3, decomp, S_256K);
+ r_Dir_Tiling* til_dir_Unlk = new r_Dir_Tiling(3, decomp, S_256K, r_Dir_Tiling::WITHOUT_SUBTILING);
+
+
+ // Domain storage layouts
+
+ dsl[0] = new r_Domain_Storage_Layout(domain, til_reg_32k);
+ dsl[1] = new r_Domain_Storage_Layout(domain, til_reg_64k);
+ dsl[2] = new r_Domain_Storage_Layout(domain, til_reg_128k);
+ dsl[3] = new r_Domain_Storage_Layout(domain, til_reg_256k);
+
+ dsl[4] = new r_Domain_Storage_Layout(domain, til_dir_32k);
+ dsl[5] = new r_Domain_Storage_Layout(domain, til_dir_64k);
+ dsl[6] = new r_Domain_Storage_Layout(domain, til_dir_128k);
+ dsl[7] = new r_Domain_Storage_Layout(domain, til_dir_256k);
+ dsl[8] = new r_Domain_Storage_Layout(domain, til_dir_Unlk);
+
+
+for (int i=0; i< TOTAL_CUBES ; i++)
+{
+ r_Database db;
+ r_Transaction trans;
+ // The main phase of the database creation
+ r_Ref< r_Marray<r_ULong> > cube1;
+
+ db.set_servername(server_name);
+
+ try
+ {
+ cout << "Opening database " << dbase_name << " on " << server_name
+ << "... " << flush;
+
+ db.open(dbase_name);
+
+ cout << "Ok" << endl;
+ cout << "Starting transaction... " << flush;
+
+ trans.begin();
+
+
+ cout << "Ok" << endl;
+ cout << "Opening the set... " << flush;
+
+ try
+ {
+ cube_set = db.lookup_object(colect_name);
+ }
+ catch (...)
+ {
+ cout << "*Failed*" << endl;
+ cout << "Creating the set... " << flush;
+
+ cube_set = new(&db, "ULong_3D_Set") r_Set< r_Ref< r_Marray<r_ULong> > >;
+ db.set_object_name(*cube_set, colect_name);
+ }
+
+ cout << "Ok" << endl;
+ cout << "Creating the datacube... " << flush;
+
+ // for (int i=0; i<TOTAL_CUBES; i++)
+ // {
+ // cube[i] =
+ cube1 =
+ new(&db, "ULong_3D_Cube") r_Marray<r_ULong>(domain, 1L /* &init */, dsl[i]);
+
+ // cube_set->insert_element(cube[i]);
+ // oid[i] = cube[i].get_oid();
+ cube_set->insert_element(cube1);
+ oid[i] = cube1->get_oid();
+
+ cout << "*" << flush;
+
+
+ cout << " ... Ok" << endl;
+
+ cout << " Cube[" << i << "]: " << oid[i] << endl;
+
+ cout << "Commiting transaction... " << flush;
+
+ trans.commit();
+
+ cout << "Ok" << endl;
+
+ cout << "Closing database... " << flush;
+
+ db.close();
+
+ }
+ catch (r_Error& e)
+ {
+ cout << e.what() << endl;
+ exit(0);
+ }
+ catch (...)
+ {
+ cout << "Undefined error..." << endl;
+ exit(0);
+ }
+}
+
+ cout << "Ok [******************]" << endl << flush;
+
+// Wrong - management of memory for storage layouts passes
+// to the marray, after being given to it.
+// for (int j=0; j<TOTAL_CUBES; j++)
+// delete dsl[j];
+
+ cout << endl;
+ cout << "Inserted data resume" << endl;
+ cout << "====================" << endl;
+
+ // for (int k=0; k<TOTAL_CUBES; k++)
+ // cout << " Cube[" << k << "]: " << oid[k] << endl;
+}
+
+int main(int argc, char* argv[])
+{
+ parse(argc, argv);
+ insert_datacube();
+
+ return 0;
+}
+
+
+
+
+
+
+
+
diff --git a/rasodmg/test/test_bmark_dir1.cc b/rasodmg/test/test_bmark_dir1.cc
new file mode 100644
index 0000000..c185858
--- /dev/null
+++ b/rasodmg/test/test_bmark_dir1.cc
@@ -0,0 +1,318 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_bmark_dir1.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: benchmark dirtiling
+ *
+ * COMMENTS:
+ * This program creates 3D and 5D datacubes for benchmarking
+ * the directional tiling method
+ *
+*/
+
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rasodmg/ref.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "raslib/odmgtypes.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/storagelayout.hh"
+#include "raslib/oid.hh"
+
+#define YEARS (2L)
+
+#define TOTAL_DAYS (365L * 2L)
+#define TOTAL_PRODUCTS (60L)
+#define TOTAL_STORES (100L)
+
+
+#define MAX_SALES 500
+
+#define S_32K (32 * 1024L)
+#define S_64K (64 * 1024L)
+#define S_128K (128 * 1024L)
+#define S_256K (256 * 1024L)
+
+#define TOTAL_CUBES 10
+
+
+char* server_name;
+char* dbase_name;
+char* colect_name;
+
+void parse(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ cout << "Usage: " << argv[0] << " [server name] [db name] [colection name]"
+ << endl;
+
+ exit(0);
+ }
+
+ server_name = argv[1];
+ dbase_name = argv[2];
+ colect_name = argv[3];
+}
+
+r_ULong init(const r_Point& pnt )
+{
+ return (long)(rand() % MAX_SALES);
+}
+
+void insert_datacube()
+{
+
+ r_Ref< r_Set< r_Ref< r_Marray<r_ULong> > > > cube_set;
+ // r_Ref< r_Marray<r_ULong> > cube[TOTAL_CUBES];
+ r_Minterval domain, block_config;
+ r_Domain_Storage_Layout* dsl[TOTAL_CUBES];
+ r_OId oid[TOTAL_CUBES];
+
+ domain = r_Minterval(3);
+ domain << r_Sinterval(1L, TOTAL_DAYS)
+ << r_Sinterval(1L, TOTAL_PRODUCTS)
+ << r_Sinterval(1L, TOTAL_STORES);
+
+
+ block_config = r_Minterval(3);
+ block_config << r_Sinterval(0L, TOTAL_DAYS)
+ << r_Sinterval(0L, TOTAL_PRODUCTS)
+ << r_Sinterval(0L, TOTAL_STORES);
+
+ // Each storage object must have an own dynamic tiling obj or else the client
+ // ( and server ) crashes because memory is released for a non heap memory free
+ // r_Marray become responsible for managing the memory allocated for the
+ // tiling object.
+ r_Aligned_Tiling* til_reg_32k = new r_Aligned_Tiling(block_config, S_32K);
+ r_Aligned_Tiling* til_reg_64k = new r_Aligned_Tiling(block_config, S_64K);
+ r_Aligned_Tiling* til_reg_128k = new r_Aligned_Tiling(block_config, S_128K);
+ r_Aligned_Tiling* til_reg_256k = new r_Aligned_Tiling(block_config, S_256K);
+
+
+ // For directional tiling
+
+ r_Dir_Decompose decomp[3];
+
+ // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dez
+ unsigned int daysMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ int ix = 0;
+ int year;
+ int month;
+ decomp[0] << 1;
+ for ( year = 0; year < YEARS ; year++)
+ {
+ for (month = 0; month < 12; month++ )
+ {
+ decomp[0] << ix + daysMonth[month];
+ ix += daysMonth[month];
+ }
+ }
+
+ decomp[1] << 1 << 60;
+
+ // << 1 << 1 + 26 << 27 + 8 << 35 + 6 << 41 + 18 << 59 + 14 << 73 + 16 << 89 + 8 << 97 + 3;
+ decomp[2] << 1 << 27 << 35 << 41 << 59 << 73 << 89 << 97 << 100;
+
+
+ r_Dir_Tiling* til_dir_32k = new r_Dir_Tiling(3, decomp, S_32K);
+ r_Dir_Tiling* til_dir_64k = new r_Dir_Tiling(3, decomp, S_64K);
+ r_Dir_Tiling* til_dir_128k = new r_Dir_Tiling(3, decomp, S_128K);
+ r_Dir_Tiling* til_dir_256k = new r_Dir_Tiling(3, decomp, S_256K);
+
+
+ r_Dir_Decompose decomp1[3];
+
+ ix = 0;
+ decomp1[0] << 1;
+ for ( year = 0; year < YEARS ; year++)
+ {
+ for (month = 0; month < 12; month++ )
+ {
+ decomp1[0] << ix + daysMonth[month];
+ ix += daysMonth[month];
+ }
+ }
+
+ // Products
+ // << 1<< 1+ 26 << 27 + 15 << 42 + 28
+ decomp1[1] << 1 << 27 << 42 << 60;
+
+ // Stores
+ // << 1 << 1 + 26 << 27 + 8 << 35 + 6 << 41 + 18 << 59 + 14 << 73 + 16 << 89 + 8 << 97 + 3;
+ decomp1[2] << 1 << 27 << 35 << 41 << 59 << 73 << 89 << 97 << 100;
+
+ r_Dir_Tiling* til_dir1_32k = new r_Dir_Tiling(3, decomp1, S_32K);
+ r_Dir_Tiling* til_dir1_64k = new r_Dir_Tiling(3, decomp1, S_64K);
+
+ // Domain storage layouts
+
+ dsl[0] = new r_Domain_Storage_Layout(domain, til_reg_32k);
+ dsl[1] = new r_Domain_Storage_Layout(domain, til_reg_64k);
+ dsl[2] = new r_Domain_Storage_Layout(domain, til_reg_128k);
+ dsl[3] = new r_Domain_Storage_Layout(domain, til_reg_256k);
+
+ dsl[4] = new r_Domain_Storage_Layout(domain, til_dir_32k);
+ dsl[5] = new r_Domain_Storage_Layout(domain, til_dir_64k);
+ dsl[6] = new r_Domain_Storage_Layout(domain, til_dir_128k);
+ dsl[7] = new r_Domain_Storage_Layout(domain, til_dir_256k);
+
+ dsl[8] = new r_Domain_Storage_Layout(domain, til_dir1_32k);
+ dsl[9] = new r_Domain_Storage_Layout(domain, til_dir1_64k);
+
+
+for (int i= 0 ; i< TOTAL_CUBES ; i++)
+{
+ r_Database db;
+ r_Transaction trans;
+ // The main phase of the database creation
+ r_Ref< r_Marray<r_ULong> > cube1;
+
+ db.set_servername(server_name);
+
+ try
+ {
+ cout << "Opening database " << dbase_name << " on " << server_name
+ << "... " << flush;
+
+ db.open(dbase_name);
+
+ cout << "Ok" << endl;
+ cout << "Starting transaction... " << flush;
+
+ trans.begin();
+
+
+ cout << "Ok" << endl;
+ cout << "Opening the set... " << flush;
+
+ try
+ {
+ cube_set = db.lookup_object(colect_name);
+ }
+ catch (...)
+ {
+ cout << "*Failed*" << endl;
+ cout << "Creating the set... " << flush;
+
+ cube_set = new(&db, "ULong_3D_Set") r_Set< r_Ref< r_Marray<r_ULong> > >;
+ db.set_object_name(*cube_set, colect_name);
+ }
+
+ cout << "Ok" << endl;
+ cout << "Creating the datacube... " << flush;
+
+ // for (int i=0; i<TOTAL_CUBES; i++)
+ // {
+ // cube[i] =
+ cout << "domain == " << domain << endl;
+ cube1 =
+ new(&db, "ULong_3D_Cube") r_Marray<r_ULong>(domain, 1L/* &init */, dsl[i]);
+
+ // cube_set->insert_element(cube[i]);
+ // oid[i] = cube[i].get_oid();
+ cube_set->insert_element(cube1);
+ oid[i] = cube1->get_oid();
+
+ cout << "*" << flush;
+
+
+ cout << " ... Ok" << endl;
+
+ cout << " Cube[" << i+1 << "]: " << oid[i] << endl;
+ cout << " Spatial domain: " << cube1->spatial_domain( ) << endl;
+ cout << " Type length: " << cube1->get_type_length( ) << endl;
+ cout << " Storage Layout: ";
+ if( i < 4 )
+ cout << "regular; tile size " << dsl[i]->get_tile_size( ) << endl;
+ else
+ {
+ cout << "directional; tile size " << dsl[i]->get_tile_size( ) << endl;
+ cout << "Dir decompose: ";
+ for ( int j = 0; j < 3 ; j++ )
+ {
+ for ( int k = 0; k < 3 ; k++)
+ {
+ if ( i < 8 )
+ decomp[k].print_status(cout );
+ else
+ decomp1[k].print_status( cout );
+ }
+ }
+ cout << endl;
+ }
+
+ cout << "Commiting transaction... " << flush;
+
+ trans.commit();
+
+ cout << "Ok" << endl;
+
+ cout << "Closing database... " << flush;
+
+ db.close();
+
+ }
+ catch (r_Error& e)
+ {
+ cout << e.what() << endl;
+ exit(0);
+ }
+ catch (...)
+ {
+ cout << "Undefined error..." << endl;
+ exit(0);
+ }
+}
+
+ cout << "Ok [******************]" << endl << flush;
+
+ cout << endl;
+ cout << "Inserted data resume" << endl;
+ cout << "====================" << endl;
+}
+
+int main(int argc, char* argv[])
+{
+ parse(argc, argv);
+ insert_datacube();
+
+ return 0;
+}
+
+
+
+
+
+
+
+
diff --git a/rasodmg/test/test_bmark_int.cc b/rasodmg/test/test_bmark_int.cc
new file mode 100644
index 0000000..ddd8610
--- /dev/null
+++ b/rasodmg/test/test_bmark_int.cc
@@ -0,0 +1,241 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_bmark_dir.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: benchmark interest tiling
+ *
+ * COMMENTS:
+ * This program is used to load the database with information
+ * for benchmarking interesting tiling
+ *
+*/
+
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rasodmg/ref.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "raslib/odmgtypes.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/storagelayout.hh"
+#include "raslib/oid.hh"
+#include "RGBCube.hh"
+
+#define S_32K (32 * 1024L)
+#define S_64K (64 * 1024L)
+#define S_128K (128 * 1024L)
+#define S_256K (256 * 1024L)
+
+#define TOTAL_CUBES 8
+#define SIZE_X 120L
+#define SIZE_Y 159L
+#define SIZE_Z 119L
+
+char* server_name;
+char* dbase_name;
+char* colect_name;
+
+void parse(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ cout << "Usage: " << argv[0] << " [server name] [db name] [colection name]"
+ << endl;
+
+ exit(0);
+ }
+
+ server_name = argv[1];
+ dbase_name = argv[2];
+ colect_name = argv[3];
+}
+
+void insert_datacube()
+{
+
+ r_Ref< r_Set< r_Ref< r_Marray<r_ULong> > > > cube_set;
+ r_Minterval domain;
+ r_Domain_Storage_Layout* dsl[TOTAL_CUBES];
+ r_OId oid[TOTAL_CUBES];
+
+ domain = r_Minterval(3);
+ domain << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(0L, SIZE_Y)
+ << r_Sinterval(0L, SIZE_Z);
+
+
+ // For alligned tiling (Regular tiling)
+
+ r_Minterval block_config(3);
+ block_config << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(0L, SIZE_Y)
+ << r_Sinterval(0L, SIZE_Z);
+
+ r_Aligned_Tiling* til_reg_32k = new r_Aligned_Tiling(block_config, S_32K);
+ r_Aligned_Tiling* til_reg_64k = new r_Aligned_Tiling(block_config, S_64K);
+ r_Aligned_Tiling* til_reg_128k = new r_Aligned_Tiling(block_config, S_128K);
+ r_Aligned_Tiling* til_reg_256k = new r_Aligned_Tiling(block_config, S_256K);
+
+
+ // For directional tiling
+
+ r_Minterval interest1(3);
+ interest1 << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(65L, 110L)
+ << r_Sinterval(35L, 75L);
+
+ r_Minterval interest2(3);
+ interest2 << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(90L, 150L)
+ << r_Sinterval(45L, 105L);
+
+ r_Minterval interest3(3);
+ interest3 << r_Sinterval(60L, 120L)
+ << r_Sinterval(0L, SIZE_Y)
+ << r_Sinterval(0L, SIZE_Z);
+
+ DList<r_Minterval> areas;
+ areas += interest1;
+ areas += interest2;
+ areas += interest3;
+
+ r_Interest_Tiling* til_int_32k =
+ new r_Interest_Tiling(areas, r_Interest_Tiling::SUB_TILING, S_32K);
+ r_Interest_Tiling* til_int_64k =
+ new r_Interest_Tiling(areas, r_Interest_Tiling::SUB_TILING, S_64K);
+ r_Interest_Tiling* til_int_128k =
+ new r_Interest_Tiling(areas, r_Interest_Tiling::SUB_TILING, S_128K);
+ r_Interest_Tiling* til_int_256k =
+ new r_Interest_Tiling(areas, r_Interest_Tiling::SUB_TILING, S_256K);
+
+ // Domain storage layouts
+
+ dsl[0] = new r_Domain_Storage_Layout(domain, til_reg_32k);
+ dsl[1] = new r_Domain_Storage_Layout(domain, til_reg_64k);
+ dsl[2] = new r_Domain_Storage_Layout(domain, til_reg_128k);
+ dsl[3] = new r_Domain_Storage_Layout(domain, til_reg_256k);
+
+ dsl[4] = new r_Domain_Storage_Layout(domain, til_int_32k);
+ dsl[5] = new r_Domain_Storage_Layout(domain, til_int_64k);
+ dsl[6] = new r_Domain_Storage_Layout(domain, til_int_128k);
+ dsl[7] = new r_Domain_Storage_Layout(domain, til_int_256k);
+
+
+ // Create cubes
+
+ r_Database db;
+ db.set_servername(server_name);
+
+ for (int i=0; i< TOTAL_CUBES ; i++)
+ {
+ r_Transaction trans;
+
+ r_Ref< r_Marray<r_ULong> > cube;
+
+ try
+ {
+ cout << "Opening database " << dbase_name << " on " << server_name
+ << "... " << flush;
+
+ db.open(dbase_name);
+
+ cout << "Ok" << endl;
+ cout << "Starting transaction... " << flush;
+
+ trans.begin();
+
+ cout << "Ok" << endl;
+ cout << "Opening the set... " << flush;
+
+ try
+ {
+ cube_set = db.lookup_object(colect_name);
+ }
+ catch (...)
+ {
+ cout << "*Failed*" << endl;
+ cout << "Creating the set... " << flush;
+
+ cube_set =
+ new(&db, "RGB_3D_Set") r_Set< r_Ref< r_Marray<RGBPixel> > >;
+
+ db.set_object_name(*cube_set, colect_name);
+ }
+
+ cout << "Ok" << endl;
+ cout << "Creating the datacube... " << flush;
+
+ cube =
+ new(&db, "RGB_3D_Cube") r_Marray<RGBPixel>(domain, dsl[i]);
+
+ cube_set->insert_element(cube);
+
+ cout << " Cube[" << i << "]: " << cube->get_oid() << endl;
+
+ cout << "*" << flush;
+ cout << " ... Ok" << endl;
+ cout << "Commiting transaction... " << flush;
+
+ trans.commit();
+
+ cout << "Ok" << endl;
+ cout << "Closing database... " << flush;
+
+ db.close();
+ }
+ catch (r_Error& e)
+ {
+ cout << e.what() << endl;
+ exit(0);
+ }
+ catch (...)
+ {
+ cout << "Undefined error..." << endl;
+ exit(0);
+ }
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ parse(argc, argv);
+ insert_datacube();
+
+ return 0;
+}
+
+
+
+
+
+
+
+
diff --git a/rasodmg/test/test_bmark_int1.cc b/rasodmg/test/test_bmark_int1.cc
new file mode 100644
index 0000000..dce1311
--- /dev/null
+++ b/rasodmg/test/test_bmark_int1.cc
@@ -0,0 +1,242 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_bmark_int1.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: benchmark interest tiling
+ *
+ * COMMENTS:
+ * This program is used to load the database with information
+ * for benchmarking interesting tiling
+ *
+*/
+
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rasodmg/ref.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/odmgtypes.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/storagelayout.hh"
+#include "raslib/oid.hh"
+#include "RGBCube.hh"
+
+#define S_32K (32 * 1024L)
+#define S_64K (64 * 1024L)
+#define S_128K (128 * 1024L)
+#define S_256K (256 * 1024L)
+
+#define TOTAL_CUBES 8
+#define SIZE_X 120L // 12L //
+#define SIZE_Y 159L // 16L //
+#define SIZE_Z 119L // 12L //
+
+char* server_name;
+char* dbase_name;
+char* colect_name;
+
+void parse(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ cout << "Usage: " << argv[0] << " [server name] [db name] [colection name]"
+ << endl;
+
+ exit(0);
+ }
+
+ server_name = argv[1];
+ dbase_name = argv[2];
+ colect_name = argv[3];
+}
+
+void insert_datacube( )
+{
+
+ r_Ref< r_Set< r_Ref< r_Marray<r_ULong> > > > cube_set;
+ r_Minterval domain[TOTAL_CUBES];
+ r_Domain_Storage_Layout* dsl[TOTAL_CUBES];
+ r_OId oid[TOTAL_CUBES];
+
+ for (int i = 0; i < TOTAL_CUBES; i++)
+ {
+ domain[i] = r_Minterval(3);
+ domain[i] << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(0L, SIZE_Y)
+ << r_Sinterval(0L, SIZE_Z);
+ }
+
+ // For alligned tiling (Regular tiling)
+
+ r_Minterval block_config(3);
+ block_config << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(0L, SIZE_Y)
+ << r_Sinterval(0L, SIZE_Z);
+
+ r_Aligned_Tiling* til_reg_32k = new r_Aligned_Tiling(block_config, S_32K);
+ r_Aligned_Tiling* til_reg_64k = new r_Aligned_Tiling(block_config, S_64K);
+ r_Aligned_Tiling* til_reg_128k = new r_Aligned_Tiling(block_config, S_128K);
+ r_Aligned_Tiling* til_reg_256k = new r_Aligned_Tiling(block_config, S_256K);
+
+
+ // For directional tiling
+
+ r_Minterval interest1(3);
+ interest1 << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(80L, 120L) // r_Sinterval(8L, 12L) //
+ << r_Sinterval(25L, 60L); // r_Sinterval(2L, 6L); //
+
+ r_Minterval interest2(3);
+ interest2 << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(70L, 159L) // r_Sinterval(7L, 16L) //
+ << r_Sinterval(25L, 105L); //r_Sinterval(2L, 10L); //
+
+
+ DList<r_Minterval> areas;
+ areas += interest1;
+ areas += interest2;
+
+ r_Interest_Tiling* til_int_32k =
+ new r_Interest_Tiling(areas, r_Interest_Tiling::SUB_TILING, S_32K);
+ r_Interest_Tiling* til_int_64k =
+ new r_Interest_Tiling(areas, r_Interest_Tiling::SUB_TILING, S_64K);
+ r_Interest_Tiling* til_int_128k =
+ new r_Interest_Tiling(areas, r_Interest_Tiling::SUB_TILING, S_128K);
+ r_Interest_Tiling* til_int_256k =
+ new r_Interest_Tiling(areas, r_Interest_Tiling::SUB_TILING, S_256K);
+
+ // Domain storage layouts
+
+ dsl[0] = new r_Domain_Storage_Layout(domain[0], til_reg_32k);
+ dsl[1] = new r_Domain_Storage_Layout(domain[1], til_reg_64k);
+ dsl[2] = new r_Domain_Storage_Layout(domain[2], til_reg_128k);
+ dsl[3] = new r_Domain_Storage_Layout(domain[3], til_reg_256k);
+
+ dsl[4] = new r_Domain_Storage_Layout(domain[4], til_int_32k);
+ dsl[5] = new r_Domain_Storage_Layout(domain[5], til_int_64k);
+ dsl[6] = new r_Domain_Storage_Layout(domain[6], til_int_128k);
+ dsl[7] = new r_Domain_Storage_Layout(domain[7], til_int_256k);
+
+
+ // Create cubes
+
+ r_Database db;
+ db.set_servername(server_name);
+
+ for ( i=0; i< TOTAL_CUBES ; i++)
+ {
+ r_Transaction trans;
+
+ r_Ref< r_Marray<r_ULong> > cube;
+
+ try
+ {
+ cout << "Opening database " << dbase_name << " on " << server_name
+ << "... " << flush;
+
+ db.open(dbase_name);
+
+ cout << "Ok" << endl;
+ cout << "Starting transaction... " << flush;
+
+ trans.begin();
+
+ cout << "Ok" << endl;
+ cout << "Opening the set... " << flush;
+
+ try
+ {
+ cube_set = db.lookup_object(colect_name);
+ }
+ catch (...)
+ {
+ cout << "*Failed*" << endl;
+ cout << "Creating the set... " << flush;
+
+ cube_set =
+ new(&db, "RGB_3D_Set") r_Set< r_Ref< r_Marray<RGBPixel> > >;
+
+ db.set_object_name(*cube_set, colect_name);
+ }
+
+ cout << "Ok" << endl;
+ cout << "Creating the datacube... " << flush;
+ r_Minterval newDomain( domain[i]);
+ cube =
+ new(&db, "RGB_3D_Cube") r_Marray<RGBPixel>(newDomain, dsl[i]);
+
+ cube_set->insert_element(cube);
+
+ cout << "Cube[" << i+1 << "]: " << cube->get_oid() << endl;
+ cout << "Spatial domain: " << cube->spatial_domain( ) <<endl;
+ cout << "Storage Layout " << endl;
+ dsl[i]->print_status( );
+
+ cout << "*" << flush;
+ cout << " ... Ok" << endl;
+ cout << "Commiting transaction... " << flush;
+
+ trans.commit();
+
+ cout << "Ok" << endl;
+ // cout << "Destroying cube... " <<flush;
+ // cube.destroy( );
+ cout << "Closing database... " << flush;
+ db.close();
+ }
+ catch (r_Error& e)
+ {
+ cout << e.what() << endl;
+ exit(0);
+ }
+ catch (...)
+ {
+ cout << "Undefined error..." << endl;
+ exit(0);
+ }
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ parse(argc, argv);
+ insert_datacube( );
+ return 0;
+}
+
+
+
+
+
+
+
+
diff --git a/rasodmg/test/test_bmark_pet.cc b/rasodmg/test/test_bmark_pet.cc
new file mode 100644
index 0000000..8fa94fb
--- /dev/null
+++ b/rasodmg/test/test_bmark_pet.cc
@@ -0,0 +1,235 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_bmark_pet.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: benchmark interest tiling
+ *
+ * COMMENTS:
+ * This program is used to load the database with information
+ * for benchmarking interesting tiling
+ *
+*/
+
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rasodmg/ref.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/odmgtypes.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/storagelayout.hh"
+#include "raslib/oid.hh"
+#include "include/basictypes.hh"
+
+#define S_32K (32 * 1024L)
+#define S_64K (64 * 1024L)
+#define S_128K (128 * 1024L)
+#define S_256K (256 * 1024L)
+
+#define TOTAL_CUBES 7
+#define SIZE_X 185L
+#define SIZE_Y 150L
+#define SIZE_Z 141L
+
+char* server_name;
+char* dbase_name;
+char* colect_name;
+
+void parse(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ cout << "Usage: " << argv[0] << " [server name] [db name] [colection name]"
+ << endl;
+
+ exit(0);
+ }
+
+ server_name = argv[1];
+ dbase_name = argv[2];
+ colect_name = argv[3];
+}
+
+void insert_datacube( )
+{
+
+ r_Ref< r_Set< r_Ref< r_Marray<r_Short> > > > cube_set;
+ r_Minterval domain[TOTAL_CUBES];
+ r_Domain_Storage_Layout* dsl[TOTAL_CUBES];
+ r_OId oid[TOTAL_CUBES];
+
+ for (int i = 0; i < TOTAL_CUBES; i++)
+ {
+ domain[i] = r_Minterval(3);
+ domain[i] << r_Sinterval(0L, SIZE_X - 1 )
+ << r_Sinterval(0L, SIZE_Y - 1)
+ << r_Sinterval(0L, SIZE_Z - 1);
+ }
+
+ // For aligned tiling (Regular tiling)
+
+ r_Minterval block_config(3);
+ block_config << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(0L, SIZE_Y)
+ << r_Sinterval(0L, SIZE_Z);
+
+ r_Aligned_Tiling* til_reg_32k = new r_Aligned_Tiling(block_config, S_32K);
+ r_Aligned_Tiling* til_reg_64k = new r_Aligned_Tiling(block_config, S_64K);
+ r_Aligned_Tiling* til_reg_128k = new r_Aligned_Tiling(block_config, S_128K);
+ r_Aligned_Tiling* til_reg_256k = new r_Aligned_Tiling(block_config, S_256K);
+ r_Aligned_Tiling* til_reg_64k1 = new r_Aligned_Tiling(block_config, S_64K);
+
+
+ // For areas of interest tiling
+ r_Minterval interest1_1("[23:170,4:75,12:138]");
+ r_Minterval interest1_2("[61:149,70:135,8:130]");
+ r_Minterval interest2_1("[28:175,2:73,8:134]");
+ r_Minterval interest2_2("[63:151,75:140,11:133]");
+
+
+ DList<r_Minterval> areas1;
+ areas1 += interest1_1;
+ areas1 += interest1_2;
+ DList<r_Minterval> areas2;
+ areas2 += interest2_1;
+ areas2 += interest2_2;
+
+ r_Interest_Tiling* til_int1 =
+ new r_Interest_Tiling(areas1, r_Interest_Tiling::NO_LIMIT);
+ r_Interest_Tiling* til_int2 =
+ new r_Interest_Tiling(areas2, r_Interest_Tiling::NO_LIMIT);
+
+ // Domain storage layouts
+
+ dsl[0] = new r_Domain_Storage_Layout(domain[0], til_reg_32k);
+ dsl[1] = new r_Domain_Storage_Layout(domain[1], til_reg_64k);
+ dsl[2] = new r_Domain_Storage_Layout(domain[2], til_reg_128k);
+ dsl[3] = new r_Domain_Storage_Layout(domain[3], til_reg_256k);
+
+ dsl[4] = new r_Domain_Storage_Layout(domain[4], til_int1);
+ dsl[5] = new r_Domain_Storage_Layout(domain[5], til_int2);
+ dsl[6] = new r_Domain_Storage_Layout(domain[6], til_reg_64k1);
+
+
+ // Create cubes
+
+ r_Database db;
+ db.set_servername(server_name);
+
+ for ( i=0; i< TOTAL_CUBES ; i++)
+ {
+ r_Transaction trans;
+
+ r_Ref< r_Marray<r_Short> > cube;
+
+ try
+ {
+ cout << "Opening database " << dbase_name << " on " << server_name
+ << "... " << flush;
+
+ db.open(dbase_name);
+
+ cout << "Ok" << endl;
+ cout << "Starting transaction... " << flush;
+
+ trans.begin();
+
+ cout << "Ok" << endl;
+ cout << "Opening the set... " << flush;
+
+ try
+ {
+ cube_set = db.lookup_object(colect_name);
+ }
+ catch (...)
+ {
+ cout << "*Failed*" << endl;
+ cout << "Creating the set... " << flush;
+
+ cube_set =
+ new(&db, "ShortSet3") r_Set< r_Ref< r_Marray<r_Short> > >;
+
+ db.set_object_name(*cube_set, colect_name);
+ }
+
+ cout << "Ok" << endl;
+ cout << "Creating the datacube... " << flush;
+ r_Minterval newDomain( domain[i]);
+ cube =
+ new(&db, "ShortCube") r_Marray<r_Short>(newDomain, dsl[i]);
+
+ cube_set->insert_element(cube);
+
+ cout << "Cube[" << i+1 << "]: " << cube->get_oid() << endl;
+ cout << "Spatial domain: " << cube->spatial_domain( ) <<endl;
+ cout << "Storage Layout " << endl;
+ dsl[i]->print_status( );
+
+ cout << "*" << flush;
+ cout << " ... Ok" << endl;
+ cout << "Commiting transaction... " << flush;
+
+ trans.commit();
+
+ cout << "Ok" << endl;
+ // cout << "Destroying cube... " <<flush;
+ // cube.destroy( );
+ cout << "Closing database... " << flush;
+ db.close();
+ }
+ catch (r_Error& e)
+ {
+ cout << e.what() << endl;
+ exit(0);
+ }
+ catch (...)
+ {
+ cout << "Undefined error..." << endl;
+ exit(0);
+ }
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ parse(argc, argv);
+ insert_datacube( );
+ return 0;
+}
+
+
+
+
+
+
+
+
diff --git a/rasodmg/test/test_bmark_stat.cc b/rasodmg/test/test_bmark_stat.cc
new file mode 100644
index 0000000..2c5b776
--- /dev/null
+++ b/rasodmg/test/test_bmark_stat.cc
@@ -0,0 +1,331 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_bmark_stat.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: Load database for statistic tiling benchmark
+ *
+ * COMMENTS:
+ * None
+*/
+
+/*
+ ATENTION: The format of the input file for using with this program is:
+
+ border_threshold accesses_threshold tilesize domain
+ access1
+ access2
+ accessXXX
+ ...
+
+ Example:
+
+ 50 0.20 1000 [0:799, 0:599]
+ [10:20, 30:40]
+ [12:20, 35:39]
+ [100:300, 300:400]
+ [120:300, 310:410]
+ [200:500, 350:500]
+ [200:510, 350:500]
+*/
+
+
+#include <iostream>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "raslib/oid.hh"
+#include "raslib/dlist.hh"
+#include "raslib/minterval.hh"
+#include "raslib/sinterval.hh"
+#include "rasodmg/ref.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/odmgtypes.hh"
+#include "rasodmg/stattiling.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/storagelayout.hh"
+#include "RGBCube.hh"
+
+#define S_32K (32 * 1024L)
+#define S_64K (64 * 1024L)
+#define S_128K (128 * 1024L)
+#define S_256K (256 * 1024L)
+
+#define TOTAL_CUBES 8
+#define SIZE_X 120L
+#define SIZE_Y 159L
+#define SIZE_Z 119L
+
+char* filename;
+char* server_name;
+char* dbase_name;
+char* colect_name;
+int cube_i;
+
+DList<r_Access> stat_info;
+unsigned int border_threshold;
+double interesting_threshold;
+unsigned long tile_size;
+r_Minterval* domain;
+
+void parse(int argc, char* argv[])
+{
+ if (argc != 6)
+ {
+ cout << "Usage: " << argv[0] << " server db collec ptfile cube" << endl;
+ cout << endl;
+ cout << " server ............. server to use" << endl;
+ cout << " db ................. database" << endl;
+ cout << " collec ............. collection" << endl;
+ cout << " ptfile ............. pattern file" << endl;
+ cout << " cube ............... datacube to create" << endl;
+
+ exit(1);
+ }
+
+ server_name = argv[1];
+ dbase_name = argv[2];
+ colect_name = argv[3];
+ filename = argv[4];
+ cube_i = atoi(argv[5]);
+
+ if ((cube_i<0) || (cube_i>7))
+ {
+ cout << "Invalid datacube. Must be in 0..7" << endl;
+ exit(0);
+ }
+}
+
+void read_data()
+{
+ const unsigned int BUF_SIZE = 256;
+ char buf[BUF_SIZE], buf2[BUF_SIZE];
+
+ cout << "Opening " << filename << " for reading... ";
+
+ ifstream is(filename, ios::in);
+ if (!is)
+ {
+ cout << "Couldn't open!!!" << endl;
+ exit(1);
+ }
+ else
+ cout << "done." << endl;
+
+ cout << "Reading parameters... ";
+
+ is >> border_threshold;
+ is >> interesting_threshold;
+ is >> tile_size;
+
+ is.getline(buf, BUF_SIZE);
+ domain = new r_Minterval(buf);
+
+ cout << "done." << endl;
+ cout << "Geting the accesses... ";
+
+ unsigned long count = 0;
+
+ while (!is.eof())
+ {
+ is.getline(buf, BUF_SIZE);
+ if (sscanf(buf, "%s", buf2) == 1)
+ {
+ r_Minterval inter(buf);
+ stat_info += inter;
+ ++count;
+
+ cout << "*";
+ }
+ }
+
+ is.close();
+
+ cout << endl;
+ cout << "Geting the accesses... done." << endl << endl;
+
+ cout << "Border threshold = " << border_threshold << endl;
+ cout << "Interesting threshold = " << interesting_threshold << endl;
+ cout << "Tile size = " << tile_size << endl;
+ cout << "Domain = " << *domain << endl;
+ cout << "Number of accesses = " << count << endl << endl;
+}
+
+
+void insert_datacube()
+{
+
+ r_Ref< r_Set< r_Ref< r_Marray<r_ULong> > > > cube_set;
+ r_Minterval domain;
+
+ domain = r_Minterval(3);
+ domain << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(0L, SIZE_Y)
+ << r_Sinterval(0L, SIZE_Z);
+
+
+ // For alligned tiling (Regular tiling)
+
+ r_Minterval block_config(3);
+ block_config << r_Sinterval(0L, SIZE_X)
+ << r_Sinterval(0L, SIZE_Y)
+ << r_Sinterval(0L, SIZE_Z);
+
+ unsigned long ts;
+ switch (cube_i)
+ {
+ case 0:
+ ts = S_32K;
+ break;
+ case 1:
+ ts = S_64K;
+ break;
+ case 2:
+ ts = S_128K;
+ break;
+ case 3:
+ ts = S_256K;
+ break;
+ default: // Irrelevant, not used.
+ ts = S_32K;
+ break;
+ }
+
+ r_Aligned_Tiling til_reg(block_config, ts);
+ r_Stat_Tiling til_stat(border_threshold, interesting_threshold, tile_size);
+
+ if (cube_i > 3)
+ {
+ til_stat.update_stat_information(stat_info);
+ }
+
+
+ // Domain storage layout
+
+ // This is a hack due to problems with the pointers
+ r_Domain_Storage_Layout* dsl[2];
+ r_Domain_Storage_Layout* use;
+
+ dsl[0] = new r_Domain_Storage_Layout(domain, &til_reg);
+ dsl[1] = new r_Domain_Storage_Layout(domain, &til_stat);
+
+ if (cube_i<4)
+ use = dsl[0];
+ else
+ use = dsl[1];
+
+ // Create cube
+
+ r_Database db;
+ db.set_servername(server_name);
+ r_Transaction trans;
+ r_Ref< r_Marray<r_ULong> > cube;
+
+ try
+ {
+ cout << "Opening database " << dbase_name << " on " << server_name
+ << "... " << flush;
+
+ db.open(dbase_name);
+
+ cout << "Ok" << endl;
+ cout << "Starting transaction... " << flush;
+
+ trans.begin();
+
+ cout << "Ok" << endl;
+ cout << "Opening the set... " << flush;
+
+ try
+ {
+ cube_set = db.lookup_object(colect_name);
+ }
+ catch (...)
+ {
+ cout << "*Failed*" << endl;
+ cout << "Creating the set... " << flush;
+
+ cube_set =
+ new(&db, "RGB_3D_Set") r_Set< r_Ref< r_Marray<RGBPixel> > >;
+
+ db.set_object_name(*cube_set, colect_name);
+ }
+
+ cout << "Ok" << endl;
+ cout << "Creating the datacube... " << flush;
+
+ cube =
+ new(&db, "RGB_3D_Cube") r_Marray<RGBPixel>(domain, use);
+
+ cube_set->insert_element(cube);
+
+ cout << "*" << flush;
+ cout << " ... Ok" << endl;
+ cout << "Commiting transaction... " << flush;
+
+ trans.commit();
+
+ cout << "Ok" << endl;
+ cout << "Closing database... " << flush;
+
+ db.close();
+
+ cout << " Ok" << endl << flush;
+ }
+ catch (r_Error& e)
+ {
+ cout << e.what() << endl;
+ exit(0);
+ }
+ catch (...)
+ {
+ cout << "Undefined error..." << endl;
+ exit(0);
+ }
+}
+
+
+int main(int argc, char* argv[])
+{
+ parse(argc, argv);
+ read_data();
+ insert_datacube();
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rasodmg/test/test_breakdown.cc b/rasodmg/test/test_breakdown.cc
new file mode 100644
index 0000000..41f4f65
--- /dev/null
+++ b/rasodmg/test/test_breakdown.cc
@@ -0,0 +1,112 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_breakdown.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: Simulates a connection breakdown with an open database and a
+ * unfinished transaction.
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <iostream>
+#include <string.h>
+#include <stdlib.h> // for exit()
+
+#include "rasodmg/ref.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+
+int main( int ac, char** av )
+{
+ char servername[255];
+ char baseName[255];
+ char collName[255];
+
+ if( ac>1 )
+ strcpy( servername, av[1] );
+ else
+ strcpy( servername, "hpwibas5" );
+
+ if( ac > 2 )
+ strcpy( baseName, av[2] );
+ else
+ strcpy( baseName, "RasDaBase" );
+
+ if( ac > 3 )
+ strcpy( collName, av[3] );
+ else
+ strcpy( collName, "Images" );
+
+ cout << endl << endl;
+ cout << "ODMG conformant insertion of Marrays" << endl;
+ cout << "====================================" << endl << endl;
+
+ r_Database db;
+ r_Transaction ta;
+ r_Ref< r_Set< r_Ref< r_Marray<int> > > > image_set;
+ r_Ref< r_Marray<int> > image;
+ r_Minterval domain;
+
+ domain = r_Minterval(2) << r_Sinterval( 0, 10 ) << r_Sinterval( 0, 10 );
+
+ db.set_servername( servername );
+
+ cout << "Opening Database on " << servername << "... "; cout.flush();
+ db.open( baseName );
+ cout << "OK" << endl;
+
+ cout << "Starting Transaction ... "; cout.flush();
+ ta.begin();
+ cout << "OK" << endl;
+
+ cout << "Creating a persistent set with two images ..."; cout.flush();
+
+ // create the set
+ image_set = new( &db ) r_Set< r_Ref< r_Marray<int> > >;
+
+ // create a name for the set
+ db.set_object_name( *image_set, collName );
+
+ // create first image
+ image = new( &db ) r_Marray<int>( domain, 0 );
+
+ // put in into the persistent list
+ image_set->insert_element( image );
+
+ //
+ // *** POW! CONNECTION BREAKDOWN! ***
+ //
+ cout << endl << "*** POW! CONNECTION BREAKDOWN! ***" << endl;
+ exit( 0 );
+}
diff --git a/rasodmg/test/test_collection.cc b/rasodmg/test/test_collection.cc
new file mode 100644
index 0000000..d668a89
--- /dev/null
+++ b/rasodmg/test/test_collection.cc
@@ -0,0 +1,116 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_collection.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <iostream>
+#include "rasodmg/collection.hh"
+#include "rasodmg/iterator.hh"
+#include "rasodmg/ref.hh"
+
+int main()
+{
+ int v,x,y,z,d;
+
+ v = 100;
+ x = 200;
+ y = 100;
+ z = 300;
+ d = 500;
+
+ cout << endl << endl;
+ cout << "Collection Examples" << endl;
+ cout << "====================" << endl << endl;
+
+ cout << "Creating r_Collection of type int." <<endl;
+ r_Collection< r_Ref_Any > a;
+ r_Iterator< r_Ref_Any > iter;
+
+ cout << "Cardinality of empty collection 'a': " << a.cardinality() << endl << endl;
+
+ cout << "Now inserting four elements:" << endl << "v = 100" << endl;
+ a.insert_element( &v );
+
+ cout << "x = 200" << endl;
+ a.insert_element( &x );
+
+ cout << "y = 100 (should work in collections)" << endl;
+ a.insert_element( &y );
+
+ cout << "z = 300" << endl;
+ a.insert_element( &z );
+
+ cout << "Cardinality of collection 'a' after four inserts: " << a.cardinality() << endl << endl;
+
+ cout << "Elements: " << flush;
+ for( iter = a.create_iterator(); iter.not_done(); iter++ )
+ cout << (*iter) << ", " << flush;
+ cout << endl;
+
+ cout << "Does 'a' contain element '100' (1=TRUE/0=FALSE)? " << a.contains_element(&y) << endl;
+
+ cout << "Does 'a' contain element '500' (1=TRUE/0=FALSE)? " << a.contains_element(&d) << endl << endl;
+
+ cout << "Now removing element 'x=200' from 'a'." << endl;
+ a.remove_element(&x);
+ cout << "Cardinality of 'a' now: " << a.cardinality() << endl << endl;
+
+ cout << "Now removing element '100' from 'a'." << endl;
+ a.remove_element(&y);
+ cout << "Cardinality of 'a' now: " << a.cardinality() << endl << endl;
+
+ cout << "Now removing (non-existing) element '500' from 'a'." << endl;
+ a.remove_element(&d);
+ cout << "Cardinality of 'a' now: " << a.cardinality() << endl << endl;
+
+ cout << "Elements: " << flush;
+ for( iter = a.create_iterator(); iter.not_done(); iter++ )
+ cout << (*iter) << ", " << flush;
+ cout << endl;
+
+ cout << "Testing assignment operator on r_Collections." << endl << "(creating r_Collection 'b' that is equal to 'a'.)" <<endl;
+ r_Collection< r_Ref_Any > b;
+ b = a;
+ cout << "Cardinality of 'b': " << b.cardinality() << endl << endl;
+
+ cout << "Testing copy constructor of r_Collection." << endl << "(creating r_Collection 'c' that is equal to 'a'.)" <<endl;
+ r_Collection< r_Ref_Any > c(a);
+ cout << "Cardinality of 'c': " << c.cardinality() << endl << endl;
+
+ cout << "Now removing all elements from 'a'." << endl;
+ a.remove_all();
+ cout << "Cardinality of 'a' now: " << a.cardinality() << endl;
+ cout << "Cardinality of 'b' is still: " << b.cardinality() << endl;
+ cout << "Cardinality of 'c' is still: " << c.cardinality() << endl << endl;
+}
diff --git a/rasodmg/test/test_comp_conv.sh b/rasodmg/test/test_comp_conv.sh
new file mode 100644
index 0000000..5f6e2c6
--- /dev/null
+++ b/rasodmg/test/test_comp_conv.sh
@@ -0,0 +1,325 @@
+#!/bin/ksh
+#constants sections
+TEST_TIME=$(date +%d.%b.%Y_%H:%M)
+TEST_DIR=$RMANHOME/rasodmg/test
+SYSTEM_INSERT=$TEST_DIR/system_insert
+SYSTEM_QUERY=$TEST_DIR/system_query
+DEFDIFF=$TEST_DIR/defdiff
+QUERYFILE=/tmp/query.ql
+LOGFILE=$PWD/$0_log
+IMG_DIR=$TEST_DIR/images
+INIMGFILE=$IMG_DIR/x1
+OUTIMGFILE=$IMG_DIR/out
+FAILIMGFILE=$IMG_DIR/fails/out
+REALIMGFILE="$OUTIMGFILE"1
+set -A CONVERSION Array TIFF JPEG HDF PNG BMP VFF
+set -A CONVERSIONEXT raw tif jpg hdf png bmp vff
+#AutoCompression not implemented ask Andeas?
+COMPRESSION="Array ZLib RLE HaarWavelet DaubechiesWavelet SepZLib \
+ SepRLE Daubechies6Wavelet Daubechies8Wavelet Daubechies10Wavelet Daubechies12Wavelet \
+ Daubechies14Wavelet Daubechies16Wavelet Daubechies18Wavelet Daubechies20Wavelet \
+ LeastAsym8Wavelet LeastAsym10Wavelet LeastAsym12Wavelet LeastAsym14Wavelet \
+ LeastAsym16Wavelet LeastAsym18Wavelet LeastAsym20Wavelet Coiflet6Wavelet \
+ Coiflet12Wavelet Coiflet18Wavelet Coiflet24Wavelet Coiflet30Wavelet QHaarWavelet"
+DEBUG=0
+SERVER=$HOSTNAME
+DATABASE=RASBASE
+USER=rasguest
+PASSWD=rasguest
+COLLNAME=pipi
+SETTYPE=BoolSet
+MDDTYPE=BoolImage
+MDDDOMAIN=[0:624,0:899]
+
+#function used
+error() {
+ echo "$1 !"
+ exit 1
+}
+
+log() {
+ echo "$1" >>$LOGFILE
+}
+
+print_options() {
+echo "RasDaMan (s)erver host ..... $SERVER"
+echo "RasDaMan (d)atabase ..... $DATABASE"
+echo "RasDaMan (u)ser ..... $USER"
+echo "Test Colle(c)tion ..... $COLLNAME"
+echo "Test Set T(y)pe ..... $SETTYPE"
+echo "Test MDD (T)ype ..... $MDDTYPE"
+echo "Test MDD D(o)main ..... $MDDDOMAIN"
+echo "Start Con(v)ersion Test"
+echo "Start Com(p)ression Test"
+echo "(E)xit Test"
+}
+
+check_options() {
+ option=""
+ if(test "$1" = "s"); then
+ while(test -z "$option"); do
+ echo "RasDaMan Server Host: \c"
+ read option
+ done
+ SERVER=$option
+ elif (test "$1" = "d"); then
+ while(test -z "$option"); do
+ echo "RasDaMan Database: \c"
+ read option
+ done
+ DATABASE=$option
+ elif (test "$1" = "u"); then
+ while(test -z "$option"); do
+ echo "RasDaMan User: \c"
+ read option
+ done
+ USER=$option
+ option=""
+ while(test -z "$option"); do
+ echo "Password: \c"
+ read option
+ done
+ PASSWD=$option
+ elif (test "$1" = "c"); then
+ while(test -z "$option"); do
+ echo "Test Collection: \c"
+ read option
+ done
+ COLLNAME=$option
+ elif (test "$1" = "y"); then
+ while(test -z "$option"); do
+ echo "Test SetType: \c"
+ read option
+ done
+ SETTYPE=$option
+ elif (test "$1" = "t"); then
+ while(test -z "$option"); do
+ echo "MDD Type: \c"
+ read option
+ done
+ MDDTYPE=$option
+ elif (test "$1" = "o"); then
+ while(test -z "$option"); do
+ echo "MDD Domain: \c"
+ read option
+ done
+ MDDDOMAIN=$option
+ elif (test "$1" = "p"); then
+ echo "All set, get ready for compression test, go!"
+ execute_compression_test
+ elif (test "$1" = "v"); then
+ echo "All set, get ready for conversion test, go!"
+ execute_conversion_test
+ else
+ echo "Please choose a valid option!"
+ fi
+}
+
+
+
+
+execute_compression_test() {
+SELECTQUERY="select a from $COLLNAME as a"
+CREATEQUERY="create collection $COLLNAME $SETTYPE"
+DELETEQUERY="delete from $COLLNAME where true"
+
+SYSTEM_INSERT_ARGS="-s $SERVER -u $USER -p $PASSWD --dbname $DATABASE --collection $COLLNAME --mddtype $MDDTYPE --mdddomain $MDDDOMAIN"
+SYSTEM_QUERY_ARGS="-s $SERVER -u $USER -p $PASSWD --dbname $DATABASE"
+
+#creates collection
+rm -rf $LOGFILE
+log "Compression Test stated on $TEST_TIME"
+log "-creating collection $COLLNAME SETTYPE"
+echo "$CREATEQUERY" > $QUERYFILE
+if (test $DEBUG -ne 0); then
+ log "$SYSTEM_QUERY $SYSTEM_QUERY_ARGS -r $QUERYFILE"
+fi
+$SYSTEM_QUERY $SYSTEM_QUERY_ARGS -r $QUERYFILE 1>>$LOGFILE 2>&1
+if ( test $? -ne 0 ); then
+ #deletes all mdd from collection from current collection
+ log "-deleting all image from $COLLNAME collection"
+ echo "$DELETEQUERY" > $QUERYFILE
+ if (test $DEBUG -ne 0); then
+ log "$SYSTEM_QUERY $SYSTEM_QUERY_ARGS -r $QUERYFILE"
+ fi
+ $SYSTEM_QUERY $SYSTEM_QUERY_ARGS -r $QUERYFILE 1>>$LOGFILE 2>&1
+ if ( test $? -ne 0 ); then
+ error "An Error occured please check the log file $LOGFILE"
+ fi
+fi
+
+k=1
+informat=${CONVERSION[0]}
+informatext=${CONVERSIONEXT[0]}
+
+for storage in $COMPRESSION; do
+ for transfer in $COMPRESSION; do
+ #insert the data in db
+ log "--inserting $INIMGFILE.$informatext with tranfer $transfer mode and storage $storage mode in $COLLNAME"
+ if (test $DEBUG -ne 0); then
+ log "$SYSTEM_INSERT $SYSTEM_INSERT_ARGS \n--storageformat $storage --transformat $transfer \
+ --inputformat $informat -r $INIMGFILE.$informatext"
+ fi
+ $SYSTEM_INSERT $SYSTEM_INSERT_ARGS --storageformat $storage --transformat $transfer \
+ --inputformat $informat -r $INIMGFILE.$informatext 1>>$LOGFILE 2>&1
+ if ( test $? -eq 0 ); then
+ #checks if what is in db is correct compared with DEF input
+ outformat=$informat
+ outformatext=$informatext
+ log "---retriving data for tranfer $transfer mode in output $outformat mode"
+ echo "$SELECTQUERY" > $QUERYFILE
+ if (test $DEBUG -ne 0); then
+ log "$SYSTEM_QUERY $SYSTEM_QUERY_ARGS --transformat $transfer --outputformat $outformat \
+ --outputfilename $OUTIMGFILE -r $QUERYFILE"
+ fi
+ $SYSTEM_QUERY $SYSTEM_QUERY_ARGS --transformat $transfer --outputformat $outformat \
+ --outputfilename $OUTIMGFILE -r $QUERYFILE 1>>$LOGFILE 2>&1
+ if ( test $? -ne 0 ); then
+ error "An Error occured please check the log file $LOGFILE"
+ fi
+
+ #comparing files src.outformatext with realfile.outformatext
+ $DEFDIFF --srcfilename $INIMGFILE.$informatext --srcformat $informat \
+ --destfilename $REALIMGFILE.$outformatext --destformat $outformat 1>>$LOGFILE 2>&1
+ if (test $? -eq 0); then
+ echo "$k-DEFIN=$informat TRANSFER=$transfer STORAGE=$storage DEFOUT=$outformat OK"
+ log "---$k-DEFIN=$informat TRANSFER=$transfer STORAGE=$storage DEFOUT=$outformat OK"
+ else
+ echo "$k-DEFIN=$informat TRANSFER=$transfer STORAGE=$storage DEFOUT=$outformat FAILED"
+ log "---$k-DEFIN=$informat TRANSFER=$transfer STORAGE=$storage DEFOUT=$outformat FAILED"
+ #keep the file for futher analysis
+ mv $REALIMGFILE.$outformatext $FAILIMGFILE$k.$outformatext
+ fi
+
+ #deletes all mdd from collection
+ log "--deleting current image"
+ echo "$DELETEQUERY" > $QUERYFILE
+ if (test $DEBUG -ne 0); then
+ log "$SYSTEM_QUERY $SYSTEM_QUERY_ARGS --transformat $transfer -r $QUERYFILE"
+ fi
+ $SYSTEM_QUERY $SYSTEM_QUERY_ARGS --transformat $transfer -r $QUERYFILE 1>>$LOGFILE 2>&1
+ if ( test $? -ne 0 ); then
+ error "An Error occured please check the log file $LOGFILE"
+ fi
+ else
+ error "An Error occured please check the log file $LOGFILE"
+ fi
+ k=$(($k+1))
+ done
+done
+}
+
+execute_conversion_test() {
+SELECTQUERY="select a from $COLLNAME as a"
+CREATEQUERY="create collection $COLLNAME $SETTYPE"
+DELETEQUERY="delete from $COLLNAME where true"
+
+SYSTEM_INSERT_ARGS="-s $SERVER -u $USER -p $PASSWD --dbname $DATABASE --collection $COLLNAME --mddtype $MDDTYPE --mdddomain $MDDDOMAIN"
+SYSTEM_QUERY_ARGS="-s $SERVER -u $USER -p $PASSWD --dbname $DATABASE"
+
+#creates collection
+rm -rf $LOGFILE
+log "Conversion Test stated on $TEST_TIME"
+log "-creating collection $COLLNAME SETTYPE"
+echo "$CREATEQUERY" > $QUERYFILE
+if (test $DEBUG -ne 0); then
+ log "$SYSTEM_QUERY $SYSTEM_QUERY_ARGS -r $QUERYFILE"
+fi
+$SYSTEM_QUERY $SYSTEM_QUERY_ARGS -r $QUERYFILE 1>>$LOGFILE 2>&1
+if ( test $? -ne 0 ); then
+ #deletes all mdd from collection from current collection
+ log "-deleting all image from $COLLNAME collection"
+ echo "$DELETEQUERY" > $QUERYFILE
+ if (test $DEBUG -ne 0); then
+ log "$SYSTEM_QUERY $SYSTEM_QUERY_ARGS -r $QUERYFILE"
+ fi
+ $SYSTEM_QUERY $SYSTEM_QUERY_ARGS -r $QUERYFILE 1>>$LOGFILE 2>&1
+ if ( test $? -ne 0 ); then
+ error "An Error occured please check the log file $LOGFILE"
+ fi
+fi
+
+i=0
+k=1
+n=${#CONVERSION[*]}
+transfer=Array
+storage=Array
+
+while (test i -lt n); do
+ informat=${CONVERSION[$i]}
+ informatext=${CONVERSIONEXT[$i]}
+ #insert the data in db
+ log "--inserting $INIMGFILE.$informatext with tranfer $transfer mode and storage $storage mode in $COLLNAME"
+ if (test $DEBUG -ne 0); then
+ log "$SYSTEM_INSERT $SYSTEM_INSERT_ARGS \n--storageformat $storage --transformat $transfer \
+ --inputformat $informat -r $INIMGFILE.$informatext"
+ fi
+ $SYSTEM_INSERT $SYSTEM_INSERT_ARGS --storageformat $storage --transformat $transfer \
+ --inputformat $informat -r $INIMGFILE.$informatext 1>>$LOGFILE 2>&1
+ if ( test $? -eq 0 ); then
+ #checks if what is in db is correct compared with DEF input
+ j=0
+ while (test j -lt n); do
+ outformat=${CONVERSION[$j]}
+ outformatext=${CONVERSIONEXT[$j]}
+ log "---retriving data for tranfer $transfer mode in output $outformat mode"
+ echo "$SELECTQUERY" > $QUERYFILE
+ if (test $DEBUG -ne 0); then
+ log "$SYSTEM_QUERY $SYSTEM_QUERY_ARGS --transformat $transfer --outputformat $outformat \
+ --outputfilename $OUTIMGFILE -r $QUERYFILE"
+ fi
+ $SYSTEM_QUERY $SYSTEM_QUERY_ARGS --transformat $transfer --outputformat $outformat \
+ --outputfilename $OUTIMGFILE -r $QUERYFILE 1>>$LOGFILE 2>&1
+ if ( test $? -ne 0 ); then
+ error "An Error occured please check the log file $LOGFILE"
+ fi
+ #comparing files src.outformatext with realfile.outformatext
+ $DEFDIFF --srcfilename $INIMGFILE.$informatext --srcformat $informat \
+ --destfilename $REALIMGFILE.$outformatext --destformat $outformat 1>>$LOGFILE 2>&1
+ if (test $? -eq 0); then
+ echo "$k-DEFIN=$informat TRANSFER=$transfer STORAGE=$storage DEFOUT=$outformat OK"
+ log "---$k-DEFIN=$informat TRANSFER=$transfer STORAGE=$storage DEFOUT=$outformat OK"
+ else
+ echo "$k-DEFIN=$informat TRANSFER=$transfer STORAGE=$storage DEFOUT=$outformat FAILED"
+ log "---$k-DEFIN=$informat TRANSFER=$transfer STORAGE=$storage DEFOUT=$outformat FAILED"
+ #keep the file for futher analysis
+ mv $REALIMGFILE.$outformatext $FAILIMGFILE$k.$outformatext
+ fi
+ j=$(($j+1))
+ k=$(($k+1))
+ done
+ #deletes all mdd from collection
+ log "--deleting current image"
+ echo "$DELETEQUERY" > $QUERYFILE
+ if (test $DEBUG -ne 0); then
+ log "$SYSTEM_QUERY $SYSTEM_QUERY_ARGS --transformat $transfer -r $QUERYFILE"
+ fi
+ $SYSTEM_QUERY $SYSTEM_QUERY_ARGS --transformat $transfer -r $QUERYFILE 1>>$LOGFILE 2>&1
+ if ( test $? -ne 0 ); then
+ error "An Error occured please check the log file $LOGFILE"
+ fi
+ else
+ error "An Error occured please check the log file $LOGFILE"
+ fi
+ i=$(($i+1))
+done
+}
+
+echo "Conversion & Compression Test - Main Menu"
+
+opt="s"
+while ( test "$opt" != "e"); do
+ print_options
+ echo "Change settings/Start Test/Exit?\c"
+ read opt
+ if (test "$opt" = "E"); then
+ opt="e"
+ fi
+ if (test "$opt" = "e"); then
+ echo "Exiting ..."
+ exit 0
+ else
+ check_options $opt
+ fi
+done
+
diff --git a/rasodmg/test/test_db2blob.sqC b/rasodmg/test/test_db2blob.sqC
new file mode 100644
index 0000000..a77a168
--- /dev/null
+++ b/rasodmg/test/test_db2blob.sqC
@@ -0,0 +1,399 @@
+// -*-C++-*- (for Emacs)
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************
+ *
+ * SOURCE: test_db2blob.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE:
+ *
+ * COMMENTS:
+ *
+ ************************************************************/
+
+#ifdef LINUX
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream.h>
+#endif
+
+#include <iostream.h>
+#include <fstream.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h> // for drand48()
+
+#include "rasodmg/marray.hh"
+#include "raslib/shhopt.h"
+
+#include <sys/time.h>
+
+#include "sql.h"
+
+// number of repetitions for each query
+unsigned long repeat = 20;
+
+static int printFlag = 0;
+
+EXEC SQL INCLUDE SQLCA;
+
+#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0)
+
+// copied from DB2 example program
+int check_error (char eString[], struct sqlca *caPointer) {
+ char eBuffer[1024];
+ char sBuffer[1024];
+ short rc, Erc;
+
+ if (caPointer->sqlcode != 0) {
+ printf ("--- error report ---\n");
+ printf ("ERROR occured : %s.\nSQLCODE : %ld\n", eString,
+ caPointer->sqlcode);
+
+ /**********************\
+ * GET SQLSTATE MESSAGE *
+ \**********************/
+ rc = sqlogstt (sBuffer, 1024, 80, caPointer->sqlstate);
+
+ /******************************\
+ * GET ERROR MESSAGE API called *
+ \******************************/
+ Erc = sqlaintp (eBuffer, 1024, 80, caPointer);
+
+ /* return code is the length of the eBuffer string */
+ if (Erc > 0) printf ("%s", eBuffer);
+
+ if (caPointer->sqlcode < 0) {
+ if (rc == 0) {
+ printf ("\n%s", sBuffer);
+ }
+ printf ("--- end error report ---\n");
+ return 1;
+ } else {
+ /* errorCode is just a Warning message */
+ if (rc == 0) {
+ printf ("\n%s", sBuffer);
+ }
+ printf ("--- end error report ---\n");
+ printf ("WARNING - CONTINUING PROGRAM WITH WARNINGS!\n");
+ return 0;
+ } /* endif */
+ } /* endif */
+ return 0;
+}
+
+class BMTimer
+{
+public:
+ /// constructor, initializes members
+ inline BMTimer();
+
+ inline void start();
+ inline void stop();
+
+private:
+ /// reference parameter for gettimeofday().
+ timeval acttime;
+ // reference parameter for gettimeofday, not used.
+ static struct timezone dummy;
+ /// used to calculate time spent in function.
+ static long oldsec;
+ /// used to calculate time spent in function.
+ static long oldusec;
+};
+
+struct timezone BMTimer::dummy;
+long BMTimer::oldsec;
+long BMTimer::oldusec;
+
+inline
+BMTimer::BMTimer()
+{
+ oldsec = 0;
+ oldusec = 0;
+}
+
+inline void
+BMTimer::start()
+{
+ gettimeofday(&acttime, &dummy);
+}
+
+inline void
+BMTimer::stop()
+{
+ oldsec = acttime.tv_sec;
+ oldusec = acttime.tv_usec;
+ gettimeofday(&acttime, &dummy);
+ cout << (acttime.tv_sec-oldsec)*1000000 + acttime.tv_usec
+ - oldusec << "us";
+}
+
+BMTimer myTimer;
+
+r_Marray<char>*
+blobRead(r_Minterval& sd)
+{
+ EXEC SQL BEGIN DECLARE SECTION;
+ long beginLoc;
+ long endLoc;
+ SQL TYPE IS BLOB_LOCATOR tomoLoc;
+ short tomo_ind;
+ // buf will be a structure with a char[] element called data and
+ // an unsigned long called length
+ SQL TYPE IS BLOB(256) blobBuf;
+ EXEC SQL END DECLARE SECTION;
+
+ int i,j;
+ // storing result
+ r_Marray<char>* result = new r_Marray<char>(sd);
+ char* resBuf = result->get_array();
+
+ EXEC SQL CONNECT TO sample;
+
+ myTimer.start();
+
+ EXEC SQL DECLARE curs1 CURSOR FOR
+ SELECT blob_col
+ FROM tomo_blob;
+
+ EXEC SQL OPEN curs1;
+
+ EXEC SQL FETCH curs1 INTO :tomoLoc :tomo_ind;
+ if (SQLCODE != 0) {
+ cout << "FETCH curs1: " << SQLCODE << endl;
+ }
+
+ if(tomo_ind < 0)
+ cout << "No BLOB there!" << endl;
+
+ // iterating through the Minterval
+ for(i=sd[0].low(); i<=sd[0].high(); i++) {
+ for(j=sd[1].low(); j<=sd[1].high(); j++) {
+ beginLoc = sd[2].low() + j*256 + i*256*256;
+ endLoc = sd[2].high() + j*256 + i*256*256;
+ unsigned long rowSize = endLoc - beginLoc + 1;
+ EXEC SQL VALUES (SUBSTR( :tomoLoc, :beginLoc, :endLoc - :beginLoc + 1))
+ INTO :blobBuf;
+ memcpy(resBuf, blobBuf.data, rowSize);
+ resBuf += rowSize;
+ }
+ }
+
+ EXEC SQL CLOSE curs1;
+
+ myTimer.stop();
+
+ EXEC SQL CONNECT RESET;
+
+ return result;
+}
+
+r_Marray<char>*
+blob1DRead(float sel)
+{
+ EXEC SQL BEGIN DECLARE SECTION;
+ long beginLoc2;
+ long endLoc2;
+ SQL TYPE IS BLOB_LOCATOR tomoLoc2;
+ short tomo_ind2;
+ // buf will be a structure with a char[] element called data and
+ // an unsigned long called length
+ SQL TYPE IS BLOB(4000000) blobBuf2;
+ EXEC SQL END DECLARE SECTION;
+
+ int i,j;
+ // storing result
+ r_Minterval* sd_res;
+ sd_res = new r_Minterval("[0:255,0:255,0:153]");
+ r_Marray<char>* result = new r_Marray<char>(*sd_res);
+ char* resBuf = result->get_array();
+
+ EXEC SQL CONNECT TO sample;
+
+ EXEC SQL DECLARE curs2 CURSOR FOR
+ SELECT blob_col
+ FROM tomo_blob;
+
+ EXEC SQL OPEN curs2;
+
+ EXEC SQL FETCH curs2 INTO :tomoLoc2 :tomo_ind2;
+ if (SQLCODE != 0) {
+ cout << "FETCH curs2: " << SQLCODE << endl;
+ }
+ if(tomo_ind2 < 0)
+ cout << "No BLOB there!" << endl;
+
+ unsigned long rowSize = (int)(sel/100 * 10092544);
+ beginLoc2 = (int)(drand48() * (10092544 - rowSize));
+ endLoc2 = beginLoc2 + rowSize;
+
+ EXEC SQL VALUES (SUBSTR( :tomoLoc2, :beginLoc2, :endLoc2 - :beginLoc2 + 1))
+ INTO :blobBuf2;
+
+ memcpy(resBuf, blobBuf2.data, rowSize);
+ resBuf += rowSize;
+
+ EXEC SQL CLOSE curs2;
+
+ EXEC SQL CONNECT RESET;
+
+ delete sd_res;
+ return result;
+}
+
+void
+blobInsert( char *fileName )
+{
+ EXEC SQL BEGIN DECLARE SECTION;
+ SQL TYPE IS BLOB_FILE tomoFile;
+ EXEC SQL END DECLARE SECTION;
+
+ EXEC SQL CONNECT TO sample;
+ CHECKERR ("CONNECT TO") exit(1);
+
+ strcpy(tomoFile.name, fileName);
+ tomoFile.name_length = strlen(fileName);
+ tomoFile.file_options = SQL_FILE_READ;
+
+ EXEC SQL INSERT INTO tomo_blob
+ VALUES(:tomoFile);
+ CHECKERR ("INSERT INTO") exit(1);
+
+ EXEC SQL CONNECT RESET;
+}
+
+void
+blob1DExec(int queryNum, float sel)
+{
+ int i;
+ // storing the result
+ r_Marray<char>* res;
+
+ for(i=1; i<=repeat; i++) {
+ myTimer.start();
+ res = blob1DRead(sel);
+ cout << queryNum << "." << i << ": ";
+ myTimer.stop();
+ cout << endl;
+ delete res;
+ }
+
+ // optionally printing the result
+ if( printFlag )
+ ((r_GMarray*)(res))->r_GMarray::print_status();
+}
+
+void
+execQuery(char* myRectStr, int queryNum, int i)
+{
+ // storing the result
+ r_Marray<char>* res;
+ // the query rectangle
+ r_Minterval* sd_res;
+
+ sd_res = new r_Minterval(myRectStr);
+
+ cout << queryNum << "." << i << ": ";
+ res = blobRead(*sd_res);
+ cout << endl;
+ delete res;
+
+ delete sd_res;
+
+ // optionally printing the result
+ if( printFlag )
+ ((r_GMarray*)(res))->r_GMarray::print_status();
+}
+
+static void
+printUsage(void)
+{
+ cout << "Usage: test_db2blob [options] aFileName"
+ << endl;
+ cout << " aFileName Name of file with query rectangles "
+ << endl
+ << " or BLOB data when inserting." << endl;
+ cout << " -h, --help Print this message and exit." << endl;
+ cout << " -i, --insert Insert BLOB instead of querying"
+ << endl;
+ cout << " -p, --print Print data queried."
+ << endl;
+ exit(0);
+}
+
+int
+main( int argc, char** argv )
+{
+ int iFlag = 0;
+ int queryNum = 0;
+ char fName[1024] = "";
+ float selArray[] = { 0.5, 1, 2, 5, 10, 20, 50, 100 };
+
+ optStruct testDB2BLOBOpt[] = {
+ /* short long type var/func special */
+ { 'h', "help", OPT_FLAG, printUsage, OPT_CALLFUNC },
+ { 'i', "insert", OPT_FLAG, &iFlag, 0 },
+ { 'p', "print", OPT_FLAG, &printFlag, 0 },
+ { 0, 0, OPT_END, 0, 0 } /* no more options */
+ };
+
+ /* parse all options */
+ optParseOptions(&argc, argv, testDB2BLOBOpt, 0);
+
+ strcpy(fName, argv[argc-1]);
+
+ if( iFlag ) {
+ blobInsert( fName );
+ exit(1);
+ }
+
+ ifstream fileStream( fName );
+ char buf[256];
+ char dummy;
+
+ int j = 0;
+ while( fileStream.get( buf, 255, '\n' ) ) {
+ fileStream.get(dummy);
+ if((buf[0] == '/' && buf[1] == '/') || buf[0] == 0) {
+ queryNum++;
+ cout << "Query " << queryNum << ": " << buf << endl;
+ j=0;
+ } else if(buf[0] != 0) {
+ execQuery(buf, queryNum, ++j);
+ }
+ }
+
+// // Selectivity 50% and 100% does not work
+// for(int i=0; i<6; i++) {
+// cout << "BLOB selectivity " << selArray[i] << endl;
+// blob1DExec(++queryNum, selArray[i]);
+// }
+}
diff --git a/rasodmg/test/test_dirtiling.cc b/rasodmg/test/test_dirtiling.cc
new file mode 100644
index 0000000..3cc57dc
--- /dev/null
+++ b/rasodmg/test/test_dirtiling.cc
@@ -0,0 +1,93 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_dirtiling.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: test class r_Dir_Tiling.
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+#include <iostream>
+#include <stdio.h>
+#include "rasodmg/marray.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "raslib/dlist.hh"
+
+int main(int argc, char* argv[])
+{
+ int tilesize = 10000;
+
+ // Get tile size
+ if (argc == 2)
+ tilesize = atoi(argv[1]);
+
+ // Create a domain decomposition
+
+ r_Dir_Decompose decomp[2];
+ decomp[0] << 0 << 50 << 200 << 600 << 700 << 950 << 999;
+
+ r_Dir_Tiling tiling(2, decomp, tilesize);
+ tiling.print_status(cout);
+
+ cout << endl << "----- Domain decomposition -----" << endl;
+
+ // Create a domain and an image
+
+ r_Minterval domain(2);
+ domain << r_Sinterval(0L, 999L) << r_Sinterval(0L, 99L);
+
+ r_Marray<char> image(domain);
+
+ // Compute tiles
+
+ DList<r_Minterval>* tiles = tiling.compute_tiles(domain, sizeof(char));
+
+ // Output the information
+
+ cout << "Domain: " << domain << endl << endl;
+ cout << "Tiles: " << endl;
+
+ DListIterator<r_Minterval> it = tiles->create_iterator();
+ for (; it.not_done(); it++)
+ {
+ r_Minterval inter = *it;
+ cout << " " << inter << endl;
+ }
+
+ delete tiles;
+}
+
+
+
+
+
+
+
+
diff --git a/rasodmg/test/test_fastscale.cc b/rasodmg/test/test_fastscale.cc
new file mode 100644
index 0000000..1911855
--- /dev/null
+++ b/rasodmg/test/test_fastscale.cc
@@ -0,0 +1,293 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_fastscale.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+#include <iostream>
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include "rasodmg/fastscale.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/marray.hh"
+#include "raslib/odmgtypes.hh"
+
+
+
+template class r_Fast_Scale<r_Char>;
+
+template<class T>
+void fast_scale_resample_array(T *dest, const T *src, const r_Minterval &destIv, const r_Minterval &srcIv, const r_Minterval &srcIter, unsigned int type_len, unsigned int length);
+
+static void test_resample(unsigned int extent, unsigned int shrink)
+{
+ r_Minterval siv(2);
+ r_Minterval div(2);
+ unsigned int shrunken;
+ r_Char *srcData;
+ r_Char *destData;
+
+ cout << "Test resampling, size " << extent
+ << ", shrink factor " << shrink << endl;
+
+ shrunken = (extent / shrink);
+ if (shrunken * shrink < extent) shrunken++;
+
+ siv << r_Sinterval((r_Range)0, (r_Range)extent-1)
+ << r_Sinterval((r_Range)0, (r_Range)extent-1);
+
+ div << r_Sinterval((r_Range)0, (r_Range)shrunken-1)
+ << r_Sinterval((r_Range)0, (r_Range)shrunken-1);
+
+ srcData = new r_Char[extent*extent];
+ destData = new r_Char[shrunken*shrunken];
+
+ unsigned int i, j;
+
+ for (i=0; i<extent; i++)
+ for (j=0; j<extent; j++)
+ srcData[i*extent + j] = (r_Char)(i+j);
+
+ cout << "go... " << flush;
+ fast_scale_resample_array(destData, srcData, div, siv, siv, 1, shrink);
+ cout << "OK... " << flush;
+
+ delete [] srcData;
+ delete [] destData;
+
+ cout << "done." << endl;
+}
+
+
+int main(int argc, char *argv[])
+{
+ char servername[256] = "sunwibas0";
+ char collname[256] = "nopscale";
+ char database[256] = "NorbertBase";
+ r_Range imgSize = 1000;
+ r_Range updtSize = 100;
+ int dostuff=3;
+
+#if 0
+ // test the actual resampling code...
+ unsigned int shrink;
+ for (shrink=2; shrink<50; shrink++)
+ {
+ test_resample(1000, shrink);
+ }
+ exit(0);
+#endif
+
+ int i;
+
+ i = 1;
+ while (i < argc)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 's':
+ strcpy(servername, argv[++i]);
+ break;
+ case 'd':
+ strcpy(database, argv[++i]);
+ break;
+ case 'c':
+ strcpy(collname, argv[++i]);
+ break;
+ case 'i':
+ imgSize = atoi(argv[++i]);
+ break;
+ case 'n': // no create
+ dostuff &= ~1;
+ break;
+ case 'N': // no update
+ dostuff &= ~2;
+ break;
+ case 'h':
+ cout << argv[0] << " [-s servername -d dbname -c collname -i imgsize -n -N -h]" << endl;
+ exit(0);
+ default:
+ cerr << "Bad switch " << argv[i] << endl;
+ exit(-1);
+ }
+ }
+ else
+ {
+ cerr << "unknown option " << argv[i] << endl;
+ exit(-1);
+ }
+ i++;
+ }
+
+ r_Database db;
+ r_Transaction ta;
+ r_Minterval tileDom(2);
+ r_Domain_Storage_Layout *myStorageLayout;
+ r_Aligned_Tiling *myAlignedTiling;
+ tileDom << r_Sinterval((r_Range)0, (r_Range)100)
+ << r_Sinterval((r_Range)0, (r_Range)100);
+ myAlignedTiling = new r_Aligned_Tiling( tileDom, tileDom.cell_count() );
+ myStorageLayout = new r_Domain_Storage_Layout( tileDom, myAlignedTiling );
+ r_Minterval imgDom(2);
+ imgDom << r_Sinterval((r_Range)0, (r_Range)imgSize)
+ << r_Sinterval((r_Range)0, (r_Range)imgSize);
+
+ r_Fast_Scale<r_Char>* myScale;
+
+ cout << "Server = " << servername << ", Database = " << database << ", collection = " << collname << ", Image size = " << imgSize << endl;
+
+ try
+ {
+ db.set_servername(servername);
+ db.open(database);
+ }
+ catch(r_Error &err)
+ {
+ cerr << err.what() << endl;
+ exit(-1);
+ }
+
+ if ((dostuff & 1) != 0)
+ {
+ try
+ {
+ ta.begin();
+ myScale = new r_Fast_Scale<r_Char>(collname, imgDom, "GreySet", "GreyImage", myStorageLayout);
+ ta.commit();
+ delete myScale;
+ cout << "created OK" << endl;
+ }
+ catch(r_Error &err)
+ {
+ ta.abort();
+ cerr << err.what() << endl;
+ }
+ }
+
+ delete myStorageLayout;
+
+ // read a small object for identification
+ try
+ {
+ ta.begin(r_Transaction::read_only);
+ r_Ref<r_GMarray> mddObj = r_Fast_Base_Scale::get_minimal_array(collname);
+ ta.commit();
+ cout << "Object read: ";
+ mddObj->print_status();
+ mddObj.destroy();
+ }
+ catch(r_Error &err)
+ {
+ ta.abort();
+ cerr << err.what() << endl;
+ }
+
+ try
+ {
+ ta.begin(r_Transaction::read_only);
+ myScale = new r_Fast_Scale<r_Char>(collname);
+ cout << "Read domain: " << myScale->get_full_domain() << endl;
+ ta.commit();
+ cout << "domain OK" << endl;
+ }
+ catch(r_Error &err)
+ {
+ ta.abort();
+ cerr << err.what() << endl;
+ }
+
+ if ((dostuff & 2) != 0)
+ {
+ // update a diagonal strip
+ for (i=0; i<=imgSize-updtSize; i+=updtSize/2)
+ {
+ try
+ {
+ r_Minterval uiv(2);
+
+ uiv << r_Sinterval((r_Range)i, (r_Range)i+updtSize-1)
+ << r_Sinterval((r_Range)i, (r_Range)i+updtSize-1);
+
+ cout << "Update " << uiv << endl;
+ r_Marray<r_Char> *updtArray = new ("GreyImage") r_Marray<r_Char>(uiv);
+ memset(updtArray->get_array(), 255, updtSize * updtSize);
+ cout << "Start insert... " << flush;
+ ta.begin();
+ myScale->insert_array(*updtArray);
+ ta.commit();
+ delete updtArray;
+ cout << "OK" << endl;
+ }
+ catch (r_Error &err)
+ {
+ ta.abort();
+ cerr << err.what();
+ }
+ }
+ }
+
+ double scaleFactor;
+
+ for (scaleFactor=1.0; scaleFactor>1e-6; scaleFactor-=0.05)
+ {
+ try
+ {
+ r_Minterval scaledIv;
+
+ if (myScale->get_scaled_domain(myScale->get_full_domain(), scaledIv, scaleFactor) != 0)
+ {
+ cout << "Read " << scaledIv << ", scaled " << scaleFactor << "..." << flush;
+ ta.begin(r_Transaction::read_only);
+ r_Ref<r_Marray<r_Char> > result;
+ result = myScale->get_scaled_image(scaledIv, scaleFactor);
+ ta.commit();
+ cout << "OK" << endl;
+ result.destroy();
+ }
+ }
+ catch(r_Error &err)
+ {
+ ta.abort();
+ cerr << err.what() << endl;
+ }
+ }
+
+ delete myScale;
+
+ db.close();
+
+ return 0;
+}
diff --git a/rasodmg/test/test_gmarray.cc b/rasodmg/test/test_gmarray.cc
new file mode 100644
index 0000000..dbd95a4
--- /dev/null
+++ b/rasodmg/test/test_gmarray.cc
@@ -0,0 +1,229 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_marray.cc
+ *
+ * MODULE: raslib
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <iostream>
+
+#include "rasodmg/marray.hh"
+
+#include "raslib/minterval.hh"
+#include "raslib/sinterval.hh"
+#include "raslib/point.hh"
+#include "raslib/error.hh"
+#include "raslib/type.hh"
+#include "raslib/basetype.hh"
+#include "raslib/attribute.hh"
+#include "raslib/structuretype.hh"
+#include "raslib/primitivetype.hh"
+
+
+struct myStructType {
+ char red;
+ char green;
+ short east;
+ float middle;
+};
+
+struct myStructType3 {
+ double feature_1 ;
+ double feature_2 ;
+ double feature_3 ;
+};
+
+struct myStructTypeCom {
+ long greyvalue;
+ long greyvalue2;
+ myStructType3 features;
+};
+
+static int INIT = 0;
+static float FINIT = 0;
+static char CINIT = 0;
+static double DINIT = 0;
+static long LINIT = 0;
+
+int initFunction( const r_Point& /*pt*/ )
+{
+ /*
+ int value=0;
+
+ for( int i=0; i< pt.dimension(); i++ )
+ value += pt[i];
+
+ return value;
+ */
+ return 3*(INIT++)/2;
+}
+
+float initFunctionFloat( const r_Point& /*pt*/ )
+{
+ return 3*(FINIT++)/2;
+}
+
+
+char initFunctionChar( const r_Point& /*pt*/ )
+{
+ return 3*(CINIT++)/2;
+}
+
+double initFunctionDouble( const r_Point& /*pt*/ )
+{
+ return 3*(DINIT++)/2;
+}
+
+long initFunctionLong( const r_Point& /*pt*/ )
+{
+ return (LINIT++);
+}
+
+
+myStructType initFunctionStruct( const r_Point& /*pt*/ )
+{
+ myStructType myStruct;
+
+ myStruct.red = 3;
+ myStruct.green = 4;
+ myStruct.east = 123;
+ myStruct.middle = 7.4;
+
+ return myStruct;
+}
+
+
+myStructType3 initFunctionStruct3( const r_Point& pt)
+{
+ myStructType3 myStruct;
+
+ myStruct.feature_1 = 0.5* initFunctionDouble( pt );
+ DINIT--;
+ myStruct.feature_2 = 3* initFunctionDouble( pt );
+ DINIT--;
+ myStruct.feature_3 = initFunctionDouble( pt );
+
+ return myStruct;
+}
+
+
+myStructTypeCom initFunctionStructCom( const r_Point& pt)
+{
+ myStructTypeCom myStructCom;
+
+ myStructCom.greyvalue = initFunctionLong( pt );
+ LINIT--;
+ myStructCom.greyvalue2 = 3*initFunctionLong( pt );
+
+ //myStructCom.features = initFunctionStruct3( pt );
+
+ myStructCom.features.feature_1 = 0.5* initFunctionDouble( pt );
+ DINIT--;
+ myStructCom.features.feature_2 = 3* initFunctionDouble( pt );
+ DINIT--;
+ myStructCom.features.feature_3 = initFunctionDouble( pt );
+
+
+ return myStructCom;
+}
+
+
+
+int main()
+{
+ cout << endl << endl;
+ cout << "Marray Examples" << endl;
+ cout << "===============" << endl << endl;
+
+ cout << "Initialization of Marray<int, [3:5,6:8]> with init function:" << endl;
+ r_Marray<int> a( r_Minterval("[3:5,6:8]"), &initFunction );
+ a.set_type_structure("marray<long>");
+ cout << "OK" << endl;
+ a.print_status( cout );
+
+
+ cout << "Initialization of Marray<float, [3:5,6:8]> with init function float:" << endl;
+ r_Marray<float> b( r_Minterval("[3:5,6:8]"), &initFunctionFloat );
+ b.set_type_structure("marray<float>");
+ cout << "OK" << endl;
+ b.print_status( cout );
+
+
+ cout << "Initialization of Marray<char, [3:5,6:8]> with init function char:" << endl;
+ r_Marray<char> c( r_Minterval("[3:5,6:8]"), &initFunctionChar );
+ c.set_type_structure("marray<char>");
+ cout << "OK" << endl;
+ c.print_status( cout );
+
+
+ cout << "Initialization of Marray<double, [3:5,6:8]> with init function double:" << endl;
+ r_Marray<double> d( r_Minterval("[3:5,6:8]"), &initFunctionDouble );
+ d.set_type_structure("marray<double>");
+ cout << "OK" << endl;
+ d.print_status( cout );
+
+ FINIT = 0;
+ CINIT = 0;
+ cout << "Initialization of Marray<struct{char, char, short, float}, [3:5,6:8]> with init function struct:" << endl;
+ r_Marray<myStructType> st( r_Minterval("[3:5,6:8]"), &initFunctionStruct );
+ st.set_type_structure("marray<struct{char,char,short,float}>");
+ cout << "OK" << endl;
+ st.print_status( cout );
+
+ DINIT = 0;
+ cout << "Initialization of Marray<struct{double, double, double}, [3:5,6:8]> with init function struct3:" << endl;
+ r_Marray<myStructType3> st3( r_Minterval("[3:5,6:8]"), &initFunctionStruct3 );
+ st3.set_type_structure("marray<struct{double,double,double}>");
+ cout << "OK" << endl;
+ st3.print_status( cout );
+
+ DINIT = 0;
+ cout << "Initialization of Marray<struct{ long, long, struct{double, double, double} }, [3:5,6:8]> with init function structCom:" << endl;
+ r_Marray<myStructTypeCom> stCom( r_Minterval("[3:5,6:8]"), &initFunctionStructCom );
+ stCom.set_type_structure("marray<struct{long,long,struct{double,double,double}}>");
+ cout << "OK" << endl;
+ stCom.print_status( cout );
+ cout << endl;
+
+ // print single cell
+ r_GMarray& gstCom = (r_GMarray&)stCom;
+
+ const r_Base_Type& baseType = *(gstCom.get_base_type_schema());
+ cout << "gmarray_stCom[4,6] = " << flush;
+ baseType.print_value( gstCom[r_Point(4,6)] );
+ cout << endl;
+
+ cout << "access second double of inner struct: " << flush;
+ const r_Structure_Type& outerStruct = (const r_Structure_Type&)baseType;
+ // const r_Attribute& innerAttribute = outerStruct[2];
+ // const r_Structure_Type& innerStruct = (const r_Structure_Type&)innerAttribute.type_of();
+ // const r_Attribute& doubleAttribute = innerStruct[1];
+ // cout << doubleAttribute.get_double( gstCom[r_Point(4,6)] ) << endl;
+ cout << outerStruct[2][1].get_double( gstCom[r_Point(4,6)] ) << endl;
+
+ return 0;
+}
diff --git a/rasodmg/test/test_insert.cc b/rasodmg/test/test_insert.cc
new file mode 100644
index 0000000..dea9147
--- /dev/null
+++ b/rasodmg/test/test_insert.cc
@@ -0,0 +1,235 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_insert.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <iostream>
+#include <string.h>
+
+#ifdef __VISUALC__
+ #define __EXECUTABLE__
+#endif
+
+#include "include/basictypes.hh"
+
+#ifdef __VISUALC__
+ #undef __EXECUTABLE__
+#endif
+
+static int INIT = 0;
+
+r_ULong initWithCounter( const r_Point& /*pt*/ )
+{
+ return INIT++;
+}
+
+
+r_ULong initWithCrossfoot( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ for( r_Dimension i=0; i< pt.dimension(); i++ )
+ value += pt[i];
+
+ return value;
+}
+
+
+r_ULong initWithCoordinates( const r_Point& pt )
+{
+ r_ULong value=0;
+ int factor=1;
+
+ for( int i=pt.dimension()-1; i >= 0; i-- )
+ {
+ value += factor * pt[i];
+ factor *= 100;
+ }
+
+ return value;
+}
+
+
+
+int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex )
+{
+ int found = 0;
+ int i=1;
+
+ while( !found && i<argc )
+ found = !strcmp( searchText, argv[i++] );
+
+ if( found && i<argc && !strchr(argv[i],'-') )
+ optionValueIndex = i;
+ else
+ optionValueIndex = 0;
+
+ return found;
+}
+
+
+
+int main( int argc, char** argv )
+{
+ char serverName[255];
+ char baseName[255];
+ char collName[255];
+ int optionValueIndex;
+
+ if( argc < 4 || checkArguments( argc, argv, "-h", optionValueIndex ) )
+ {
+ cout << "Usage: test_insert server_name base_name collection_name [options]" << endl << endl;
+ cout << "Options: -h ... this help" << endl;
+ // cout << " -nooutput ... no output of MDD content" << endl;
+ // cout << " -hex ... output in hex" << endl;
+ cout << endl;
+ return 0;
+ }
+
+ strcpy( serverName, argv[1] );
+ strcpy( baseName, argv[2] );
+ strcpy( collName, argv[3] );
+
+ cout << endl << endl;
+ cout << "ODMG conformant insertion of Marrays" << endl;
+ cout << "====================================" << endl << endl;
+
+ r_Database db;
+ r_Transaction ta;
+ r_Ref< r_Set< r_Ref< r_Marray<r_ULong> > > > image_set;
+ r_Ref< r_Marray<r_ULong> > image1, image2, image3, image4,
+ image5, image6, transImage;
+ r_Minterval domain, domain2;
+
+ domain = r_Minterval(2) << r_Sinterval( 0, 10 ) << r_Sinterval( 0, 10 );
+
+ db.set_servername( serverName );
+
+ try
+ {
+ cout << "Opening Database " << baseName << " on " << serverName << "... " << flush;
+ db.open( baseName );
+ cout << "OK" << endl;
+
+ cout << "Starting Transaction ... " << flush;
+ ta.begin();
+ cout << "OK" << endl;
+
+ cout << "Opening the set ... " << flush;
+
+ try{
+ image_set = db.lookup_object( collName );
+ }
+ catch( r_Error& /*obj*/ )
+ {
+ cout << "FAILED" << endl;
+ // cout << obj.what() << endl;
+
+ //
+ // set doesn't exist -> create the set
+ //
+
+ cout << "Create the set ... " << flush;
+
+ // create the set
+ image_set = new( &db, "ULongSet" ) r_Set< r_Ref< r_Marray<r_ULong> > >;
+
+ // create a name for the persistent set in order to be able to look it up again
+ db.set_object_name( *image_set, collName );
+ }
+
+ cout << "OK" << endl;
+
+ cout << "Create image1 with constant 0 ... " << flush;
+ image1 = new( &db, "ULongImage" ) ULongImage( domain, (r_ULong)0 );
+ cout << "OK" << endl;
+
+ cout << "Create image2 with copy constructor from image1 ... " << flush;
+ image2 = new( &db, "ULongImage" ) ULongImage( (const ULongImage&) *image1 );
+ cout << "OK" << endl;
+
+ cout << "Create transient image with constant 1 ... " << flush;
+ transImage = new ULongImage( domain, 1ul );
+ cout << "OK" << endl;
+
+ cout << "Create image3 with copy constructor from transient image ... " << flush;
+ image3 = new( &db, "ULongImage" ) ULongImage( (const ULongImage&) *transImage );
+ cout << "OK" << endl;
+
+ transImage.destroy();
+
+ // image2->initialize_oid( db.get_new_oid(1) );
+
+ cout << "Create image4 with cross foot ... " << flush;
+ image4 = new( &db, "ULongImage" ) r_Marray<r_ULong>( domain, &initWithCrossfoot );
+ cout << "OK" << endl;
+
+ cout << "Create image5 with counter ... " << flush;
+ image5 = new( &db, "ULongImage" ) r_Marray<r_ULong>( domain, &initWithCounter );
+ cout << "OK" << endl;
+
+ cout << "Create image6 with coordinates ... " << flush;
+ image6 = new( &db, "ULongImage" ) r_Marray<r_ULong>( domain, &initWithCoordinates );
+ cout << "OK" << endl;
+
+ cout << "Insert images into the set " << collName << " ... " << flush;
+
+ // insert the images
+ image_set->insert_element( image1 );
+ image_set->insert_element( image2 );
+ image_set->insert_element( image3 );
+ image_set->insert_element( image4 );
+ image_set->insert_element( image5 );
+ image_set->insert_element( image6 );
+
+ cout << "OK" << endl;
+
+ cout << "Commiting Transaction ... " << flush;
+ ta.commit();
+ cout << "OK" << endl;
+
+ cout << "Closing Database ... " << flush;
+ db.close();
+ cout << "OK" << endl;
+ }
+ catch( r_Error& errorObj )
+ {
+ ta.abort();
+ db.close();
+ cerr << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/rasodmg/test/test_insert3.cc b/rasodmg/test/test_insert3.cc
new file mode 100644
index 0000000..8d620e7
--- /dev/null
+++ b/rasodmg/test/test_insert3.cc
@@ -0,0 +1,843 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_insert3.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+ */
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream>
+#endif
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <fstream>
+
+#include <math.h>
+
+#ifdef __VISUALC__
+ #define __EXECUTABLE__
+#endif
+#include "include/basictypes.hh"
+#include "raslib/type.hh"
+
+#include "rasodmg/storagelayout.hh"
+
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/interesttiling.hh"
+#include "rasodmg/stattiling.hh"
+
+
+const int MAX_STR_LEN = 255;
+
+static int INIT = 0;
+static r_Long minNo = 0;
+static r_Long maxNo = 0;
+static ifstream fileStream;
+
+using namespace std;
+
+r_ULong initWithCounter( const r_Point& /*pt*/ )
+{
+ return INIT++;
+}
+
+
+r_Char initWithCounterChar( const r_Point& /*pt*/ )
+{
+ return (r_Char) INIT++;
+}
+
+
+r_UShort initWithCounterUShort( const r_Point& /*pt*/ )
+{
+ return (r_UShort) INIT++;
+}
+
+
+
+r_ULong initWithCrossfoot( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ for( r_Dimension i=0; i< pt.dimension(); i++ )
+ value += (r_ULong)pt[i];
+
+ return value;
+}
+
+
+r_ULong initWithCoordinates( const r_Point& pt )
+{
+ r_ULong value=0;
+ r_ULong factor=1;
+
+ for( int i=pt.dimension()-1; i >= 0; i-- )
+ {
+ value += (r_ULong)(factor * pt[i]);
+ factor *= 100;
+ }
+
+ return value;
+}
+
+
+
+r_Char initWithCurve( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ for( r_Dimension i=0; i < pt.dimension(); i++ )
+ value += (r_Char)( 255* sin( .25 * (float)pt[i] ) );
+
+ return (r_Char)value;
+}
+
+
+
+r_ULong initWithColorCube( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ if( pt.dimension() == 3 )
+ value = ((r_ULong)(pt[0]) << 16) + ((r_ULong)(pt[1]) << 8) + (r_ULong)(pt[2]);
+
+ return value;
+}
+
+
+r_Char initWithRandomChar( const r_Point& /*pt*/ )
+{
+ // rand creates numbers between 0 and 32767
+ r_ULong number = rand();
+ double factor = (maxNo - minNo)/32767.0;
+
+ return (r_Char)(minNo + (number * factor));
+}
+
+r_ULong initWithRandomULong( const r_Point& /*pt*/ )
+{
+ // rand creates numbers between 0 and 32767
+ r_ULong number = rand();
+ double factor = (maxNo - minNo)/32767.0;
+
+ return (r_ULong)(minNo + (number * factor));
+}
+
+
+r_Char initFromFile( const r_Point& /*pt*/ )
+{
+ char ch;
+
+ if( fileStream.get(ch) )
+ return ch;
+ else
+ return 0;
+}
+
+#ifdef QUERY_TEST
+r_Ref< r_Marray<r_ULong> > readFile( r_Database& db )
+{
+ r_Ref< r_Marray<r_ULong> > image;
+ r_Minterval domain(3);
+ long dx, dy, dz, depth, cx, cy, cz;
+ int i;
+
+ ifstream fileStream( "hw8.full.vol" );
+ if( !fileStream )
+ {
+ std::cout << "Error: File not found." << std::endl;
+ exit(-1);
+ }
+
+ // read the first 16 bytes
+ char charDummy;
+ for( i=0; i<16; i++ )
+ fileStream >> charDummy;
+
+ dx = 256;
+ dy = 256;
+ dz = 20;
+ depth = 8;
+
+ domain << r_Sinterval( (r_Long)0, (r_Long)(dx-1) ) << r_Sinterval( (r_Long)0, (r_Long)(dy-1) ) << r_Sinterval( (r_Long)0, (r_Long)(dz-1) );
+
+ std::cout << domain << "... "<< std::flush;
+
+ image = new( &db ) r_Marray<r_ULong>( domain );
+
+ r_ULong* dataPtr = (r_ULong*)image->get_array();
+
+ r_Point pt(3);
+
+ // for( i=0; i<dx*dy*(221-dz); i++ )
+ // fileStream >> charDummy;
+
+ for( cz = 0; cz < dz; cz++ )
+ {
+ pt[2] = cz;
+ for( cy = 0; cy < dy; cy++ )
+ {
+ pt[1] = cy;
+ for( cx = 0; cx < dx; cx++ )
+ {
+ unsigned char ch;
+ fileStream.get(ch);
+
+ pt[0] = cx;
+ dataPtr[domain.cell_offset(pt)] = ((r_ULong)ch << 16) +
+ ((r_ULong)ch << 8) +
+ ((r_ULong)ch);
+ }
+ }
+ }
+
+ fileStream.close();
+
+ return image;
+}
+#endif
+
+
+void printColl( r_Ref< r_Set< r_Ref< r_GMarray > > >& image_set, int output, int hexOutput )
+{
+ std::cout << "Collection" << std::endl;
+ std::cout << " Oid...................: " << image_set->get_oid() << std::endl;
+ std::cout << " Type Name.............: " << image_set->get_object_name() << std::endl;
+ std::cout << " Type Structure........: "
+ << ( image_set->get_type_structure() ? image_set->get_type_structure() : "<nn>" ) << std::endl;
+ std::cout << " Type Schema...........: " << std::flush;
+ if( image_set->get_type_schema() )
+ image_set->get_type_schema()->print_status( std::cout );
+ else
+ std::cout << "<nn>" << std::flush;
+ std::cout << std::endl;
+ std::cout << " Number of entries.....: " << image_set->cardinality() << std::endl;
+ std::cout << " Element Type Schema...: " << std::flush;
+ if( image_set->get_element_type_schema() )
+ image_set->get_element_type_schema()->print_status( std::cout );
+ else
+ std::cout << "<nn>" << std::flush;
+ std::cout << std::endl;
+
+ r_Iterator< r_Ref< r_GMarray > > iter = image_set->create_iterator();
+
+ std::cout << std::endl;
+ for ( int i=1 ; iter.not_done(); iter++, i++ )
+ {
+ // do not dereference the object
+ std::cout << "Image " << i << " oid: " << (*iter).get_oid() << std::endl;
+
+ if( output )
+ {
+ (*iter)->print_status( std::cout, hexOutput );
+ std::cout << std::endl;
+ }
+ }
+ std::cout << std::endl;
+}
+
+
+
+int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex )
+{
+ int found = 0;
+ int i=1;
+
+ while( !found && i<argc )
+ found = !strcmp( searchText, argv[i++] );
+
+ if( found && i<argc && (argv[i][0] != '-') )
+ optionValueIndex = i;
+ else
+ optionValueIndex = 0;
+
+ return found;
+}
+
+void printUsage(char* name){
+ std::cout << name << " v1.1 systemtest insert utility" << std::endl;
+ std::cout << "Description: Systemtest insert utility for creation and update of sets in RasDaMan" << std::endl;
+ std::cout << "Usage: " << name << " [options]" << std::endl << std::endl;
+ std::cout << "Options: -h ... this help" << std::endl;
+ std::cout << " -server <srvname> ... name of server.(mandatory)" << std::endl;
+ std::cout << " -port <nnnn> ... port of server.(default 7001)" << std::endl;
+ std::cout << " -base <dbname> ... name of database.(madatory)" << std::endl;
+ std::cout << " -setname <setname> ... name of collection.(madatory)" << std::endl;
+ std::cout << " -settype <typename> ... type name used for creation of a new set." << std::endl;
+ std::cout << " -mddtype <typename> ... type name used for creation of a new mdd object." << std::endl;
+ std::cout << " -user <usrname> ... user name.(default rasguest)" << std::endl;
+ std::cout << " -passwd <usrpasswd> ... user password.(default rasquest)" << std::endl;
+ std::cout << " -transferformat <format> ... transfer format.(default Array)" << std::endl;
+ std::cout << " -transferformatparams <formatparams> ... transfer format parameters.(default NULL)" << std::endl;
+ std::cout << " -storageformat <format> ... storage format.(default Array)" << std::endl;
+ std::cout << " -storageformatparams <formatparams> ... storage format parameters.(default NULL)" << std::endl;
+ std::cout << " -tiling <tiling> ... tiling strategy.(default SizeTiling)" << std::endl;
+ std::cout << " -tilingparams <tilingparams> ... tiling strategy params.(default 131072)" << std::endl;
+ std::cout << " -file <filename> ... file name used to read data from a file" << std::endl;
+ std::cout << " -testbed ... turn on output for testbed.default(default off)" << std::endl;
+ std::cout << std::endl << std::endl;
+
+ std::cout << "Report bugs to <support@active­knowledge.com>" << std::endl;
+}
+
+r_Tiling*
+getTilingScheme(r_Tiling_Scheme& tilingS, char* tilingP){
+ r_Tiling* retval=NULL;
+
+ try {
+ std::cout << " Creating tiling strategy ..." << std::flush;
+ switch(tilingS) {
+ case r_NoTiling:
+ retval = new r_No_Tiling(tilingP);
+ break;
+ case r_AlignedTiling:
+ retval = new r_Aligned_Tiling(tilingP);
+ break;
+ case r_InterestTiling:
+ retval = new r_Interest_Tiling(tilingP);
+ break;
+ case r_DirectionalTiling:
+ retval = new r_Dir_Tiling(tilingP);
+ break;
+ case r_StatisticalTiling:
+ retval = new r_Stat_Tiling(tilingP);
+ break;
+ default:
+ retval = new r_Size_Tiling(tilingP);
+ break;
+ }
+ std::cout << "OK" << std::flush;
+ }
+ catch(r_Error& err){
+ std::cout << "FAILED" << std::endl;
+ std::cout << "Error " << err.get_errorno() << " : " << err.what() << std::endl;
+ }
+
+ return retval;
+}
+
+int main( int argc, char** argv ) {
+ int optionValueIndex=0;
+ int testbed = 0;
+
+ r_Tiling_Scheme tilingScheme = r_SizeTiling;
+ char* tilingSchemeParams = "131072";
+
+ r_Data_Format transferFormat=r_Array;
+ char *transferFormatParams = NULL;
+ r_Data_Format storageFormat=r_Array;
+ char *storageFormatParams = NULL;
+
+ char serverName[MAX_STR_LEN]="";
+ r_ULong serverPort=7001;
+ char baseName[MAX_STR_LEN]="";
+
+ char userName[MAX_STR_LEN]="rasguest";
+ char userPasswd[MAX_STR_LEN]="rasguest";
+
+ char collName[MAX_STR_LEN]="";
+ char setTypeName[MAX_STR_LEN] = "";
+ char mddTypeName[MAX_STR_LEN] = "";
+ char fileName[MAX_STR_LEN]="";
+
+
+ if( checkArguments( argc, argv, "-h", optionValueIndex ) ) {
+ printUsage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+
+ if( checkArguments( argc, argv, "-server", optionValueIndex ) && optionValueIndex )
+ strcpy( serverName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-base", optionValueIndex ) && optionValueIndex )
+ strcpy( baseName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-setname", optionValueIndex ) && optionValueIndex )
+ strcpy( collName, argv[optionValueIndex] );
+
+ if(!strcmp(serverName, "") ||
+ !strcmp(baseName, "") ||
+ !strcmp(collName, "") ) {
+ std::cerr << "Mandatory parameters are missing!" << std::endl;
+ printUsage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+
+ if( checkArguments( argc, argv, "-port", optionValueIndex ) && optionValueIndex )
+ serverPort = strtoul( argv[optionValueIndex], (char **)NULL, 10 ) ;
+
+ if( checkArguments( argc, argv, "-user", optionValueIndex ) && optionValueIndex )
+ strcpy( userName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-passwd", optionValueIndex ) && optionValueIndex )
+ strcpy( userPasswd, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-transferformat", optionValueIndex ) && optionValueIndex ) {
+ transferFormat = get_data_format_from_name( argv[optionValueIndex] );
+ if(transferFormat == r_Data_Format_NUMBER) {
+ std::cerr << "Invalid transfer format '" << argv[optionValueIndex] << "' switched to " << r_Array << std::endl;
+ transferFormat = r_Array;
+ }
+ }
+
+ if( checkArguments( argc, argv, "-transferformatparams", optionValueIndex ) && optionValueIndex )
+ transferFormatParams = argv[optionValueIndex] ;
+
+ if( checkArguments( argc, argv, "-storageformat", optionValueIndex ) && optionValueIndex ) {
+ storageFormat = get_data_format_from_name(argv[optionValueIndex] );
+ if(storageFormat == r_Data_Format_NUMBER) {
+ std::cerr << "Invalid storage format '" << argv[optionValueIndex] << "' switched to " << r_Array << std::endl;
+ storageFormat = r_Array;
+ }
+ }
+
+ if( checkArguments( argc, argv, "-storageformatparams", optionValueIndex ) && optionValueIndex )
+ storageFormatParams = argv[optionValueIndex] ;
+
+ if( checkArguments( argc, argv, "-settype", optionValueIndex ) && optionValueIndex )
+ strcpy( setTypeName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-mddtype", optionValueIndex ) && optionValueIndex )
+ strcpy( mddTypeName, argv[optionValueIndex] );
+
+ testbed = checkArguments( argc, argv, "-testbed", optionValueIndex );
+
+ if( checkArguments( argc, argv, "-tiling", optionValueIndex ) && optionValueIndex ) {
+ tilingScheme = get_tiling_scheme_from_name( argv[optionValueIndex] );
+ if(tilingScheme == r_Tiling_Scheme_NUMBER) {
+ std::cerr << "Invalid tiling scheme '" << argv[optionValueIndex] << "' switched to " << r_SizeTiling << std::endl;
+ tilingScheme = r_SizeTiling;
+ }
+ if(tilingScheme == r_RegularTiling) {
+ std::cerr << "Tiling scheme '" << argv[optionValueIndex] << "' not supported, switched to " << r_SizeTiling << std::endl;
+ tilingScheme = r_SizeTiling;
+ }
+ }
+
+ if( checkArguments( argc, argv, "-tilingparams", optionValueIndex ) && optionValueIndex )
+ tilingSchemeParams = argv[optionValueIndex] ;
+
+ if( checkArguments( argc, argv, "-file", optionValueIndex ) && optionValueIndex )
+ strcpy( fileName, argv[optionValueIndex] );
+
+ std::cout << std::endl << std::endl;
+ std::cout << "Insertion of one MDD into the database" << std::endl;
+ std::cout << "======================================" << std::endl << std::endl;
+
+ r_Database db;
+ r_Transaction ta;
+ r_Ref< r_Set< r_Ref< r_GMarray > > > image_set;
+ r_Ref< r_GMarray > image;
+ r_Minterval domain;
+ r_Dimension dim;
+ r_Range low, high;
+ r_ULong initMode, initValue;
+
+ RGBPixel rgbValue = { 1, 2, 3 };
+
+ db.set_servername( serverName, serverPort );
+ db.set_useridentification( userName, userPasswd );
+
+
+ try
+ {
+ std::cout << "MDD Initialization: 0 - Marray<r_ULong> with constant" << std::endl;
+ std::cout << " 1 - Marray<r_ULong> with counter" << std::endl;
+ std::cout << " 2 - Marray<r_ULong> with coordinates" << std::endl;
+ std::cout << " 3 - Marray<r_ULong> with crossfoot" << std::endl;
+ std::cout << " 4 - Marray<r_ULong> with color cube" << std::endl << std::endl;
+
+ std::cout << " 5 - Marray<r_Char> with constant" << std::endl;
+ std::cout << " 6 - insert RGBImage with constant" << std::endl;
+ std::cout << " 7 - Marray<r_Char> with 255*( sin(.25*x1) + ... + sin(.25*xn) )" << std::endl;
+
+ std::cout << " 8 - Marray<r_ULong> read a file (hw8.full.vol)" << std::endl;
+ std::cout << " 9 - Create just an empty collection of type Marray<r_ULong>" << std::endl;
+ std::cout << " 10 - Delete collection of type GMarray" << std::endl;
+ std::cout << " 11 - Delete an object of collection" << std::endl;
+
+ std::cout << " 13 - Marray<r_Char> with counter" << std::endl;
+ std::cout << " 14 - Marray<r_Char> with random numbers" << std::endl;
+ std::cout << " 15 - Marray<r_UShort> with counter" << std::endl;
+ std::cout << " 16 - Marray<r_ULong> with random numbers" << std::endl;
+ std::cout << " 17 - Marray<r_Boolean>" << std::endl;
+ std::cout << " 18 - Marray<r_Char> from file" << std::endl;
+
+ cin >> initMode;
+ std::cout << "Selected mode : " << initMode << std::endl;
+
+ if( initMode == 18 )
+ {
+ fileStream.open( fileName );
+ if( !fileStream )
+ {
+ std::cout << "Error: File " << fileName << " not found." << std::endl;
+ exit(-1);
+ }
+ }
+
+ if( initMode == 0 || initMode == 5 || initMode == 17 )
+ {
+ std::cout << "Constant value : ";
+ cin >> initValue;
+ std::cout << initValue << std::endl;
+ }
+ if( initMode <= 7 || initMode >= 13 )
+ {
+ std::cout << "Number of dimensions : ";
+ cin >> dim;
+ std::cout << dim << std::endl;
+
+ domain = r_Minterval(dim);
+
+ for( r_Dimension i = 1; i<=dim ; i++ )
+ {
+ std::cout << setw(2) << i << " Dimension( lower bound : ";
+ cin >> low;
+ std::cout << low << " upper bound : ";
+ cin >> high;
+ std::cout << high << " ); " ;
+
+ domain << r_Sinterval( low, high );
+ }
+
+ std::cout << std::endl;
+ }
+
+ if( initMode == 14 || initMode == 16 )
+ {
+ std::cout << "Minimum number : ";
+ cin >> minNo;
+ std::cout << minNo << std::endl;
+
+ std::cout << "Maximum number : ";
+ cin >> maxNo;
+ std::cout << maxNo << std::endl;
+ }
+
+ try{
+ std::cout << "Opening Database " << baseName << " on " << serverName << "... "<< std::flush;
+ db.open( baseName );
+ std::cout << "OK" << std::endl;
+
+ std::cout << "Starting Transaction ... " << std::flush;
+ ta.begin();
+ std::cout << "OK" << std::endl;
+
+ std::cout << "Setting transfer and storage formats ... " << std::flush;
+ db.set_transfer_format( transferFormat, transferFormatParams );
+ db.set_storage_format( storageFormat, storageFormatParams );
+ std::cout << "OK" << std::endl;
+ }
+ catch(r_Error& obj){
+ std::cout << "FAILED" << std::endl;
+ std::cout << "Error " << obj.get_errorno() << " : " << obj.what() << std::endl;
+ ta.abort();
+ db.close();
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "Opening the set " << collName << "... " << std::flush;
+
+ if( initMode == 10 || initMode == 11 )
+ {
+ //
+ // get the set
+ //
+
+ try{
+ image_set = db.lookup_object( collName );
+ }
+ catch( r_Error &obj )
+ {
+ std::cout << "FAILED" << std::endl;
+ std::cout << "Error " << obj.get_errorno() << " : " << obj.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "OK" << std::endl;
+
+ if( initMode == 10 )
+ {
+ // delete the set
+
+ if( !image_set.is_null() )
+ image_set.delete_object();
+ // delete image_set; (not implemented yet)
+ }
+ else
+ {
+ int imageNo=0;
+
+ printColl( image_set, 0, 0 );
+
+ std::cout << "Please enter the image number to delete: ";
+ cin >> imageNo;
+ std::cout << imageNo << std::endl;
+
+ r_Iterator< r_Ref< r_GMarray > > iter = image_set->create_iterator();
+
+ for ( int i=1; iter.not_done() && i<imageNo; iter++, i++ );
+
+ if( imageNo && iter.not_done() )
+ {
+ image_set->remove_element( *iter );
+ std::cout << "MDD " << imageNo << " removed." << std::endl;
+ }
+ else
+ std::cout << "Number not valid." << std::endl << std::endl;
+ }
+ }
+ else
+ {
+ //
+ // get set
+ //
+
+ try{
+ image_set = db.lookup_object( collName );
+ }
+ catch( r_Error& /*obj*/ )
+ {
+ std::cout << "FAILED" << std::endl;
+ //std::cout << "Error " << obj.get_errorno() << " : " << obj.what() << std::endl;
+
+ //
+ // set doesn't exist -> create the set
+ //
+
+ std::cout << "Create the set " << collName << " ... " << std::flush;
+
+ if( initMode == 5 || initMode == 7 || initMode == 13 || initMode == 14 || initMode == 18 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "GreySet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_Char> > >;
+ }
+ else if( initMode == 6 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "RGBSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<RGBPixel> > >;
+ }
+ else if( initMode == 15 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "UShortSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_UShort> > >;
+ }
+ else if( initMode == 17 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "BoolSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_Boolean> > >;
+ }
+ else
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "ULongSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_ULong> > >;
+ }
+
+ // create a name for the persistent set in order to be able to look it up again
+ db.set_object_name( *image_set, collName );
+ }
+
+ std::cout << " with type name " << setTypeName << " ... OK" << std::endl;
+
+ std::cout << "OId of the set is " << image_set->get_oid() << " ... " << std::endl;
+
+ if( initMode <= 9 || initMode >= 13 )
+ {
+ std::cout << "Creating the marray ..." << std::flush;
+
+ // create storage layout object
+ r_Tiling* tilingObj = getTilingScheme(tilingScheme, tilingSchemeParams);
+
+ if(tilingObj == NULL) return EXIT_FAILURE;
+
+ r_Storage_Layout* stl = new r_Storage_Layout( tilingObj );
+
+ // create the image
+ switch( initMode )
+ {
+ case 0:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, (r_ULong)initValue, stl );
+ break;
+ case 1:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithCounter, stl );
+ break;
+ case 2:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithCoordinates, stl );
+ break;
+ case 3:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithCrossfoot, stl );
+ break;
+ case 4:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithColorCube, stl );
+ break;
+ case 5:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, (r_Char)initValue, stl );
+ break;
+ case 6:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "RGBImage" );
+
+ image = new( &db, mddTypeName ) RGBImage( domain, rgbValue, stl );
+ break;
+ case 7:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initWithCurve, stl );
+ break;
+ case 13:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initWithCounterChar, stl );
+ break;
+ case 14:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initWithRandomChar, stl );
+ break;
+ case 15:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "UShortImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_UShort>( domain, &initWithCounterUShort, stl );
+ break;
+ case 16:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithRandomULong, stl );
+ break;
+ case 17:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "BoolImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Boolean>( domain, (r_Boolean)initValue, stl );
+ break;
+ case 18:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initFromFile, stl );
+ break;
+ default:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, (r_ULong)0, stl );
+ }
+
+ std::cout << " Marray type " << mddTypeName << " ... OK" << std::endl;
+ std::cout << "OId of the new image is " << image->get_oid() << std::endl;
+
+ std::cout << "Inserting one image with domain " << domain << " into collection " << collName << "..." << std::flush;
+ // put in into the persistent list
+ image_set->insert_element( image );
+ std::cout << "OK" << std::endl << std::endl;
+
+ if( testbed )
+ {
+ std::cout << std::endl << "Testbed output:" << std::endl;
+ std::cout << "-- Testbed: set_oid=" << image_set->get_oid() << std::endl;
+ std::cout << "-- Testbed: image_oid=" << image->get_oid() << std::endl;
+ std::cout << std::endl;
+ }
+
+ }
+ }
+
+ try
+ {
+ std::cout << "Committing Transaction ... " << std::flush;
+ ta.commit();
+ std::cout << "OK" << std::endl;
+ }
+ catch( r_Error &obj )
+ {
+ std::cerr << "Error " << obj.get_errorno() << " : " << obj.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "Closing Database ... " << std::flush;
+ db.close();
+ std::cout << "OK" << std::endl;
+
+ if( initMode == 18 )
+ fileStream.close();
+ }
+ catch( r_Error& obj )
+ {
+ std::cerr << "Error " << obj.get_errorno() << " : " << obj.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
+
diff --git a/rasodmg/test/test_interesttiling.cc b/rasodmg/test/test_interesttiling.cc
new file mode 100644
index 0000000..3c5ee45
--- /dev/null
+++ b/rasodmg/test/test_interesttiling.cc
@@ -0,0 +1,97 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_interestrtiling.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: test class r_Interest_Tiling.
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+#include <iostream>
+#include <stdio.h>
+#include "rasodmg/marray.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/interesttiling.hh"
+#include "raslib/minterval.hh"
+#include "raslib/sinterval.hh"
+#include "raslib/dlist.hh"
+
+int main()
+{
+ r_Minterval domain(2);
+ domain << r_Sinterval(0L, 500L) << r_Sinterval(0L, 600L);
+
+ r_Minterval int1(2);
+ int1 << r_Sinterval(0L, 100L) << r_Sinterval(0L, 500L);
+
+ r_Minterval int2(2);
+ int2 << r_Sinterval(200L, 400L) << r_Sinterval(100L, 200L);
+
+ r_Minterval int3(2);
+ int3 << r_Sinterval(250L, 450L) << r_Sinterval(150L, 250L);
+
+ r_Minterval int4(2);
+ int4 << r_Sinterval(300L, 500L) << r_Sinterval(400L, 550L);
+
+ DList<r_Minterval> iareas;
+ iareas += int1;
+ iareas += int2;
+ iareas += int3;
+ iareas += int4;
+
+ r_Interest_Tiling tiling(iareas, r_Interest_Tiling::REGROUP_AND_SUBTILING,
+ 50000);
+
+ DList<r_Minterval>* tiles = tiling.compute_tiles(domain, 1);
+
+ cout << "Domain: " << domain << endl << endl;
+ cout << "Interest Areas: " << endl;
+ DListIterator<r_Minterval> it_areas = iareas.create_iterator();
+ for (; it_areas.not_done(); it_areas++)
+ {
+ r_Minterval inter = *it_areas;
+ cout << " " << inter << endl;
+ }
+
+ cout << "Tiles: " << endl;
+
+ DListIterator<r_Minterval> it = tiles->create_iterator();
+ for (; it.not_done(); it++)
+ {
+ r_Minterval inter = *it;
+ cout << " " << inter << endl;
+ }
+
+ delete tiles;
+
+ return 0;
+}
+
+
diff --git a/rasodmg/test/test_iterator.cc b/rasodmg/test/test_iterator.cc
new file mode 100644
index 0000000..24feea6
--- /dev/null
+++ b/rasodmg/test/test_iterator.cc
@@ -0,0 +1,135 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_iterator.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <iostream>
+#include "rasodmg/collection.hh"
+#include "rasodmg/iterator.hh"
+
+int main()
+{
+ int i,v,x,y,z,status;
+
+ i = 0;
+ v = 100;
+ x = 200;
+ y = 300;
+ z = 400;
+ status = 5;
+
+ cout << endl << endl;
+ cout << "Iterator Examples" << endl;
+ cout << "===================" << endl << endl;
+
+ cout << "Creating r_Collection of type int." <<endl;
+ r_Collection<int> a;
+
+ cout << "Creating an iterator of an empty collection." <<endl;
+ r_Iterator<int> iterEmpty = a.create_iterator();
+ if( iterEmpty.not_done() )
+ cout << "Iterator says that iteration is not done." << endl << endl;
+ else
+ cout << "Iterator says that iteration is done." << endl << endl;
+
+ cout << "Now inserting four elements:" << endl << "v = 100" << endl;
+ a.insert_element(v);
+ r_Iterator<int> iterTest = a.create_iterator();
+ if( iterTest.not_done() )
+ cout << "Iterator says that iteration is not done." << endl << endl;
+ else
+ cout << "Iterator says that iteration is done." << endl << endl;
+
+ cout << "x = 200" << endl;
+ a.insert_element(x);
+
+ cout << "y = 300" << endl;
+ a.insert_element(y);
+
+ cout << "z = 400" << endl;
+ a.insert_element(z);
+
+ cout << "Cardinality of collection 'a' after four inserts: " << a.cardinality() << endl << endl;
+
+ cout << "Now creating an iterator for 'a'." << endl;
+
+ // ODMG wants an iterator to be created this way...
+ r_Iterator<int> iter = a.create_iterator();
+
+ // ...but this is an equally valid version that doesn't require
+ // r_Collection to have a member function create_iterator:
+ //r_Iterator<int> iter( a );
+
+ cout << "Iterator points to element: " << iter.get_element() << endl << endl
+ << "Advancing iterator two times." << endl;
+ iter.advance();
+ iter.advance();
+ cout << "Iterator points to element: " << iter.get_element() << endl << endl
+ << "Regetting this element and advancing iterator (next function)." << endl;
+ status = iter.next( i );
+ cout << "Element is " << i << "." << endl;
+ cout << "Iterator points to element: " << iter.get_element() << endl << endl
+ << "Resetting iterator." << endl;
+ iter.reset();
+ cout << "Iterator points to element: " << iter.get_element() << endl << endl;
+
+ cout << "Testing prefix and postfix incrementors." << endl;
+ r_Iterator<int> iter2 = a.create_iterator();
+ //r_Iterator<int> iter2( a );
+ iter.reset();
+ cout << "Postfix incrementor returns: " << iter++.get_element() << endl;
+ iter.reset();
+ iter2 = ++iter;
+ cout << "Prefix incrementor returns: " << iter2.get_element() << endl << endl;
+
+ cout << "Resetting both iterators." << endl;
+ iter.reset();
+ iter2.reset();
+ cout << "iter1 == iter2 ? (1=TRUE/0=FALSE) " << iter.is_equal(iter2) << endl;
+ cout << "iter1 != iter2 ? (1=TRUE/0=FALSE) " << (!iter.is_equal(iter2)) << endl << endl;
+
+ cout << "Computing all permutatios of the four numbers:" << endl;
+
+ r_Iterator<int> iter3 = a.create_iterator();
+ //r_Iterator<int> iter3( a );
+ r_Iterator<int> iter4 = a.create_iterator();
+ //r_Iterator<int> iter4( a );
+
+ for ( ; iter.not_done(); iter++ )
+ for ( iter2.reset(); iter2.not_done(); iter2++ )
+ for ( iter3.reset(); iter3.not_done(); iter3++ )
+ for ( iter4.reset(); iter4.not_done(); iter4++ )
+ if ( !(iter4.is_equal(iter3) ||
+ iter4.is_equal(iter2) ||
+ iter4.is_equal(iter) ||
+ iter3.is_equal(iter2) ||
+ iter3.is_equal(iter) ||
+ iter2.is_equal(iter) ) )
+ cout << *iter << " " << *iter2 << " " << *iter3 << " " << *iter4 << endl;
+}
diff --git a/rasodmg/test/test_lookup.cc b/rasodmg/test/test_lookup.cc
new file mode 100644
index 0000000..c18c7fa
--- /dev/null
+++ b/rasodmg/test/test_lookup.cc
@@ -0,0 +1,378 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_lookup.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+ */
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <iostream>
+#include <string.h>
+
+#include "raslib/type.hh"
+
+#ifdef __VISUALC__
+ #define __EXECUTABLE__
+ #include "include/basictypes.hh"
+ #undef __EXECUTABLE__
+#else
+ #include "include/basictypes.hh"
+#endif
+
+const int MAX_STR_LEN = 255;
+enum prg_mode {
+ USE_INVALID = 0,
+ USE_COLLNAME,
+ USE_OIDSTR
+ };
+
+using namespace std;
+
+int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex )
+{
+ int found = 0;
+ int i=1;
+
+ while( !found && i<argc )
+ found = !strcmp( searchText, argv[i++] );
+
+ if( found && i<argc && (argv[i][0] != '-') )
+ optionValueIndex = i;
+ else
+ optionValueIndex = 0;
+
+ return found;
+}
+
+
+
+void printColl( r_Ref< r_Set< r_Ref< r_GMarray > > >& image_set, int output, int rgbOutput, int hexOutput )
+{
+ std::cout << "Collection" << std::endl;
+ std::cout << " Oid...................: " << image_set->get_oid() << std::endl;
+ std::cout << " Type Name.............: " << image_set->get_object_name() << std::endl;
+ std::cout << " Type Structure........: "
+ << ( image_set->get_type_structure() ? image_set->get_type_structure() : "<nn>" ) << std::endl;
+ std::cout << " Type Schema...........: " << std::flush;
+ if( image_set->get_type_schema() )
+ image_set->get_type_schema()->print_status( std::cout );
+ else
+ std::cout << "<nn>" << std::flush;
+ std::cout << std::endl;
+ std::cout << " Number of entries.....: " << image_set->cardinality() << std::endl;
+ std::cout << " Element Type Schema...: " << std::flush;
+ if( image_set->get_element_type_schema() )
+ image_set->get_element_type_schema()->print_status( std::cout );
+ else
+ std::cout << "<nn>" << std::flush;
+ std::cout << std::endl;
+
+ if( output )
+ {
+ r_Iterator< r_Ref< r_GMarray > > iter = image_set->create_iterator();
+
+ std::cout << std::endl;
+
+ for ( int i=1 ; iter.not_done(); iter++, i++ )
+ {
+ std::cout << "Image " << i << std::endl;
+
+ if( !rgbOutput )
+ (*iter)->print_status( std::cout, hexOutput );
+ else
+ {
+ RGBImage image( **iter );
+ r_Point pt(0,0);
+
+ std::cout << "[0,0] = {" << (int)image[pt].red << ","
+ << (int)image[pt].green << ","
+ << (int)image[pt].blue << "}" << std::endl;
+ }
+ std::cout << std::endl;
+ }
+
+ std::cout << std::endl;
+ }
+}
+
+void
+printUsage(char* name) {
+ std::cout << name << "v1.1 systemtest lookup utility " << std::endl << std::endl;
+ std::cout << "Description: Systemtest lookup utility for retrival of set / marray from RasDaMan " << std::endl << std::endl;
+ std::cout << "Usage: " << name << " [options]" << std::endl << std::endl;
+ std::cout << "Options: -h ... this help" << std::endl;
+ std::cout << " -server <srvname> ... name of server.(mandatory)" << std::endl;
+ std::cout << " -port <nnnn> ... port of server.(default 7001)" << std::endl;
+ std::cout << " -base <dbname> ... name of database.(madatory)" << std::endl;
+ std::cout << " -setname <setname> ... name of collection for retrival by name.(madatory)" << std::endl;
+ std::cout << " -oid <oidset> ... oid of marray or set as string for retrival by oid.(mandatory)" << std::endl;
+ std::cout << " -user <usrname> ... user name.(default rasguest)" << std::endl;
+ std::cout << " -passwd <usrpasswd> ... user password.(default rasguest)" << std::endl;
+ std::cout << " -transferformat <format> ... transfer format.(default Array)" << std::endl;
+ std::cout << " -transferformatparams <formatparams> ... transfer format parameters.(default NULL)" << std::endl;
+ std::cout << " -storageformat <format> ... storage format.(default Array)" << std::endl;
+ std::cout << " -storageformatparams <formatparams> ... storage format parameters.(default NULL)" << std::endl;
+ std::cout << " -ia ... interactive control for multiple collection retrieval.(default off)" << std::endl;
+ std::cout << " -hex ... output in hex.(default off)" << std::endl;
+ std::cout << " -rgb ... output is rgb struct.(default off)" << std::endl;
+ std::cout << " -nooutput ... no output of MDD content.(default on)" << std::endl;
+ std::cout << " -testbed ... turn on output for testbed.(default off)" << std::endl;
+
+ std::cout << std::endl << std::endl;
+
+ std::cout << "Report bugs to <support@active­knowledge.com>" << std::endl;
+}
+
+int main( int argc, char** argv )
+{
+ int interactive=0;
+ int output=0;
+ int optionValueIndex=0;
+ char key = 'a';
+ int hexOutput = 0;
+ int rgbOutput = 0;
+ prg_mode mode=USE_INVALID;
+ int testbed = 0;
+
+ r_Data_Format transferFormat=r_Array;
+ char *transferFormatParams = NULL;
+ r_Data_Format storageFormat=r_Array;
+ char *storageFormatParams = NULL;
+
+ char *serverName="";
+ r_ULong serverPort = 7001;
+ char *baseName="";
+
+ char *collName="";
+ char *oidString="";
+
+ char *userName="rasguest";
+ char *userPasswd="rasguest";
+
+#ifdef TEST_LOOKUP
+ r_GMarray* transImage = 0;
+ r_Ref<r_GMarray> transImageRef = 0;
+#endif
+
+ if( checkArguments( argc, argv, "-h", optionValueIndex ) ) {
+ printUsage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+
+ if( checkArguments( argc, argv, "-server", optionValueIndex ) && optionValueIndex )
+ serverName=argv[optionValueIndex];
+
+ if( checkArguments( argc, argv, "-base", optionValueIndex ) && optionValueIndex )
+ baseName=argv[optionValueIndex];
+
+ if( checkArguments( argc, argv, "-setname", optionValueIndex ) && optionValueIndex ) {
+ collName=argv[optionValueIndex];
+ mode=USE_COLLNAME;
+ }
+
+ if( checkArguments( argc, argv, "-oid", optionValueIndex ) && optionValueIndex ) {
+ oidString=argv[optionValueIndex];
+ if(mode != USE_INVALID) {
+ std::cerr << "Use -setname or -oid, not both in the same time" << std::endl;
+ printUsage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ mode=USE_OIDSTR;
+ }
+
+ if(!strcmp(serverName, "") ||
+ !strcmp(baseName, "") ||
+ (mode == USE_INVALID) ) {
+ std::cerr << "Mandatory parameters are missing!" << std::endl;
+ printUsage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+
+ if( checkArguments( argc, argv, "-port", optionValueIndex ) && optionValueIndex )
+ serverPort = strtoul( argv[optionValueIndex], (char **)NULL, 10 ) ;
+
+ if( checkArguments( argc, argv, "-user", optionValueIndex ) && optionValueIndex )
+ strcpy( userName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-passwd", optionValueIndex ) && optionValueIndex )
+ strcpy( userPasswd, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-transferformat", optionValueIndex ) && optionValueIndex ) {
+ transferFormat = get_data_format_from_name( argv[optionValueIndex] );
+ if(transferFormat == r_Data_Format_NUMBER) {
+ std::cerr << "Invalid transfer format '" << argv[optionValueIndex] << "' switched to " << r_Array << std::endl;
+ transferFormat = r_Array;
+ }
+ }
+
+ if( checkArguments( argc, argv, "-transferformatparams", optionValueIndex ) && optionValueIndex )
+ transferFormatParams = argv[optionValueIndex] ;
+
+ if( checkArguments( argc, argv, "-storageformat", optionValueIndex ) && optionValueIndex ) {
+ storageFormat = get_data_format_from_name(argv[optionValueIndex] );
+ if(storageFormat == r_Data_Format_NUMBER) {
+ std::cerr << "Invalid storage format '" << argv[optionValueIndex] << "' switched to " << r_Array << std::endl;
+ storageFormat = r_Array;
+ }
+ }
+
+ if( checkArguments( argc, argv, "-storageformatparams", optionValueIndex ) && optionValueIndex )
+ storageFormatParams = argv[optionValueIndex] ;
+
+ interactive = checkArguments( argc, argv, "-ia", optionValueIndex );
+ output = !checkArguments( argc, argv, "-nooutput", optionValueIndex );
+ hexOutput = checkArguments( argc, argv, "-hex", optionValueIndex );
+ rgbOutput = checkArguments( argc, argv, "-rgb", optionValueIndex );
+ testbed = checkArguments( argc, argv, "-testbed", optionValueIndex );
+
+ std::cout << std::endl << std::endl;
+ std::cout << "ODMG conformant lookup of Marrays" << std::endl;
+ std::cout << "=================================" << std::endl << std::endl;
+
+ r_Database db;
+ r_Transaction ta;
+
+
+
+ try
+ {
+ std::cout << "Opening database '" << baseName << "' on server '" << serverName << "':" << serverPort
+ << " using user '" << userName << "':'" << userPasswd << "' ... " << std::flush;
+ db.set_servername( serverName, serverPort );
+ db.set_useridentification( userName, userPasswd );
+ db.open( baseName );
+ std::cout << "OK" << std::endl;
+
+ while( key != 'q' )
+ {
+ std::cout << "Starting Read Only Transaction ... " << std::flush;
+ ta.begin( r_Transaction::read_only );
+ std::cout << "OK" << std::endl;
+
+ if( mode == USE_COLLNAME )
+ {
+ r_Ref< r_Set< r_Ref< r_GMarray > > > image_set;
+
+ std::cout << "Looking up collection by name " << collName << " ..." << std::flush;
+ image_set = db.lookup_object( collName );
+ std::cout << "OK" << std::endl;
+
+ printColl( image_set, output, rgbOutput, hexOutput );
+ }
+ else
+ {
+ r_Ref<r_Object> persObject;
+ r_OId oid( oidString );
+
+ std::cout << "Looking up object by oid " << oid << " ..." << std::flush;
+ persObject = db.lookup_object( oid );
+ std::cout << "OK" << std::endl;
+
+ std::cout << "Object type: " << persObject->get_type_structure() << std::endl;
+
+ if( strstr( persObject->get_type_structure(), "set" ) )
+ {
+ r_Ref< r_Set< r_Ref< r_GMarray > > > image_set = (r_Ref_Any) persObject;
+
+ printColl( image_set, output, rgbOutput, hexOutput );
+ }
+ else
+ {
+ r_Ref<r_GMarray> marray = (r_Ref_Any) persObject;
+
+ std::cout << "MDD object with domain " << marray->spatial_domain()
+ << " and type " << marray->get_type_name() << std::endl;
+
+ if( output )
+ marray->print_status( std::cout );
+
+#ifdef TEST_LOOKUP
+ // make a copy for use after ta
+ transImage = new r_GMarray( (const r_GMarray&)*marray );
+ transImageRef = new("type") r_GMarray( (const r_GMarray&)*marray );
+#endif
+ }
+
+ std::cout << std::endl;
+ }
+
+ std::cout << "Commiting Transaction ... " << std::flush;
+ ta.commit();
+ std::cout << "OK" << std::endl;
+
+ if( interactive )
+ {
+ std::cout << "Command (q=quit, a=again): ";
+ cin >> key;
+ }
+ else
+ key = 'q';
+
+ }
+
+ std::cout << "Closing Database ... " << std::flush;
+ db.close();
+ std::cout << "OK" << std::endl;
+
+ }
+ catch( r_Error& errorObj )
+ {
+ ta.abort();
+ db.close();
+ std::cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+#ifdef TEST_LOOKUP
+ if( transImage )
+ {
+ std::cout << "Transient MDD object with domain " << transImage->spatial_domain()
+ << " and type " << transImage->get_type_name() << std::endl;
+
+ transImage->print_status( std::cout, hexOutput );
+
+ delete transImage;
+ }
+
+ if( transImageRef != 0 )
+ {
+ std::cout << "Transient MDD object with domain " << transImageRef->spatial_domain()
+ << " and type " << transImageRef->get_type_name() << std::endl;
+
+ transImageRef->print_status( std::cout, hexOutput );
+
+ transImageRef.destroy();
+ }
+#endif
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/rasodmg/test/test_marray.cc b/rasodmg/test/test_marray.cc
new file mode 100644
index 0000000..210db3f
--- /dev/null
+++ b/rasodmg/test/test_marray.cc
@@ -0,0 +1,110 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_marray.cc
+ *
+ * MODULE: raslib
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <iostream>
+
+#include "rasodmg/marray.hh"
+
+#include "raslib/minterval.hh"
+#include "raslib/sinterval.hh"
+#include "raslib/point.hh"
+#include "raslib/error.hh"
+
+static int INIT = 0;
+
+int initFunction( const r_Point& /*pt*/ )
+{
+ /*
+ int value=0;
+
+ for( int i=0; i< pt.dimension(); i++ )
+ value += pt[i];
+
+ return value;
+ */
+ return INIT++;
+}
+
+
+int main()
+{
+ cout << endl << endl;
+ cout << "Marray Examples" << endl;
+ cout << "===============" << endl << endl;
+
+ cout << "Initialization of Marray<int, [0:2,3:5,6:8]> with init function:" << endl;
+ r_Minterval domain(3);
+ domain << r_Sinterval(0,2) << r_Sinterval(3,5) << r_Sinterval(6,8);
+ r_Marray<int> a( domain, &initFunction );
+ cout << "OK" << endl;
+ a.print_status( cout );
+
+ cout << "Value [0,3,6] = " << a[r_Point(0,3,6)] << endl;
+ cout << "Changing to 99" << endl;
+ a[r_Point(0,3,6)] = 99;
+ cout << "New value [0,3,6] = " << a[r_Point(0,3,6)] << endl;
+
+ cout << endl << "Projection operator:" << endl;
+ cout << "project a[1]" << endl;
+ r_Marray<int> b = a[1];
+ b.print_status( cout );
+
+ cout << endl << "Projection and cast operator a[r_Point(1,4,7)] :" << endl;
+ cout << "a[1][4][7] = " << (int)(a[ r_Point(1,4,7) ]) << endl;
+
+ cout << endl << "Projection and cast operator a[1][4][7] :" << endl;
+ cout << "a[1][4][7] = " << (int)(a[1][4][7]) << endl;
+
+ cout << endl << "Triming operator:" << endl;
+ cout << "trim a[1:3, 4:6, 7:9]" << endl;
+ r_Marray<int> c = a[ r_Minterval(3) << r_Sinterval(1,3) << r_Sinterval(4,6) << r_Sinterval(7,9) ];
+ c.print_status( cout );
+
+ cout << "Initialization of Marray<char, [0:2,0:2,0:2]> with 'A'" << endl;
+ r_Minterval domain2(3);
+ domain2 << r_Sinterval(0,2) << r_Sinterval(0,2) << r_Sinterval(0,2);
+ r_Marray<char> a_char( domain2, 'A' );
+ cout << "OK" << endl;
+ a_char.print_status( cout );
+
+ cout << "Transforming the object GMarray( [0:2,0:2,0:2], 4 ) to Marray<int>( [...] )" << endl;
+ r_GMarray genMDD( domain2, 4 );
+ r_Marray<int> specMDD( genMDD );
+
+ cout << specMDD.spatial_domain() << endl;
+
+ return 0;
+}
diff --git a/rasodmg/test/test_oqlquery.cc b/rasodmg/test/test_oqlquery.cc
new file mode 100644
index 0000000..1fe0839
--- /dev/null
+++ b/rasodmg/test/test_oqlquery.cc
@@ -0,0 +1,157 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_sinterval.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <iostream>
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <iostream>
+#include "rasodmg/oqlquery.hh"
+
+int main()
+{
+ cout << endl << endl;
+ cout << "r_OQL_Query Examples" << endl;
+ cout << "====================" << endl << endl;
+
+
+ // 1. Example
+
+ cout << "1. Initializing with two string arguments." << endl;
+ r_OQL_Query q1("select d from $1 where d.id = $2");
+
+ try
+ {
+ q1 << "Images d" << "<id>";
+ }
+ catch( r_Error& err )
+ {
+ cout << err.what() << endl;
+ }
+
+ cout << "Parameterized query string : " << q1.get_parameterized_query() << endl;
+ cout << "Query string : " << q1.get_query() << endl << endl;
+
+
+ // 2. Example
+
+ cout << "2. Initializing with too many arguments." << endl;
+ r_OQL_Query q2("select d from $1 where d.id = $2");
+
+ try
+ {
+ q2 << "Images d" << "<id>" << "too many";
+ }
+ catch( r_Error& err )
+ {
+ cout << err.what() << endl;
+ }
+
+ cout << "Parameterized query string : " << q2.get_parameterized_query() << endl;
+ cout << "Query string : " << q2.get_query() << endl << endl;
+
+
+ // 3. Example
+
+ cout << "3. Initializing with different arguments." << endl;
+ r_OQL_Query q3("select $1 from $2 $3 where d.id1 = $4 and d.id2 = $5");
+
+ try
+ {
+ q3 << (unsigned char)'d' << "Images" << (unsigned char)'d' << (r_Long)100l << (r_Long)20l;
+ }
+ catch( r_Error& err )
+ {
+ cout << err.what() << endl;
+ }
+
+ cout << "Parameterized query string : " << q3.get_parameterized_query() << endl;
+ cout << "Query string : " << q3.get_query() << endl << endl;
+
+ // 4. Example
+
+ cout << "4. Initializing with different arguments." << endl;
+ r_OQL_Query q4("select d$1 from $2 as d where some( d$3 > $4 )");
+
+ try
+ {
+ q4 << ( r_Minterval(2) << r_Sinterval((r_Long)100l,(r_Long)199l) << r_Sinterval((r_Long)200l,(r_Long)299l) )
+ << "Images"
+ << ( r_Minterval(2) << r_Sinterval((r_Long)300l,(r_Long)399l) << r_Sinterval((r_Long)400l,(r_Long)499l) )
+ << (r_Long)127l;
+ }
+ catch( r_Error& err )
+ {
+ cout << err.what() << endl;
+ }
+
+ cout << "Parameterized query string : " << q4.get_parameterized_query() << endl;
+ cout << "Query string : " << q4.get_query() << endl << endl;
+
+ // 5. Example
+
+ cout << "4. Initializing with different arguments." << endl;
+ r_OQL_Query q5("update upd1 as a set a assign $1 *$2*3");
+
+ try
+ {
+ r_GMarray mdd;
+
+ cout << "Parameterized query string : " << q5.get_parameterized_query() << endl;
+ cout << "Query string : " << q5.get_query() << endl << endl;
+ q5 << mdd;
+ cout << "Parameterized query string : " << q5.get_parameterized_query() << endl;
+ cout << "Query string : " << q5.get_query() << endl << endl;
+ q5 << mdd;
+ cout << "Parameterized query string : " << q5.get_parameterized_query() << endl;
+ cout << "Query string : " << q5.get_query() << endl << endl;
+ }
+ catch( r_Error& err )
+ {
+ cout << err.what() << endl;
+ }
+
+ cout << "Parameterized query string : " << q5.get_parameterized_query() << endl;
+ cout << "Query string : " << q5.get_query() << endl << endl;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/rasodmg/test/test_polygon.cc b/rasodmg/test/test_polygon.cc
new file mode 100644
index 0000000..bee92bc
--- /dev/null
+++ b/rasodmg/test/test_polygon.cc
@@ -0,0 +1,951 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_polygon.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+ */
+
+#include "mymalloc/mymalloc.h"
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+extern "C" {
+ #include "tiffio.h"
+}
+
+#include <iostream>
+#include <vector>
+
+using std::vector;
+using std::iterator;
+
+#include <stdio.h>
+#include <math.h>
+#include <ctype.h>
+#if defined(SOLARIS)
+#include <strings.h>
+#else
+#include <string.h>
+#endif
+
+#include "rasodmg/polygon.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/oqlquery.hh"
+#include "rasodmg/fastscale.hh"
+#include "raslib/basetype.hh"
+#include "raslib/mitera.hh"
+#include "raslib/shhopt.h"
+#include "rasodmg/ref.hh"
+#include "conversion/tiff.hh"
+
+#include "cmlinterpreter.hh"
+#include "cmloption.hh"
+#include "cmlerror.hh"
+
+// global limits
+static const int MYSTRINGSIZE = 256;
+static const int SUCCES = 0;
+static const int FAILED = 1;
+
+// global variable used in this program
+r_Database db;
+r_Transaction ta;
+r_Float rScale;
+char* rBgr=NULL;
+r_Polygon poly;
+
+// default values & constants
+static const char* DefaultSrv = "localhost";
+static const char* DefaultPort = "7001";
+static const char* DefaultDb = "RASBASE";
+static const char* DefaultUsr = "rasguest";
+static const char* DefaultPasswd = "rasguest";
+static const r_Float DefaultScale = 1.;
+
+
+
+
+// parameters of this program
+CmlInterpreter cmlInter;
+CmlStringOption cmlSrv('s',"server", "srv-name", "name of machine running RasDaMan manager. Default: localhost");
+CmlStringOption cmlPort(0,"port", "nnnn", "port number used by RasDaMan manager. Default: 7001");
+CmlStringOption cmlDb('d',"database", "db-name", "name of database. Default: RASBASE).");
+CmlStringOption cmlUsr(0, "user", "user-name", "name of user. Default rasguest");
+CmlStringOption cmlPasswd(0,"passwd", "user-passwd", "password of user. Default rasguest");
+CmlStringOption cmlColl('c',"collname", "coll-name", "name of collection. Mandatory");
+CmlStringOption cmlDomain('r',"domain", "domain", "domain to be retrieved (e.g. \"[1000:8000,5000:10000]\"). Mandatory");
+CmlStringOption cmlScale('f',"scale", "factor", "scale factor applied to domain. Default 1");
+CmlStringOption cmlFile('t',"tiffile", "file-name", "name of TIFF file written. Mandatory");
+CmlStringOption cmlPolygon('p',"polygon", "pol-desc","polygon for clipping (e.g. \"[1010,8200] [4000,8200] [3000,9800]\").");
+CmlStringOption cmlBgr('b',"background", "bgr-desc", "background of TIFF file (e.g. 0x1f).");
+CmlBoolOption cmlHelp('h',"help","print this message.");
+
+
+
+// This is a quick first try at a class for creating TIFFs stripe by stripe. It copies
+// a lot of code from class r_Conv_TIFF in conversion/tiff.cc. Ideally this at some
+// point should make use of Andreas' conversion framework.
+
+class r_TIFFStripe
+{
+public:
+ r_TIFFStripe(const char* newFileName, const r_Minterval& tiffDom);
+ void openTiff(); //open the tiff file
+ bool addArray(const r_GMarray& myArray); //write myArray to tiff file
+ void closeTiff(); //close the tiff file
+ ~r_TIFFStripe();
+private:
+ char* fileName; //filename of the tiff image
+ TIFF* tiffFile; //handler of the tiff image
+ uint16 bpp; // bits per pixel (24 for RGB)
+ uint16 bps; // bits per sample (8 for RGB)
+ unsigned long typeSize; // size of base type, will be retrieved with r_Base_Type::size()
+ uint32 width; // image width
+ uint32 height; //image height
+ char* scanLine; // buffer for scanLine to be written to file
+ uint32 tiffRow; // row's no of tiff image
+};
+
+r_TIFFStripe::r_TIFFStripe(const char* newFileName, const r_Minterval& tiffDom)
+ : bpp(8), bps(8), typeSize(1), tiffRow(0), fileName(NULL), tiffFile(NULL), scanLine(NULL)
+{
+ fileName = strdup(newFileName);
+ width = (uint32)(tiffDom.get_extent()[0]);
+ height = (uint32)(tiffDom.get_extent()[1]);
+ // copied this formula from Andreas, do not fully get it. 31 seems to be an internal
+ // buffer for tifflib and >> 5 together with uint32 instead of char seems to be used
+ // to get the correct number of chars as oppose to bits.
+
+ //allocate the buffer
+ scanLine = (char*)mymalloc(width*typeSize);
+}
+
+void
+r_TIFFStripe::openTiff()
+{
+ uint16 cmap[256]; // Colour map (for greyscale images)
+
+ tiffFile = TIFFOpen(fileName, "w");
+
+ // These fields are written to the file by TIFFWriteDirectory, which is automatically
+ // called by TIFFClose and TIFFFlush
+
+ TIFFSetField(tiffFile, TIFFTAG_ARTIST, "RasDaMan");
+ TIFFSetField(tiffFile, TIFFTAG_DOCUMENTNAME, "Image");
+ TIFFSetField(tiffFile, TIFFTAG_SOFTWARE, "RasDaMan");
+ //TIFFSetField(tiffFile, TIFFTAG_SUBFILETYPE, (uint32)0);
+ TIFFSetField(tiffFile, TIFFTAG_IMAGEWIDTH, width);
+ TIFFSetField(tiffFile, TIFFTAG_IMAGELENGTH, height);
+ TIFFSetField(tiffFile, TIFFTAG_BITSPERSAMPLE, bps);
+ // UNIX doesn't mind which fill-order. NT only understands this one.
+ TIFFSetField(tiffFile, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
+ // problem: LZW is no longer supported in current versions of libtiff.
+ TIFFSetField(tiffFile, TIFFTAG_COMPRESSION, (uint16)COMPRESSION_NONE);
+ TIFFSetField(tiffFile, TIFFTAG_ORIENTATION, (uint16)ORIENTATION_TOPLEFT);
+
+ // Format-dependent tags, currently support only 8bit grey images
+ TIFFSetField(tiffFile, TIFFTAG_PHOTOMETRIC, (uint16)PHOTOMETRIC_PALETTE);
+ TIFFSetField(tiffFile, TIFFTAG_SAMPLESPERPIXEL, (uint16)1);
+ TIFFSetField(tiffFile, TIFFTAG_PLANARCONFIG, (uint16)PLANARCONFIG_CONTIG);
+ // TIFFSetField(tiffFile, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiffFile, (uint32)-1));
+ TIFFSetField(tiffFile, TIFFTAG_ROWSPERSTRIP, (uint32)1);
+ //TIFFSetField(tiffFile, TIFFTAG_MINSAMPLEVALUE, (uint16)0);
+ //TIFFSetField(tiffFile, TIFFTAG_MAXSAMPLEVALUE, (uint16)255);
+ TIFFSetField(tiffFile, TIFFTAG_RESOLUTIONUNIT, (uint16)RESUNIT_INCH);
+
+ // This will have to be adapted!
+ TIFFSetField(tiffFile, TIFFTAG_XRESOLUTION, (float)90.0);
+ TIFFSetField(tiffFile, TIFFTAG_YRESOLUTION, (float)90.0);
+ TIFFSetField(tiffFile, TIFFTAG_XPOSITION, (float)0.0);
+ TIFFSetField(tiffFile, TIFFTAG_YPOSITION, (float)0.0);
+
+ // build the colour-map (greyscale, i.e. all 3 components identical)
+ // TIFF needs 16 bit values for this (--> tools/tiffdither.c)
+ for (int i=0; i<256; i++) cmap[i] = (uint16)(i*((1L << 16) - 1)/255);
+ TIFFSetField(tiffFile, TIFFTAG_COLORMAP, cmap, cmap, cmap);
+}
+
+bool
+r_TIFFStripe::addArray(const r_GMarray& myArray)
+{
+ // here we write the r_GMarray we get line by line into the TIFF. We
+ // assume that the width of myArray (width = [0] r_Sinterval)
+ // corresponds to the width of the whole TIFF.
+
+ unsigned long imageHeight = myArray.spatial_domain().get_extent()[1];
+ unsigned long imageWidth = myArray.spatial_domain().get_extent()[0];
+
+ if(imageWidth != width)
+ {
+ cout << "Error Tiff file \"" << fileName << "\" initialised for "
+ << width << ", not for " << imageWidth << " !" << endl;
+ return false;
+ }
+
+ const char* linePtr = myArray.get_array(); // points to myArray's data
+ char* scanLinePtr = (char*)scanLine;
+
+
+ for (int row = 0; row < imageHeight; row++) {
+ // copy data (and transpose)
+ for (int col=0; col < imageWidth; col++) {
+ for(int i=0; i<typeSize; i++) {
+ *scanLinePtr++ = *(linePtr + col*imageHeight*typeSize + row*typeSize + i);
+ }
+ // not really fast and does not work for all types! Good enough for now.
+ }
+ if(TIFFWriteScanline(tiffFile, (tdata_t)scanLine, tiffRow++, 0) < 0)
+ {
+ // error
+ cerr << "Error writing line into file " << fileName << "." << endl;
+ return false;
+ }
+ memset(scanLine, 0, imageWidth*typeSize);
+ scanLinePtr = (char*)scanLine;
+ }
+
+ return true;
+}
+
+void
+r_TIFFStripe::closeTiff()
+{
+ TIFFClose(tiffFile);
+}
+
+r_TIFFStripe::~r_TIFFStripe()
+{
+ if(fileName)
+ free(fileName);
+ if(scanLine)
+ free(scanLine);
+}
+
+void
+printUsage(char* name)
+{
+ static const char* ExColl="lva";
+ static const char* ExDomain="[0:100,0:100]";
+ static const char* ExFile="lva.tif";
+
+ cout << name << " v1.0 - RasDaMan Export Utility for 2D marrays" << endl;
+ cout << "Description: Exports data with background, from RasDaMan database from a fastscale collection" << endl;
+ cout << " for a domain with a scale." << endl;
+ cout << " Returns " << SUCCES << " for succes, otherwise " << FAILED << endl;
+ cout << "Notes: If a polygon is specified, the result is a image which has data inside the polygon and"<< endl;
+ cout << " the rest is filled with background color." << endl;
+
+ cout << "Usage options:" << endl;
+ cmlInter.printHelp();
+
+ cout << "For example:" << endl;
+ cout << name << "\t" << cmlSrv.getLongFormTag() << " " << DefaultSrv << " ";
+ cout << cmlPort.getLongFormTag() << " " << DefaultPort << " ";
+ cout << cmlDb.getLongFormTag() << " " << DefaultDb << " ";
+ cout << cmlColl.getLongFormTag() << " " << ExColl << " ";
+ cout << endl << "\t\t" << cmlDomain.getLongFormTag() << " " << ExDomain << " ";
+ cout << cmlScale.getLongFormTag() << " " << DefaultScale << " ";
+ cout << cmlFile.getLongFormTag() << " " << ExFile << " ";
+ cout << endl << "\t\t" << cmlUsr.getLongFormTag() << " " << DefaultUsr << " ";
+ cout << cmlPasswd.getLongFormTag() << " " << DefaultPasswd << " ";
+ cout << endl;
+
+ cout << "Report bugs to <support@active­knowledge.com>" << endl;
+}
+
+void
+printStatus(char* name)
+{
+ cout << name << "'s parameters list:" << endl;
+ cmlInter.printStatus();
+}
+
+void
+defineParams()
+{
+ cmlInter.defineOption(&cmlSrv);
+ cmlInter.defineOption(&cmlPort);
+ cmlInter.defineOption(&cmlDb);
+ cmlInter.defineOption(&cmlUsr);
+ cmlInter.defineOption(&cmlPasswd);
+ cmlInter.defineOption(&cmlColl);
+ cmlInter.defineOption(&cmlDomain);
+ cmlInter.defineOption(&cmlScale);
+ cmlInter.defineOption(&cmlFile);
+ cmlInter.defineOption(&cmlPolygon);
+ cmlInter.defineOption(&cmlBgr);
+ cmlInter.defineOption(&cmlHelp);
+}
+
+void
+getParams()
+{
+ CmlOption* ptr=NULL;
+
+ ptr=cmlInter.getOption(&cmlSrv);
+ cmlSrv=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlPort);
+ cmlPort=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlDb);
+ cmlDb=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlUsr);
+ cmlUsr=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlPasswd);
+ cmlPasswd=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlColl);
+ cmlColl=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlDomain);
+ cmlDomain=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlScale);
+ cmlScale=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlFile);
+ cmlFile=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlPolygon);
+ cmlPolygon=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlBgr);
+ cmlBgr=*((CmlStringOption*)ptr);
+
+ ptr=cmlInter.getOption(&cmlHelp);
+ cmlHelp=*((CmlBoolOption*)ptr);
+
+ ptr=NULL;
+}
+
+bool
+parseParams(int argc, char** argv)
+{
+ try
+ {
+ defineParams();
+ cmlInter.interpretArguments(argc, argv);
+ getParams();
+ }
+ catch(CmlError& err)
+ {
+ cout << "Command Line Parsing Error:" << endl << err.getText() << endl;
+ return false;
+ }
+
+ //check rule
+ if(cmlColl.isPresent() &&
+ cmlDomain.isPresent() &&
+ cmlFile.isPresent()
+ )
+ return true;
+ else
+ {
+ cout << "Error some of mandatory arguments are missing!" << endl;
+ cout << "Please check your command line!" << endl;
+ return false;
+ }
+}
+
+bool
+fillPolygon(r_Polygon& myPoly)
+{
+
+ char* startPos = (char*)cmlPolygon.getString();
+ char* endPos=NULL;
+ int pointStrLen=0, pointNo=0;
+ char currPoint[MYSTRINGSIZE];
+ r_Point myPoint;
+
+
+ //cout << "start decoding polygon string"<< endl;
+
+ while(true)
+ {
+ strcpy(currPoint, "");
+ startPos = index(startPos, '[');
+ if(!startPos) {
+ // Did not find a closing [, that's it.
+ break;
+ }
+
+ endPos = index(startPos, ']');
+ if(!endPos) {
+ // Did not find a closing ], that's it.
+ break;
+ }
+
+ // try to add point
+ pointStrLen = endPos - startPos + 1;
+ strncpy(currPoint, startPos, pointStrLen);
+ currPoint[pointStrLen+1] = '\0';
+
+ try
+ {
+ myPoint=r_Point(currPoint);
+ myPoly.addPoint( myPoint );
+ pointNo++;
+ //cout << "-point " << pointNo << " : " << currPoint << endl;
+ }
+ catch(r_Error& err)
+ {
+ cout << "Error decoding point \"" << currPoint << "\" from polygon string \""
+ << cmlPolygon.getString() << " !" << endl;
+ return false;
+ }
+ startPos += pointStrLen;
+ }
+
+ if(!pointNo)
+ {
+ cout << "Error no points found, while decoding polygon string \"" << cmlPolygon.getString() << "\" !" << endl;
+ return false;
+ }
+
+ //cout << "end decoding"<< endl;
+
+ myPoly.close();
+
+ return true;
+}
+
+bool
+parseBgr()
+{
+ static char hexval[]= { 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f,
+ };
+ static char hexfig[]= { '0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f',
+ '\0'};
+
+ static r_Bytes sizeBgrMin=2, sizeHexFig=strlen(hexfig);
+ char* pBgr=(char*)cmlBgr.getString();
+ r_Bytes sizeBgr=strlen(pBgr), sizerBgr=0, indexFigure=0, indexHexFig=0;
+
+ if(sizeBgr <= sizeBgrMin)
+ {
+ cout << "Error decoding background \"" << pBgr << "\", is not a hex string !" << endl;
+ return false;
+ }
+
+ if (pBgr[0] !='0' || (pBgr[1] != 'x' && pBgr[1]!='X'))
+ {
+ cout << "Error decoding background \"" << pBgr << "\", 0x or 0X is missing !" << endl;
+ return false;
+ }
+
+ if(sizeBgr%sizeBgrMin)
+ {
+ sizerBgr=(sizeBgr-sizeBgrMin+1)/sizeBgrMin;
+ }
+ else
+ sizerBgr=(sizeBgr-sizeBgrMin)/sizeBgrMin;
+
+ rBgr=new char [sizeBgr+1];
+ memset(rBgr,'\0', sizeBgr+1);
+
+ //skip tag 0x/0X
+ pBgr+=sizeBgrMin;
+
+ while (*pBgr)
+ {
+ //check figure
+ indexHexFig=0;
+ while(indexHexFig<sizeHexFig)
+ {
+ if (tolower(*pBgr) == hexfig[indexHexFig])
+ break;
+ indexHexFig++;
+ }
+
+ if(indexHexFig>=sizeHexFig)
+ {
+ cout << "Error decoding background \"" << pBgr << "\", \"" << *pBgr << "\" is no a hex value !" << endl;
+ delete[] rBgr;
+ return false;
+ }
+
+ //set value figure
+ if(indexFigure%sizeBgrMin)
+ {
+#if defined(LITTLE_ENDIAN)
+ rBgr[indexFigure/sizeBgrMin]=rBgr[indexFigure/sizeBgrMin] * 16 + hexval[indexHexFig];
+#else
+ rBgr[indexFigure/sizeBgrMin]=rBgr[indexFigure/sizeBgrMin]+ hexval[indexHexFig] * 16;
+#endif
+ }
+ else
+ rBgr[indexFigure/sizeBgrMin]=hexval[indexHexFig];
+
+ //advance
+ pBgr++;
+ indexFigure++;
+ }
+
+ return true;
+}
+
+
+bool
+detectParams()
+{
+ r_Long rPort=0;
+
+ // server name
+ if(!cmlSrv.isPresent())
+ cmlSrv.setValue(DefaultSrv);
+
+ // server port
+ if(!cmlPort.isPresent())
+ cmlPort.setValue(DefaultPort);
+ else
+ {
+ try
+ {
+ rPort=cmlPort.getLong();
+ }
+ catch(CmlError& err)
+ {
+ cout << "Error decoding " << cmlPort.getLongForm() << " \"" << cmlPort.getString()
+ << "\" isn't a number!" << endl;
+ return false;
+ }
+ if (rPort <= 0.)
+ {
+ cout << "Error decoding " << cmlPort.getLongForm() << " \"" << cmlPort.getString()
+ << "\" is negative or zero !" << endl;
+ return false;
+ }
+ }
+
+ // database name
+ if(!cmlDb.isPresent())
+ cmlDb.setValue(DefaultDb);
+
+ // user name
+ if(!cmlUsr.isPresent())
+ cmlUsr.setValue(DefaultUsr);
+
+ // user passord
+ if(!cmlPasswd.isPresent())
+ cmlPasswd.setValue(DefaultPasswd);
+
+ // scale factor
+ if(!cmlScale.isPresent())
+ rScale=DefaultScale;
+ else
+ {
+ try
+ {
+ rScale=cmlScale.getDouble();
+ }
+ catch(CmlError& err)
+ {
+ cout << "Error decoding " << cmlScale.getLongForm() << " \"" << cmlScale.getString()
+ << "\" isn't a number!" << endl;
+ return false;
+ }
+ if (rScale <= 0.)
+ {
+ cout << "Error decoding " << cmlScale.getLongForm() << " \"" << cmlScale.getString()
+ << "\" is negative or zero !" << endl;
+ return false;
+ }
+ }
+
+ // collection name
+ // nothing to check here
+
+ // collection domain
+ try
+ {
+ r_Minterval test(cmlDomain.getString());
+ }
+ catch(r_Error& err)
+ {
+ cout << "Error while decoding " << cmlDomain.getLongForm() << " \"" << cmlDomain.getString() << "\" !" << endl;
+ cout << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ return false;
+ }
+
+ // filename
+ //nothing to be checked here
+
+ // polygon
+ if(cmlPolygon.isPresent())
+ {
+ if(!fillPolygon(poly))
+ return false;
+
+ //FIXME
+ //is convex?
+ if(poly.detectPolygonType()!=r_Polygon::CONVEX)
+ {
+ cout << "We support only simple convex polygon now. Please check your polygon !" << endl;
+ return false;
+ }
+ }
+
+ // background
+ if(cmlBgr.isPresent())
+ return parseBgr();
+
+ return true;
+}
+
+
+
+bool
+exportData()
+{
+
+ // At the moment we do just a quick check for the TIFF writing using r_Conversion.
+ // Now we do a query and store the result as a TIFF using r_Conversion.
+
+ // Ok, the whole TIFF conversion thing is done below. Now let's get an
+ // array from RasDaMan here.
+ r_Ref<r_GMarray> mddObj;
+ r_Fast_Base_Scale *scaler=NULL;
+ r_Minterval trimDom(cmlDomain.getString());
+ r_Minterval tiffDom, currDom, insertionUnit(2), clipDom(2);
+ r_Minterval collDom;
+ r_Point trimExtent;
+ r_Polygon myPoly;
+
+ // 5 MB buffer for spooling images
+ r_ULong bufSize = 5 * 1024 * 1024;
+ //size of base type
+ r_Bytes typeSize = 1;
+ // no of scan lines in buffer
+ r_ULong numScanLineInBuf=0;
+ //tiff strip object
+ r_TIFFStripe* myTiff=NULL;
+
+ try
+ {
+ db.set_servername(cmlSrv.getString(), cmlPort.getLong());
+ db.set_useridentification(cmlUsr.getString(), cmlPasswd.getString());
+ db.open(cmlDb.getString());
+
+ try
+ {
+ ta.begin( r_Transaction::read_only );
+ scaler = new r_Fast_Scale<r_Char>(cmlColl.getString());
+ collDom = scaler->get_full_domain();
+ }
+ catch( r_Error& errorObj )
+ {
+ cout << "Error while initializing collection " << cmlColl.getString() << " !" << endl;
+ cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << endl;
+ ta.abort();
+ db.close();
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+ return false;
+ }
+
+ if (!collDom.covers(trimDom))
+ {
+ cout << "Error, the requested domain " << trimDom << " is not in the collection domain " << collDom << " !" << endl;
+
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ ta.abort();
+ db.close();
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+
+ return false;
+ }
+
+ // Ok, now here we split the domain in stripes. We take a roughly 5 MB buffer. It
+ // is calculated using the original domain of the area to be retrieved and scale^2
+ // to calculate the memory used without calculating the domains back and forth.
+
+ insertionUnit[0] = trimDom[0]; // we take the whole width of the image.
+
+ trimExtent=trimDom.get_extent();
+ numScanLineInBuf = bufSize / ( typeSize * trimExtent[0] * rScale * rScale);
+ numScanLineInBuf = numScanLineInBuf > trimExtent[1] ? trimExtent[1] : numScanLineInBuf;
+
+ if(numScanLineInBuf < 1) //if numScanLine is 0 as result of division
+ numScanLineInBuf=1;
+
+ insertionUnit[1] = r_Sinterval((r_Range)0, (r_Range)(numScanLineInBuf - 1));
+
+ try {
+ scaler->get_scaled_domain(trimDom, tiffDom, rScale);
+ }
+ catch( r_Error& errorObj ){
+ cout << "Error while getting the scaled domain !" << endl;
+ cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << endl;
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ ta.abort();
+ db.close();
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+ return false;
+ }
+
+
+ if(cmlPolygon.isPresent())
+ {
+ // we scale the polygon according to the scale factor
+ cout << "Defined Polygon: " << poly << endl;
+ poly.scale(collDom.get_origin(), rScale);
+ cout << "Scaled Polygon: " << poly << endl;
+ }
+
+ myTiff = new r_TIFFStripe(cmlFile.getString(), tiffDom);
+ myTiff->openTiff();
+
+ cout << "Retrieving area " << trimDom << " of object " << cmlColl.getString()
+ << " with scale factor " << rScale << "." << endl;
+ cout << "Retrieving units of shape " << insertionUnit << "." << endl;
+ cout << "Tiff Image area " << tiffDom << endl;
+
+ r_MiterArea myIter(&insertionUnit, &trimDom);
+ while( !myIter.isDone() ) {
+ currDom = myIter.nextArea();
+ cout << " Getting " << currDom << " with scale factor " << rScale << "." << endl;
+ try {
+ mddObj = scaler->get_scaled_object(currDom, rScale, 1);
+ }
+ catch( r_Error& errorObj )
+ {
+ cout << "Error while getting the scaled domain !" << endl;
+ cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << endl;
+ if(myTiff)
+ {
+ myTiff->closeTiff();
+ delete myTiff;
+ myTiff=NULL;
+ }
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ ta.abort();
+ db.close();
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+ return false;
+ }
+
+ // The polygonal cutout is currently not done. We will need a scale function with the
+ // same semantics as fastscale for it to work. Then the polygon can be specified in
+ // original pixel coordinates and will be scaled according to the scaling factor.
+
+ if(cmlPolygon.isPresent()) {
+ // we clip the polygon it according to the scaled domain retrieved by r_Fast_Scale
+
+ // original polygon is modified by clip function
+ myPoly=poly;
+
+ scaler->get_scaled_domain(currDom, clipDom, rScale);
+ cout << "Domain for clipping: " << clipDom << endl;
+
+ //FIXME
+ //quick hack for test_polygon because get_scaled_image
+ //returns the clipDom translated in currDom.get_origin()
+ mddObj->set_spatial_domain(clipDom);
+
+ myPoly.clip(clipDom);
+ cout << "Clipped polygon: " << myPoly << endl;
+
+
+ // we would have to transpose it here. This is done by the TIFF conversion.
+
+ // REALLY IMPORTANT: The TA has to be open here! Otherwise neither
+ // type info nor domain can be read.
+ try
+ {
+ myPoly.fillMArray(*mddObj, false, rBgr);
+ }
+ catch(r_Error& err)
+ {
+ cout << "Error size of background " << strlen(rBgr) << " bytes "
+ << " is different from mdd base type size " << mddObj->get_type_length()
+ << " bytes !" << endl;
+ mddObj.destroy();
+ throw err;
+ }
+ }//end if(usePolygon)
+
+ // Ok, now we use our r_TIFFStripe class here
+ if(!myTiff->addArray(*mddObj))
+ {
+ if(myTiff)
+ {
+ myTiff->closeTiff();
+ delete myTiff;
+ myTiff=NULL;
+ }
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr=NULL;
+ }
+
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ mddObj.destroy();
+
+ ta.abort();
+ db.close();
+
+ return false;
+ }
+ mddObj.destroy();
+ }//end while
+
+ delete scaler;
+ scaler=NULL;
+
+ myTiff->closeTiff();
+ delete myTiff;
+ myTiff=NULL;
+
+ delete[] rBgr;
+ rBgr=NULL;
+
+ ta.commit();
+ db.close();
+ }
+ catch(r_Error & errObj)
+ {
+ cout << "Error while exporting the data !" << endl;
+ cout << "Error " << errObj.get_errorno() << " : " << errObj.what() << endl;
+ if(scaler)
+ {
+ delete scaler;
+ scaler=NULL;
+ }
+
+ ta.abort();
+ db.close();
+
+ if(rBgr)
+ {
+ delete[] rBgr;
+ rBgr = NULL;
+ }
+ if(myTiff)
+ {
+ myTiff->closeTiff();
+ delete myTiff;
+ myTiff = NULL;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool
+processRequest(char* name)
+{
+ bool result=false;
+
+ if(detectParams())
+ {
+#if defined(RMANDEBUG)
+ printStatus(name);
+#endif
+ result=exportData();
+ }
+
+ return result;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ int result=FAILED;
+
+ if(!parseParams(argc, argv))
+ printUsage(argv[0]);
+ else
+ if(cmlHelp.isPresent())
+ {
+ printUsage(argv[0]);
+ result=SUCCES;
+ }
+ else
+ if(processRequest(argv[0]))
+ result=SUCCES;
+ else
+ printUsage(argv[0]);
+ return result;
+
+}
+
diff --git a/rasodmg/test/test_query.cc b/rasodmg/test/test_query.cc
new file mode 100644
index 0000000..b8b8faf
--- /dev/null
+++ b/rasodmg/test/test_query.cc
@@ -0,0 +1,693 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_query.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+ */
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sstream>
+#include <fstream>
+
+using namespace std;
+
+#ifdef __VISUALC__
+ #define __EXECUTABLE__
+#endif
+
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+
+#include "rasodmg/ref.hh"
+
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/iterator.hh"
+#include "rasodmg/oqlquery.hh"
+
+#include "raslib/type.hh"
+
+#include "raslib/minterval.hh"
+
+#include "raslib/primitive.hh"
+#include "raslib/complex.hh"
+#include "raslib/structure.hh"
+
+#include "raslib/structuretype.hh"
+#include "raslib/primitivetype.hh"
+
+#include "rasodmg/storagelayout.hh"
+
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/dirtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/interesttiling.hh"
+#include "rasodmg/stattiling.hh"
+
+#ifdef __VISUALC__
+ #undef __EXECUTABLE__
+#endif
+
+const int MAX_STR_LEN = 255;
+const int MAX_QUERY_LEN = 10240;
+
+bool printText = false;
+
+int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex )
+{
+ int found = 0;
+ int i=1;
+
+ while( !found && i<argc )
+ found = !strcmp( searchText, argv[i++] );
+
+ if( found && i<argc && (argv[i][0] != '-') )
+ optionValueIndex = i;
+ else
+ optionValueIndex = 0;
+
+ return found;
+}
+
+
+void printScalar( const r_Scalar& scalar )
+{
+ switch( scalar.get_type()->type_id() )
+ {
+ case r_Type::BOOL:
+ std::cout << ( ((r_Primitive*)&scalar)->get_boolean() ? "T" : "F" ) << std::flush;
+ break;
+
+ case r_Type::CHAR:
+ std::cout << (int)((r_Primitive*)&scalar)->get_char() << std::flush;
+ break;
+
+ case r_Type::OCTET:
+ std::cout << (int)((r_Primitive*)&scalar)->get_octet() << std::flush;
+ break;
+
+ case r_Type::SHORT:
+ std::cout << ((r_Primitive*)&scalar)->get_short() << std::flush;
+ break;
+
+ case r_Type::USHORT:
+ std::cout << ((r_Primitive*)&scalar)->get_ushort() << std::flush;
+ break;
+
+ case r_Type::LONG:
+ std::cout << ((r_Primitive*)&scalar)->get_long() << std::flush;
+ break;
+
+ case r_Type::ULONG:
+ std::cout << ((r_Primitive*)&scalar)->get_ulong() << std::flush;
+ break;
+
+ case r_Type::FLOAT:
+ std::cout << ((r_Primitive*)&scalar)->get_float() << std::flush;
+ break;
+
+ case r_Type::DOUBLE:
+ std::cout << ((r_Primitive*)&scalar)->get_double() << std::flush;
+ break;
+
+ case r_Type::COMPLEXTYPE1:
+ case r_Type::COMPLEXTYPE2:
+ std::cout << "(" << ((r_Complex*)&scalar)->get_re() << ", " << ((r_Complex*)&scalar)->get_im() << ")" << std::flush;
+ break;
+
+ case r_Type::STRUCTURETYPE:
+ {
+ r_Structure* structValue = (r_Structure*)&scalar;
+
+ std::cout << "{ " << std::flush;
+
+ for( int i=0; i<structValue->count_elements(); i++ )
+ {
+ printScalar( (*structValue)[i] );
+
+ if( i < structValue->count_elements()-1 ) std::cout << ", " << std::flush;
+ }
+
+ std::cout << " }" << std::endl;
+ }
+ break;
+ default:
+ std::cout << "scalar type " << scalar.get_type()->type_id() << " not supported!" << std::endl;
+ break;
+ }
+}
+
+void printUsage(char* name){
+ std::cout << name << "v1.1 systemtest query utility " << std::endl;
+ std::cout << "Description: Systemtest query utility for query execution in RasDaMan" << std::endl;
+ std::cout << "Usage: " << name << " [options]" << std::endl << std::endl;
+ std::cout << "Options: -h ... this help" << std::endl;
+ std::cout << " -server <srvname> ... name of server.(mandatory)" << std::endl;
+ std::cout << " -port <nnnn> ... port of server.(default 7001)" << std::endl;
+ std::cout << " -base <dbname> ... name of database.(madatory)" << std::endl;
+ std::cout << " -file <filename> ... file name used to read query from a file" << std::endl;
+ std::cout << " -user <usrname> ... user name.(default rasguest)" << std::endl;
+ std::cout << " -passwd <usrpasswd> ... user password.(default rasguest)" << std::endl;
+ std::cout << " -transferformat <format> ... transfer format.(default Array)" << std::endl;
+ std::cout << " -transferformatparams <formatparams> ... transfer format parameters.(default NULL)" << std::endl;
+ std::cout << " -storageformat <format> ... storage format.(default Array)" << std::endl;
+ std::cout << " -storageformatparams <formatparams> ... storage format parameters.(default NULL)" << std::endl;
+ std::cout << " -mdddomain <domain> ... MDD domain." << std::endl;
+ std::cout << " -tiling <tiling> ... tiling strategy, only for update query.(default SizeTiling)" << std::endl;
+ std::cout << " -tilingparams <tilingparams> ... tiling strategy params, only for update query.(default 131072)" << std::endl;
+ std::cout << " -hex ... output in hex.(default off)" << std::endl;
+ std::cout << " -nooutput ... no output of MDD content.(default on)" << std::endl;
+ std::cout << " -testbed ... turn on output for testbed.(default off)" << std::endl;
+ std::cout << " -text ... print textual output.(default off)" << std::endl;
+ std::cout << std::endl << std::endl;
+
+ std::cout << "Report bugs to <support@active-knowledge.com>" << std::endl;
+}
+
+r_Tiling*
+getTilingScheme(r_Tiling_Scheme& tilingS, char* tilingP){
+ r_Tiling* retval=NULL;
+
+ try {
+ std::cout << "Creating tiling strategy ..." << std::flush;
+ switch(tilingS) {
+ case r_NoTiling:
+ retval = new r_No_Tiling(tilingP);
+ break;
+ case r_AlignedTiling:
+ retval = new r_Aligned_Tiling(tilingP);
+ break;
+ case r_InterestTiling:
+ retval = new r_Interest_Tiling(tilingP);
+ break;
+ case r_DirectionalTiling:
+ retval = new r_Dir_Tiling(tilingP);
+ break;
+ case r_StatisticalTiling:
+ retval = new r_Stat_Tiling(tilingP);
+ break;
+ default:
+ retval = new r_Size_Tiling(tilingP);
+ break;
+ }
+ std::cout << "OK" << std::flush;
+ }
+ catch(r_Error& err){
+ std::cout << "FAILED" << std::endl;
+ std::cout << "Error " << err.get_errorno() << " : " << err.what() << std::endl;
+ }
+
+ return retval;
+}
+
+int main( int argc, char** argv )
+{
+ int optionValueIndex=0;
+
+ char serverName[MAX_STR_LEN] = "";
+ r_ULong serverPort = 7001;
+ char baseName[MAX_STR_LEN] = "";
+
+ char userName[MAX_STR_LEN] = "rasguest";
+ char userPasswd[MAX_STR_LEN] = "rasguest";
+
+ char fileName[MAX_STR_LEN] = "";
+
+ r_Data_Format transferFormat = r_Array;
+ char *transferFormatParams = NULL;
+ r_Data_Format storageFormat = r_Array;
+ char *storageFormatParams = NULL;
+
+ r_Tiling_Scheme tilingScheme = r_SizeTiling;
+ char* tilingSchemeParams = "131072";
+
+
+ int output = 0;
+ int hexOutput = 0;
+ int testbed = 0;
+
+ r_ULong tileSize=0;
+ r_Minterval tileConfig;
+ r_Minterval mddDomain;
+
+ if( checkArguments( argc, argv, "-h", optionValueIndex ) ) {
+ printUsage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+
+ if( checkArguments( argc, argv, "-server", optionValueIndex ) && optionValueIndex )
+ strcpy( serverName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-base", optionValueIndex ) && optionValueIndex )
+ strcpy( baseName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-file", optionValueIndex ) && optionValueIndex )
+ strcpy( fileName, argv[optionValueIndex] );
+
+ if(!strcmp(serverName, "") ||
+ !strcmp(baseName, "") ||
+ !strcmp(fileName, "") ) {
+ std::cerr << "Mandatory parameters are missing!" << std::endl;
+ printUsage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+
+ hexOutput = checkArguments( argc, argv, "-hex", optionValueIndex );
+ printText = checkArguments( argc, argv, "-text", optionValueIndex );
+ output = !checkArguments( argc, argv, "-nooutput", optionValueIndex );
+ testbed = checkArguments( argc, argv, "-testbed", optionValueIndex );
+
+ if( checkArguments( argc, argv, "-mdddomain", optionValueIndex ) && optionValueIndex )
+ mddDomain = r_Minterval( argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-tileconf", optionValueIndex ) && optionValueIndex )
+ tileConfig = r_Minterval( argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-tilesize", optionValueIndex ) && optionValueIndex )
+ tileSize = strtoul( argv[optionValueIndex], (char **)NULL, 10 ) ;
+
+ if( checkArguments( argc, argv, "-port", optionValueIndex ) && optionValueIndex )
+ serverPort = strtoul( argv[optionValueIndex], (char **)NULL, 10 ) ;
+
+ if( checkArguments( argc, argv, "-user", optionValueIndex ) && optionValueIndex )
+ strcpy( userName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-passwd", optionValueIndex ) && optionValueIndex )
+ strcpy( userPasswd, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-transferformat", optionValueIndex ) && optionValueIndex ) {
+ transferFormat = get_data_format_from_name( argv[optionValueIndex] );
+ if(transferFormat == r_Data_Format_NUMBER) {
+ std::cerr << "Invalid transfer format '" << argv[optionValueIndex] << "' switched to " << r_Array << std::endl;
+ transferFormat = r_Array;
+ }
+ }
+
+ if( checkArguments( argc, argv, "-transferformatparams", optionValueIndex ) && optionValueIndex )
+ transferFormatParams = argv[optionValueIndex] ;
+
+ if( checkArguments( argc, argv, "-storageformat", optionValueIndex ) && optionValueIndex ) {
+ storageFormat = get_data_format_from_name(argv[optionValueIndex] );
+ if(storageFormat == r_Data_Format_NUMBER) {
+ std::cerr << "Invalid storage format '" << argv[optionValueIndex] << "' switched to " << r_Array << std::endl;
+ storageFormat = r_Array;
+ }
+ }
+
+ if( checkArguments( argc, argv, "-storageformatparams", optionValueIndex ) && optionValueIndex )
+ storageFormatParams = argv[optionValueIndex] ;
+
+ if( checkArguments( argc, argv, "-tiling", optionValueIndex ) && optionValueIndex ) {
+ tilingScheme = get_tiling_scheme_from_name( argv[optionValueIndex] );
+ if(tilingScheme == r_Tiling_Scheme_NUMBER) {
+ std::cerr << "Invalid tiling scheme '" << argv[optionValueIndex] << "' switched to " << r_SizeTiling << std::endl;
+ tilingScheme = r_SizeTiling;
+ }
+ if(tilingScheme == r_RegularTiling) {
+ std::cerr << "Tiling scheme '" << argv[optionValueIndex] << "' not supported, switched to " << r_SizeTiling << std::endl;
+ tilingScheme = r_SizeTiling;
+ }
+ }
+
+ if( checkArguments( argc, argv, "-tilingparams", optionValueIndex ) && optionValueIndex )
+ tilingSchemeParams = argv[optionValueIndex] ;
+
+
+#ifdef __VISUALC__
+ std::ifstream fileStream( fileName, ios::nocreate );
+ if( !fileStream.is_open() )
+#else
+ std::ifstream fileStream( fileName );
+ if( !fileStream )
+#endif
+ {
+ std::cout << "Error: File not found." << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::ostringstream queryStream;
+
+ queryStream << "-- " << fileName << std::endl;
+
+ char ch;
+ while( fileStream.get(ch) ) queryStream.put(ch);
+
+ queryStream << std::ends;
+
+ std::cout << std::endl << std::endl;
+
+ r_Database db;
+ r_Transaction ta;
+
+ db.set_servername( serverName, serverPort );
+ db.set_useridentification( userName, userPasswd );
+
+ try
+ {
+ std::cout << "Creating query string ..."<< std::flush;
+ r_OQL_Query q1( queryStream.str().c_str() );
+ std::cout << "OK" << std::endl;
+ std::cout << "The query is: " << std::endl;
+
+ std::cout << q1.get_query() << std::endl;
+
+ std::cout << "Opening Database " << baseName << " on " << serverName << "... "<< std::flush;
+ db.open( baseName );
+ std::cout << "OK" << std::endl;
+
+ if( q1.is_update_query() )
+ {
+ std::cout << "Starting Update Transaction ... "<< std::flush;
+ ta.begin();
+ std::cout << "OK" << std::endl;
+
+ std::cout << "Setting transfer and storage formats ... " << std::flush;
+ db.set_transfer_format( transferFormat, transferFormatParams );
+ db.set_storage_format( storageFormat, storageFormatParams );
+ std::cout << "OK" << std::endl;
+
+ r_Marray<r_ULong>* mddConst = NULL;
+ r_Tiling* tilingObj = NULL;
+ r_Storage_Layout* stl = NULL;
+
+
+ std::cout << "Executing the update query ..."<< std::flush;
+
+ if( strstr( queryStream.str().c_str(), "$" ) )
+ {
+ r_Minterval domain;
+ if( mddDomain.dimension() )
+ domain = mddDomain;
+ else
+ domain = r_Minterval("[0:10,0:10]");
+
+ // create storage layout object
+
+ try {
+ tilingObj = getTilingScheme(tilingScheme, tilingSchemeParams);
+
+ stl = new r_Storage_Layout( tilingObj );
+
+ // mddConst = new( "GreyCube" ) r_Marray<r_Char>( domain, (unsigned char)0, stl );
+ mddConst = new( "ULongImage" ) r_Marray<r_ULong>( domain, (r_ULong)9, stl );
+ // mddConst = new( "FloatCube4" ) r_Marray<r_Float>( domain, 9ul, stl );
+
+ q1 << *mddConst;
+ }
+ catch(r_Error& errorObj) {
+ std::cout << "FAILED" << std::endl;
+ std::cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << std::endl;
+
+ if( testbed )
+ {
+ std::cout << "-- Testbed line: error_no=" << errorObj.get_errorno() << std::endl;
+ std::cout << std::endl;
+ }
+
+ std::cout << "Aborting Transaction ... "<< std::flush;
+ ta.abort();
+ std::cout << "OK" << std::endl;
+
+ std::cout << "Closing Database ... "<< std::flush;
+ db.close();
+
+ std::cout << "OK" << std::endl;
+
+ if( mddConst ) delete mddConst;
+ else
+ if( stl ) delete stl;
+ else if(tilingObj) delete tilingObj;
+
+ return EXIT_FAILURE;
+ }
+ }
+
+ try
+ {
+ r_oql_execute( q1 );
+ }
+ catch( r_Error& errorObj )
+ {
+ std::cout << "FAILED" << std::endl;
+ std::cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << std::endl;
+
+ if( testbed )
+ {
+ std::cout << "-- Testbed line: error_no=" << errorObj.get_errorno() << std::endl;
+ std::cout << std::endl;
+ }
+
+ std::cout << "Aborting Transaction ... " << std::flush;
+ ta.abort();
+ std::cout << "OK" << std::endl;
+
+ std::cout << "Closing Database ... " << std::flush;
+ db.close();
+
+ std::cout << "OK" << std::endl;
+
+ if( mddConst ) delete mddConst;
+
+ return EXIT_FAILURE;
+ }
+ std::cout << "OK" << std::endl;
+
+ if( mddConst ) delete mddConst;
+ }
+ else
+ {
+ std::cout << "Starting Read Only Transaction ... " << std::flush;
+ ta.begin( r_Transaction::read_only );
+ std::cout << "OK" << std::endl;
+
+ std::cout << "Setting transfer and storage formats ... " << std::flush;
+ db.set_transfer_format( transferFormat, transferFormatParams );
+ db.set_storage_format( storageFormat, storageFormatParams );
+ std::cout << "OK" << std::endl;
+
+ r_Set< r_Ref_Any > result_set;
+
+ std::cout << "Executing the retrieval query ..." << std::flush;
+
+ try
+ {
+ r_oql_execute( q1, result_set );
+ }
+ catch( r_Error& errorObj )
+ {
+ std::cout << "FAILED" << std::endl;
+ std::cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << std::endl;
+
+ if( testbed )
+ {
+ std::cout << "-- Testbed line: error_no=" << errorObj.get_errorno() << std::endl;
+ std::cout << std::endl;
+ }
+
+ std::cout << "Aborting Transaction ... " << std::flush;
+ ta.abort();
+ std::cout << "OK" << std::endl;
+
+ std::cout << "Closing Database ... " << std::flush;
+ db.close();
+ std::cout << "OK" << std::endl;
+
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "OK" << std::endl;
+ std::cout << "Collection" << std::endl;
+ std::cout << " Oid...................: " << result_set.get_oid() << std::endl;
+ std::cout << " Type Structure........: "
+ << ( result_set.get_type_structure() ? result_set.get_type_structure() : "<nn>" ) << std::endl;
+ std::cout << " Type Schema...........: " << std::flush;
+ if( result_set.get_type_schema() )
+ result_set.get_type_schema()->print_status( std::cout );
+ else
+ std::cout << "<nn>" << std::flush;
+ std::cout << std::endl;
+ std::cout << " Number of entries.....: " << result_set.cardinality() << std::endl;
+ std::cout << " Element Type Schema...: " << std::flush;
+ if( result_set.get_element_type_schema() )
+ result_set.get_element_type_schema()->print_status( std::cout );
+ else
+ std::cout << "<nn>" << std::flush;
+ std::cout << std::endl;
+
+ if( testbed )
+ {
+ std::cout << "-- Testbed line: result_type=" << result_set.get_type_structure() << std::endl;
+ std::cout << "-- Testbed line: result_elements=" << result_set.cardinality() << std::endl;
+ std::cout << std::endl;
+ }
+
+ /* The following can be used, if the type is known and the element type is not atomic.
+
+ r_Set< r_Ref< r_Point > >* set2 = (r_Set< r_Ref< r_Point > >*)&result_set;
+ r_Iterator< r_Ref<r_Point> > iter2 = set2->create_iterator();
+ for( iter2.reset(); iter2.not_done(); iter2++ )
+ std::cout << **iter2 << std::endl;
+ */
+
+ if( output || testbed )
+ {
+ r_Iterator< r_Ref_Any > iter = result_set.create_iterator();
+
+ std::cout << std::endl;
+
+ if( testbed )
+ std::cout << "-- Testbed start block:" << std::endl;
+
+ for ( int i=1 ; iter.not_done(); iter++, i++ )
+ {
+ switch( result_set.get_element_type_schema()->type_id() )
+ {
+ case r_Type::MARRAYTYPE:
+ {
+ const char *defExt;
+ r_Data_Format mafmt = r_Ref<r_GMarray>(*iter)->get_current_format();
+
+ // special treatment only for DEFs
+ switch (mafmt)
+ {
+ case r_TIFF:
+ defExt = "tif"; break;
+ case r_JPEG:
+ defExt = "jpg"; break;
+ case r_HDF:
+ defExt = "hdf"; break;
+ case r_PNG:
+ defExt = "png"; break;
+ case r_BMP:
+ defExt = "bmp"; break;
+ case r_VFF:
+ defExt = "vff"; break;
+ default:
+ defExt = NULL;
+ }
+
+ if( defExt == NULL )
+ {
+ std::cout << "Image " << i << std::endl;
+ if (printText)
+ {
+ int numCells = r_Ref<r_GMarray>(*iter)->get_array_size();
+ const char* theStuff = r_Ref<r_GMarray>(*iter)->get_array();
+ for (int cnt = 0; cnt < numCells; cnt++)
+ std::cout << theStuff[cnt];
+ std::cout << std::endl;
+ }
+ else {
+ r_Ref<r_GMarray>(*iter)->print_status( std::cout, hexOutput );
+ }
+ std::cout << std::endl;
+ }
+ else
+ {
+ char defFileName[256];
+
+ sprintf( defFileName, "image%d.%s", i, defExt );
+ std::cout << "Image " << i << " written to " << defFileName << std::endl;
+
+ FILE *tfile = fopen( defFileName, "wb" );
+ fwrite((void*)r_Ref<r_GMarray>(*iter)->get_array(), 1,
+ r_Ref<r_GMarray>(*iter)->get_array_size(), tfile );
+ fclose(tfile);
+ }
+ }
+ break;
+
+ case r_Type::POINTTYPE:
+ std::cout << "Element " << i << ": " << *(r_Ref<r_Point>(*iter)) << std::endl;
+ break;
+
+ case r_Type::SINTERVALTYPE:
+ std::cout << "Element " << i << ": " << *(r_Ref<r_Sinterval>(*iter)) << std::endl;
+ break;
+
+ case r_Type::MINTERVALTYPE:
+ std::cout << "Element " << i << ": " << *(r_Ref<r_Minterval>(*iter)) << std::endl;
+ break;
+
+ case r_Type::OIDTYPE:
+ std::cout << "Element " << i << ": " << *(r_Ref<r_OId>(*iter)) << std::endl;
+ break;
+
+ default:
+ std::cout << "Element " << i << ": " << std::flush;
+ printScalar( *(r_Ref<r_Scalar>(*iter)) );
+ std::cout << std::endl;
+ // or simply
+ // r_Ref<r_Scalar>(*iter)->print_status( std::cout );
+ }
+ }
+
+ if( testbed )
+ std::cout << "-- Testbed end block:" << std::endl;
+
+ std::cout << std::endl;
+ }
+
+ } // retrieval query
+
+ std::cout << "Commiting Transaction ... " << std::endl;
+ ta.commit();
+ std::cout << "OK" << std::endl;
+
+ std::cout << "Closing Database ... " << std::flush;
+ db.close();
+ std::cout << "OK" << std::endl;
+ }
+ catch( r_Error& errorObj )
+ {
+ std::cout << "FAILED" << std::endl;
+ std::cout << "Error " << errorObj.get_errorno() << " : " << errorObj.what() << std::endl;
+ ta.abort();
+ db.close();
+ if( testbed )
+ {
+ std::cout << "-- Testbed line: error_no=" << errorObj.get_errorno() << std::endl;
+ std::cout << std::endl;
+ }
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/rasodmg/test/test_ref.cc b/rasodmg/test/test_ref.cc
new file mode 100644
index 0000000..1da5d68
--- /dev/null
+++ b/rasodmg/test/test_ref.cc
@@ -0,0 +1,69 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_ref.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <iostream>
+#include "rasodmg/ref.hh"
+
+class X
+{
+ public:
+ int a;
+};
+
+int main()
+{
+ cout << endl << endl;
+ cout << "r_Ref tests" << endl;
+ cout << "===========" << endl << endl;
+
+ r_Ref<X> ptr;
+ r_Ref<int> ptr2;
+
+ cout << "r_Ref created. is_null() ? " << ptr.is_null() << endl;
+
+ ptr = new X;
+
+ cout << "r_Ref assigned to pointer of base type. is_null() ? " << ptr.is_null() << endl;
+
+ (*ptr).a = 1;
+ cout << "assignment *ptr.a = 1. Current value ? " << (*ptr).a << endl;
+ ptr->a = 2;
+ cout << "assignment ptr->a = 2. Current value ? " << ptr->a << endl;
+
+ ptr.destroy(); // delete from memory
+
+ return 0;
+}
diff --git a/rasodmg/test/test_set.cc b/rasodmg/test/test_set.cc
new file mode 100644
index 0000000..a6bbc0f
--- /dev/null
+++ b/rasodmg/test/test_set.cc
@@ -0,0 +1,104 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_set.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ *
+*/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#include <iostream>
+#include "rasodmg/set.hh"
+
+int main()
+{
+ int v,x,y,z;
+
+ v = 100;
+ x = 200;
+ y = 100;
+ z = 300;
+
+ cout << endl << endl;
+ cout << "Set Examples" << endl;
+ cout << "=============" << endl << endl;
+
+ cout << "Creating r_Set of type int." << endl;
+ r_Set<int> a;
+
+ cout << "Cardinality of empty set 'a': " << a.cardinality() << endl << endl;
+
+ cout << "Now inserting four elements:" << endl << "v = 100" << endl;
+ a.insert_element(v);
+
+ cout << "x = 200" << endl;
+ a.insert_element(x);
+
+ cout << "y = 100 (should fail in sets)" << endl;
+ a.insert_element(y);
+
+ cout << "z = 300" << endl;
+ a.insert_element(z);
+
+ cout << "Cardinality of collection 'a' after four inserts: " << a.cardinality() << endl << endl;
+
+ cout << "Does 'a' contain element '100' (1=TRUE/0=FALSE)? " << a.contains_element(100) << endl;
+
+ cout << "Does 'a' contain element '500' (1=TRUE/0=FALSE)? " << a.contains_element(500) << endl << endl;
+
+ cout << "Now removing element 'x=200' from 'a'." << endl;
+ a.remove_element(x);
+ cout << "Cardinality of 'a' now: " << a.cardinality() << endl << endl;
+
+ cout << "Now removing element '100' from 'a'." << endl;
+ a.remove_element(100);
+ cout << "Cardinality of 'a' now: " << a.cardinality() << endl << endl;
+
+ cout << "Now removing (non-existing) element '500' from 'a'." << endl;
+ a.remove_element(500);
+ cout << "Cardinality of 'a' now: " << a.cardinality() << endl << endl;
+
+ cout << "Testing assignment operator on r_Sets." << endl << "(creating r_Set 'b' that is equal to 'a'.)" <<endl;
+ r_Set<int> b;
+ b = a;
+ cout << "Cardinality of 'b': " << b.cardinality() << endl << endl;
+
+ cout << "Testing copy constructor of r_Set." << endl << "(creating r_Set 'c' that is equal to 'a'.)" <<endl;
+ r_Set<int> c(a);
+ cout << "Cardinality of 'c': " << c.cardinality() << endl << endl;
+
+ cout << "Now removing all elements from 'a'." << endl;
+ a.remove_all();
+ cout << "Cardinality of 'a' now: " << a.cardinality() << endl;
+ cout << "Cardinality of 'b' is still: " << b.cardinality() << endl;
+ cout << "Cardinality of 'c' is still: " << c.cardinality() << endl << endl;
+
+ return 0;
+}
diff --git a/rasodmg/test/test_stattiling.cc b/rasodmg/test/test_stattiling.cc
new file mode 100644
index 0000000..a1a1f44
--- /dev/null
+++ b/rasodmg/test/test_stattiling.cc
@@ -0,0 +1,173 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_interestrtiling.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE: test class r_StatTiling.
+ *
+ * COMMENTS:
+ * None
+*/
+
+/*
+ ATENTION: The format of the input file for using with this program is:
+
+ border_threshold accesses_threshold tilesize domain
+ access1
+ access2
+ accessXXX
+ ...
+
+ Example:
+
+ 50 0.20 1000 [0:799, 0:599]
+ [10:20, 30:40]
+ [12:20, 35:39]
+ [100:300, 300:400]
+ [120:300, 310:410]
+ [200:500, 350:500]
+ [200:510, 350:500]
+*/
+
+
+#include <iostream>
+#include <stdio.h>
+#include "rasodmg/marray.hh"
+#include "rasodmg/tiling.hh"
+#include "raslib/dlist.hh"
+#include "rasodmg/stattiling.hh"
+#include "raslib/minterval.hh"
+#include "raslib/sinterval.hh"
+
+char* filename;
+DList<r_Access> stat_info;
+unsigned int border_threshold;
+double interesting_threshold;
+unsigned long tile_size;
+r_Minterval* domain;
+
+void parse(int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ cout << "Usage: test_stattiling <filename>" << endl << endl;
+ exit(1);
+ }
+
+ filename = argv[1];
+}
+
+void read_data()
+{
+ const unsigned int BUF_SIZE = 256;
+ char buf[BUF_SIZE], buf2[BUF_SIZE];
+
+ cout << "Opening " << filename << " for reading... ";
+
+ ifstream is(filename, ios::in);
+ if (!is)
+ {
+ cout << "Couldn't open!!!" << endl;
+ exit(1);
+ }
+ else
+ cout << "done." << endl;
+
+ cout << "Reading parameters... ";
+
+ is >> border_threshold;
+ is >> interesting_threshold;
+ is >> tile_size;
+
+ is.getline(buf, BUF_SIZE);
+ domain = new r_Minterval(buf);
+
+ cout << "done." << endl;
+ cout << "Geting the accesses... ";
+
+ unsigned long count = 0;
+
+ while (!is.eof())
+ {
+ is.getline(buf, BUF_SIZE);
+ if (sscanf(buf, "%s", buf2) == 1)
+ {
+ r_Minterval inter(buf);
+ stat_info += inter;
+ ++count;
+
+ cout << "*";
+ }
+ }
+
+ is.close();
+
+ cout << endl;
+ cout << "Geting the accesses... done." << endl << endl;
+
+ cout << "Border threshold = " << border_threshold << endl;
+ cout << "Interesting threshold = " << interesting_threshold << endl;
+ cout << "Tile size = " << tile_size << endl;
+ cout << "Domain = " << *domain << endl;
+ cout << "Number of accesses = " << count << endl << endl;
+}
+
+void test_tiling()
+{
+ r_Stat_Tiling tiling(border_threshold, interesting_threshold, tile_size);
+ tiling.update_stat_information(stat_info);
+
+ DList<r_Minterval>* tiles = tiling.compute_tiles(*domain, 1);
+
+ cout << endl << "Tiles: " << endl;
+ while (!tiles->is_empty())
+ {
+ r_Minterval inter = tiles->get_first(TRUE);
+ cout << " " << inter << endl;
+ }
+
+ delete tiles;
+ delete domain;
+}
+
+int main(int argc, char* argv[])
+{
+ parse(argc, argv);
+ read_data();
+ test_tiling();
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rasodmg/test/test_storage.cc b/rasodmg/test/test_storage.cc
new file mode 100644
index 0000000..81c1261
--- /dev/null
+++ b/rasodmg/test/test_storage.cc
@@ -0,0 +1,282 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: test_storage.cc
+ *
+ * MODULE: rasodmg
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <iostream>
+#include <string.h>
+
+#ifdef __VISUALC__
+ #define __EXECUTABLE__
+#endif
+#include "rasodmg/ref.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/marray.hh"
+#include "raslib/odmgtypes.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/dirtiling.hh"
+
+#ifdef __VISUALC__
+ #undef __EXECUTABLE__
+#endif
+
+static int INIT = 0;
+
+r_ULong initWithCounter( const r_Point& /*pt*/ )
+{
+ return INIT++;
+}
+
+
+r_ULong initWithCrossfoot( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ for( r_Dimension i=0; i< pt.dimension(); i++ )
+ value += pt[i];
+
+ return value;
+}
+
+
+r_ULong initWithCoordinates( const r_Point& pt )
+{
+ r_ULong value=0;
+ int factor=1;
+
+ for( int i=pt.dimension()-1; i >= 0; i-- )
+ {
+ value += factor * pt[i];
+ factor *= 100;
+ }
+
+ return value;
+}
+
+
+
+int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex )
+{
+ int found = 0;
+ int i=1;
+
+ while( !found && i<argc )
+ found = !strcmp( searchText, argv[i++] );
+
+ if( found && i<argc && !strchr(argv[i],'-') )
+ optionValueIndex = i;
+ else
+ optionValueIndex = 0;
+
+ return found;
+}
+
+
+
+
+int main( int argc, char** argv )
+{
+ char serverName[255];
+ char baseName[255];
+ char collName[255];
+ int optionValueIndex;
+
+ if( argc < 4 || checkArguments( argc, argv, "-h", optionValueIndex ) )
+ {
+ cout << "Usage: test_storage server_name base_name collection_name [options]" << endl << endl;
+ cout << "Options: -h ... this help" << endl;
+ // cout << " -nooutput ... no output of MDD content" << endl;
+ // cout << " -hex ... output in hex" << endl;
+ cout << endl;
+ return 0;
+ }
+
+ strcpy( serverName, argv[1] );
+ strcpy( baseName, argv[2] );
+ strcpy( collName, argv[3] );
+
+ cout << endl << endl;
+ cout << "ODMG conformant insertion of Marrays" << endl;
+ cout << "====================================" << endl << endl;
+
+ r_Database db;
+ r_Transaction ta;
+ r_Ref< r_Set< r_Ref< r_Marray<r_ULong> > > > image_set;
+ r_Ref< r_Marray<r_ULong> > image1, image2, image3, image4;
+ r_Minterval domain, domain2;
+
+ domain = r_Minterval(2) << r_Sinterval( 0, 100 ) << r_Sinterval( 0, 100 );
+
+ // Default storage layout
+ r_Storage_Layout* sl1 = new r_Storage_Layout;
+ cout << "sl1 " << *sl1 <<endl;
+
+ // Default tiling with a different tile size than the previous one:
+ r_Size_Tiling* til2 = new r_Size_Tiling( 40000 );
+ r_Storage_Layout* sl2 = new r_Storage_Layout( til2 );
+ //, r_Storage_Layout::No_Compression );
+ cout << "sl2 " << *sl2 <<endl;
+
+ // Aligned Tiling
+ r_Aligned_Tiling* til3 = new r_Aligned_Tiling( r_Minterval("[0:1,0:2]"), 3200 );
+ // cout << *til3;
+ r_Storage_Layout* sl3 = new r_Storage_Layout( til3 );
+ cout << "sl3 " << *sl3 <<endl;
+
+ // Directional Tiling
+ vector<r_Dir_Decompose> decompVec;
+ r_Dir_Decompose decompI, decompII;
+ decompI << 0 << 10 << 20 << 40 << 60 << 70 << 100;
+ decompII << 0 << 10 << 20 << 40 << 60 << 70 << 100;
+ decompVec.push_back(decompI);
+ decompVec.push_back(decompII);
+ r_Dir_Tiling* til4 = new r_Dir_Tiling( 2, decompVec );
+ r_Storage_Layout* sl4 = new r_Storage_Layout( til4 );
+ cout << "sl4 " << *sl4 <<endl;
+
+ // FIXME adapt this to test also statistical, interest and no tiling
+/*
+ // Interest Tiling
+ vector<r_Dir_Decompose> decompVec;
+ r_Dir_Decompose decompI, decompII;
+ decompI << 0 << 10 << 20 << 40 << 60 << 70 << 100;
+ decompII << 0 << 10 << 20 << 40 << 60 << 70 << 100;
+ decompVec.push_back(decompI);
+ decompVec.push_back(decompII);
+ r_Dir_Tiling* til4 = new r_Dir_Tiling( 2, decompVec );
+ r_Storage_Layout* sl4 = new r_Storage_Layout( til4 );
+ cout << "sl4 " << *sl4 <<endl;
+
+ // Statistic Tiling
+ vector<r_Dir_Decompose> decompVec;
+ r_Dir_Decompose decompI, decompII;
+ decompI << 0 << 10 << 20 << 40 << 60 << 70 << 100;
+ decompII << 0 << 10 << 20 << 40 << 60 << 70 << 100;
+ decompVec.push_back(decompI);
+ decompVec.push_back(decompII);
+ r_Dir_Tiling* til4 = new r_Dir_Tiling( 2, decompVec );
+ r_Storage_Layout* sl4 = new r_Storage_Layout( til4 );
+ cout << "sl4 " << *sl4 <<endl;
+
+ // No Tiling
+ vector<r_Dir_Decompose> decompVec;
+ r_Dir_Decompose decompI, decompII;
+ decompI << 0 << 10 << 20 << 40 << 60 << 70 << 100;
+ decompII << 0 << 10 << 20 << 40 << 60 << 70 << 100;
+ decompVec.push_back(decompI);
+ decompVec.push_back(decompII);
+ r_Dir_Tiling* til4 = new r_Dir_Tiling( 2, decompVec );
+ r_Storage_Layout* sl4 = new r_Storage_Layout( til4 );
+ cout << "sl4 " << *sl4 <<endl;
+*/
+
+
+ db.set_servername( serverName );
+
+ try
+ {
+ cout << "Opening Database " << baseName << " on " << serverName << "... " << flush;
+ db.open( baseName );
+ cout << "OK" << endl;
+
+ cout << "Starting Transaction ... " << flush;
+ ta.begin();
+ cout << "OK" << endl;
+
+ cout << "Opening the set ... " << flush;
+
+ try{
+ image_set = db.lookup_object( collName );
+ }
+ catch( r_Error &obj )
+ {
+ cout << "FAILED" << endl;
+ // cout << obj.what() << endl;
+
+ //
+ // set doesn't exist -> create the set
+ //
+
+ cout << "Create the set ... " << flush;
+
+ // create the set
+ image_set = new( &db, "ULongSet" ) r_Set< r_Ref< r_Marray<r_ULong> > >;
+
+ // create a name for the persistent set in order to be able to look it up again
+ db.set_object_name( *image_set, collName );
+ }
+
+ cout << "OK" << endl;
+
+ cout << "Creating four images ... " << flush;
+
+ // create first image
+ image1 = new( &db, "ULongImage" ) r_Marray<r_ULong>( domain, (r_ULong)0, sl1 );
+
+ // create second image
+ image2 = new( &db, "ULongImage" ) r_Marray<r_ULong>( domain, &initWithCrossfoot, sl2 );
+
+ // create third image
+ image3 = new( &db, "ULongImage" ) r_Marray<r_ULong>( domain, &initWithCounter, sl3 );
+
+ // create fourth image
+ image4 = new( &db, "ULongImage" ) r_Marray<r_ULong>( domain, &initWithCoordinates, sl4 );
+
+ cout << "OK" << endl;
+
+ cout << "Inserting them into the set " << collName << " ... " << flush;
+
+ // insert the images
+ image_set->insert_element( image1 );
+ image_set->insert_element( image2 );
+ image_set->insert_element( image3 );
+ image_set->insert_element( image4 );
+
+ cout << "OK" << endl;
+
+ cout << "Commiting Transaction ... " << flush;
+ ta.commit();
+ cout << "OK" << endl;
+
+ cout << "Closing Database ... " << flush;
+ db.close();
+ cout << "OK" << endl;
+ }
+ catch( r_Error& errorObj )
+ {
+ cerr << errorObj.what() << endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/rasodmg/test/test_transaction.cc b/rasodmg/test/test_transaction.cc
new file mode 100644
index 0000000..faa12b3
--- /dev/null
+++ b/rasodmg/test/test_transaction.cc
@@ -0,0 +1,152 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+#include <iostream>
+#include <stdio.h>
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#endif
+
+#include "rasodmg/database.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/marray.hh"
+#include "rasodmg/ref.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/oqlquery.hh"
+
+
+#define STRINGSIZE 256
+
+
+int main(int argc, char *argv[])
+{
+ char dbname[STRINGSIZE] = "";
+ char servername[STRINGSIZE] = "";
+ char collname[STRINGSIZE] = "tTAcoll";
+ r_Range range_low = 0;
+ r_Range range_high = 15;
+
+ int i;
+
+ i = 1;
+ while (i < argc)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 's':
+ strcpy(servername, argv[++i]);
+ break;
+ case 'd':
+ strcpy(dbname, argv[++i]);
+ break;
+ case 'c':
+ strcpy(collname, argv[++i]);
+ break;
+ case 'h':
+ cout << "Usage: " << argv[0] << " -s servername -d dbname" << endl;
+ exit(0);
+ }
+ }
+ i++;
+ }
+
+ if ((strlen(servername) == 0) || (strlen(dbname) == 0))
+ {
+ cerr << "Must specify servername and databasename!" << endl;
+ exit(-1);
+ }
+
+ r_Database db;
+
+ try
+ {
+ cout << "Trying to open " << dbname << " on " << servername << "... ";
+ cout << flush;
+ db.set_servername(servername);
+ db.open(dbname);
+ cout << "OK" << endl;
+ }
+ catch (r_Error &err)
+ {
+ cout << "failed." << endl;
+ cerr << err.what();
+ return -1;
+ }
+
+ r_Transaction ta;
+ char queryString[STRINGSIZE];
+
+ try
+ {
+ ta.begin();
+ sprintf(queryString, "CREATE COLLECTION %s GreySet", collname);
+ cout << "Collection " << collname << flush;
+ r_OQL_Query query(queryString);
+ r_oql_execute(query);
+ ta.commit();
+ cout << " created." << endl;
+ }
+ catch (r_Error &err)
+ {
+ ta.abort();
+ cout << " not created: " << err.what() << endl;
+ }
+
+ try
+ {
+ r_Sinterval siv = r_Sinterval(range_low, range_high);
+ r_Minterval interv(2);
+ interv << siv << siv;
+ r_Ref<r_Marray<char> > mddPtr = new ("GreyImage") r_Marray<char>(interv);
+ memset(mddPtr->get_array(), 0, interv.cell_count());
+
+ ta.begin();
+
+ cout << "Starting write transaction, press return to commit..." << flush;
+
+ sprintf(queryString, "INSERT INTO %s VALUES $1", collname);
+ r_OQL_Query query(queryString);
+ query << (*mddPtr);
+ r_oql_execute(query);
+
+ while (fgetc(stdin) == EOF) ;
+
+ ta.commit();
+
+ cout << "Write transaction successful." << endl;
+ }
+ catch(r_Error &err)
+ {
+ cerr << "Write transaction failed: " << err.what() << endl;
+ ta.abort();
+ db.close();
+ exit(0);
+ }
+
+ db.close();
+
+ return 0;
+}
diff --git a/rasodmg/test/tmov_16.ql b/rasodmg/test/tmov_16.ql
new file mode 100644
index 0000000..2742c4d
--- /dev/null
+++ b/rasodmg/test/tmov_16.ql
@@ -0,0 +1,425 @@
+// This query tests different selectivities with moving query boxes
+// on tomo_cubed with 16kB tiles ([0:24,0:24,0:24]). Each selectivity
+// is repeated 20 times with query boxes of the same shape and size
+// starting at different origins.
+
+// [0.5]: [39:83, 43:87, 117:143]
+SELECT img[39:83, 43:87, 117:143]
+FROM tomo_cubed_16 AS img
+// [0.5]: [146:190, 116:160, 35:61]
+SELECT img[146:190, 116:160, 35:61]
+FROM tomo_cubed_16 AS img
+// [0.5]: [17:61, 42:86, 15:41]
+SELECT img[17:61, 42:86, 15:41]
+FROM tomo_cubed_16 AS img
+// [0.5]: [112:156, 154:198, 108:134]
+SELECT img[112:156, 154:198, 108:134]
+FROM tomo_cubed_16 AS img
+// [0.5]: [138:182, 26:70, 48:74]
+SELECT img[138:182, 26:70, 48:74]
+FROM tomo_cubed_16 AS img
+// [0.5]: [53:97, 94:138, 22:48]
+SELECT img[53:97, 94:138, 22:48]
+FROM tomo_cubed_16 AS img
+// [0.5]: [190:234, 59:103, 17:43]
+SELECT img[190:234, 59:103, 17:43]
+FROM tomo_cubed_16 AS img
+// [0.5]: [118:162, 147:191, 30:56]
+SELECT img[118:162, 147:191, 30:56]
+FROM tomo_cubed_16 AS img
+// [0.5]: [210:254, 179:223, 18:44]
+SELECT img[210:254, 179:223, 18:44]
+FROM tomo_cubed_16 AS img
+// [0.5]: [129:173, 76:120, 102:128]
+SELECT img[129:173, 76:120, 102:128]
+FROM tomo_cubed_16 AS img
+// [0.5]: [199:243, 119:163, 59:85]
+SELECT img[199:243, 119:163, 59:85]
+FROM tomo_cubed_16 AS img
+// [0.5]: [47:91, 52:96, 108:134]
+SELECT img[47:91, 52:96, 108:134]
+FROM tomo_cubed_16 AS img
+// [0.5]: [87:131, 103:147, 11:37]
+SELECT img[87:131, 103:147, 11:37]
+FROM tomo_cubed_16 AS img
+// [0.5]: [32:76, 81:125, 87:113]
+SELECT img[32:76, 81:125, 87:113]
+FROM tomo_cubed_16 AS img
+// [0.5]: [14:58, 77:121, 0:26]
+SELECT img[14:58, 77:121, 0:26]
+FROM tomo_cubed_16 AS img
+// [0.5]: [128:172, 145:189, 21:47]
+SELECT img[128:172, 145:189, 21:47]
+FROM tomo_cubed_16 AS img
+// [0.5]: [185:229, 102:146, 60:86]
+SELECT img[185:229, 102:146, 60:86]
+FROM tomo_cubed_16 AS img
+// [0.5]: [40:84, 39:83, 106:132]
+SELECT img[40:84, 39:83, 106:132]
+FROM tomo_cubed_16 AS img
+// [0.5]: [37:81, 10:54, 51:77]
+SELECT img[37:81, 10:54, 51:77]
+FROM tomo_cubed_16 AS img
+// [0.5]: [46:90, 21:65, 102:128]
+SELECT img[46:90, 21:65, 102:128]
+FROM tomo_cubed_16 AS img
+// [1]: [199:254, 50:105, 11:44]
+SELECT img[199:254, 50:105, 11:44]
+FROM tomo_cubed_16 AS img
+// [1]: [180:235, 51:106, 91:124]
+SELECT img[180:235, 51:106, 91:124]
+FROM tomo_cubed_16 AS img
+// [1]: [199:254, 43:98, 113:146]
+SELECT img[199:254, 43:98, 113:146]
+FROM tomo_cubed_16 AS img
+// [1]: [78:133, 40:95, 37:70]
+SELECT img[78:133, 40:95, 37:70]
+FROM tomo_cubed_16 AS img
+// [1]: [11:66, 98:153, 19:52]
+SELECT img[11:66, 98:153, 19:52]
+FROM tomo_cubed_16 AS img
+// [1]: [90:145, 74:129, 83:116]
+SELECT img[90:145, 74:129, 83:116]
+FROM tomo_cubed_16 AS img
+// [1]: [82:137, 103:158, 1:34]
+SELECT img[82:137, 103:158, 1:34]
+FROM tomo_cubed_16 AS img
+// [1]: [186:241, 191:246, 47:80]
+SELECT img[186:241, 191:246, 47:80]
+FROM tomo_cubed_16 AS img
+// [1]: [143:198, 68:123, 77:110]
+SELECT img[143:198, 68:123, 77:110]
+FROM tomo_cubed_16 AS img
+// [1]: [188:243, 23:78, 94:127]
+SELECT img[188:243, 23:78, 94:127]
+FROM tomo_cubed_16 AS img
+// [1]: [71:126, 11:66, 75:108]
+SELECT img[71:126, 11:66, 75:108]
+FROM tomo_cubed_16 AS img
+// [1]: [89:144, 109:164, 12:45]
+SELECT img[89:144, 109:164, 12:45]
+FROM tomo_cubed_16 AS img
+// [1]: [47:102, 56:111, 14:47]
+SELECT img[47:102, 56:111, 14:47]
+FROM tomo_cubed_16 AS img
+// [1]: [24:79, 190:245, 77:110]
+SELECT img[24:79, 190:245, 77:110]
+FROM tomo_cubed_16 AS img
+// [1]: [14:69, 189:244, 0:33]
+SELECT img[14:69, 189:244, 0:33]
+FROM tomo_cubed_16 AS img
+// [1]: [198:253, 167:222, 117:150]
+SELECT img[198:253, 167:222, 117:150]
+FROM tomo_cubed_16 AS img
+// [1]: [125:180, 1:56, 113:146]
+SELECT img[125:180, 1:56, 113:146]
+FROM tomo_cubed_16 AS img
+// [1]: [90:145, 126:181, 109:142]
+SELECT img[90:145, 126:181, 109:142]
+FROM tomo_cubed_16 AS img
+// [1]: [154:209, 9:64, 47:80]
+SELECT img[154:209, 9:64, 47:80]
+FROM tomo_cubed_16 AS img
+// [1]: [81:136, 1:56, 87:120]
+SELECT img[81:136, 1:56, 87:120]
+FROM tomo_cubed_16 AS img
+// [2]: [116:185, 1:70, 77:119]
+SELECT img[116:185, 1:70, 77:119]
+FROM tomo_cubed_16 AS img
+// [2]: [99:168, 87:156, 20:62]
+SELECT img[99:168, 87:156, 20:62]
+FROM tomo_cubed_16 AS img
+// [2]: [81:150, 74:143, 35:77]
+SELECT img[81:150, 74:143, 35:77]
+FROM tomo_cubed_16 AS img
+// [2]: [16:85, 100:169, 56:98]
+SELECT img[16:85, 100:169, 56:98]
+FROM tomo_cubed_16 AS img
+// [2]: [180:249, 47:116, 92:134]
+SELECT img[180:249, 47:116, 92:134]
+FROM tomo_cubed_16 AS img
+// [2]: [78:147, 57:126, 9:51]
+SELECT img[78:147, 57:126, 9:51]
+FROM tomo_cubed_16 AS img
+// [2]: [160:229, 76:145, 39:81]
+SELECT img[160:229, 76:145, 39:81]
+FROM tomo_cubed_16 AS img
+// [2]: [95:164, 29:98, 26:68]
+SELECT img[95:164, 29:98, 26:68]
+FROM tomo_cubed_16 AS img
+// [2]: [143:212, 120:189, 35:77]
+SELECT img[143:212, 120:189, 35:77]
+FROM tomo_cubed_16 AS img
+// [2]: [163:232, 116:185, 78:120]
+SELECT img[163:232, 116:185, 78:120]
+FROM tomo_cubed_16 AS img
+// [2]: [116:185, 58:127, 69:111]
+SELECT img[116:185, 58:127, 69:111]
+FROM tomo_cubed_16 AS img
+// [2]: [38:107, 169:238, 0:42]
+SELECT img[38:107, 169:238, 0:42]
+FROM tomo_cubed_16 AS img
+// [2]: [87:156, 112:181, 41:83]
+SELECT img[87:156, 112:181, 41:83]
+FROM tomo_cubed_16 AS img
+// [2]: [14:83, 118:187, 37:79]
+SELECT img[14:83, 118:187, 37:79]
+FROM tomo_cubed_16 AS img
+// [2]: [24:93, 172:241, 27:69]
+SELECT img[24:93, 172:241, 27:69]
+FROM tomo_cubed_16 AS img
+// [2]: [105:174, 14:83, 21:63]
+SELECT img[105:174, 14:83, 21:63]
+FROM tomo_cubed_16 AS img
+// [2]: [54:123, 92:161, 0:42]
+SELECT img[54:123, 92:161, 0:42]
+FROM tomo_cubed_16 AS img
+// [2]: [151:220, 160:229, 58:100]
+SELECT img[151:220, 160:229, 58:100]
+FROM tomo_cubed_16 AS img
+// [2]: [73:142, 42:111, 73:115]
+SELECT img[73:142, 42:111, 73:115]
+FROM tomo_cubed_16 AS img
+// [2]: [38:107, 181:250, 25:67]
+SELECT img[38:107, 181:250, 25:67]
+FROM tomo_cubed_16 AS img
+// [5]: [82:176, 43:137, 32:88]
+SELECT img[82:176, 43:137, 32:88]
+FROM tomo_cubed_16 AS img
+// [5]: [114:208, 6:100, 52:108]
+SELECT img[114:208, 6:100, 52:108]
+FROM tomo_cubed_16 AS img
+// [5]: [116:210, 132:226, 29:85]
+SELECT img[116:210, 132:226, 29:85]
+FROM tomo_cubed_16 AS img
+// [5]: [29:123, 69:163, 53:109]
+SELECT img[29:123, 69:163, 53:109]
+FROM tomo_cubed_16 AS img
+// [5]: [85:179, 1:95, 72:128]
+SELECT img[85:179, 1:95, 72:128]
+FROM tomo_cubed_16 AS img
+// [5]: [80:174, 121:215, 27:83]
+SELECT img[80:174, 121:215, 27:83]
+FROM tomo_cubed_16 AS img
+// [5]: [142:236, 129:223, 46:102]
+SELECT img[142:236, 129:223, 46:102]
+FROM tomo_cubed_16 AS img
+// [5]: [130:224, 156:250, 82:138]
+SELECT img[130:224, 156:250, 82:138]
+FROM tomo_cubed_16 AS img
+// [5]: [27:121, 111:205, 45:101]
+SELECT img[27:121, 111:205, 45:101]
+FROM tomo_cubed_16 AS img
+// [5]: [139:233, 122:216, 49:105]
+SELECT img[139:233, 122:216, 49:105]
+FROM tomo_cubed_16 AS img
+// [5]: [12:106, 3:97, 84:140]
+SELECT img[12:106, 3:97, 84:140]
+FROM tomo_cubed_16 AS img
+// [5]: [73:167, 70:164, 1:57]
+SELECT img[73:167, 70:164, 1:57]
+FROM tomo_cubed_16 AS img
+// [5]: [160:254, 1:95, 80:136]
+SELECT img[160:254, 1:95, 80:136]
+FROM tomo_cubed_16 AS img
+// [5]: [152:246, 54:148, 72:128]
+SELECT img[152:246, 54:148, 72:128]
+FROM tomo_cubed_16 AS img
+// [5]: [25:119, 50:144, 55:111]
+SELECT img[25:119, 50:144, 55:111]
+FROM tomo_cubed_16 AS img
+// [5]: [151:245, 34:128, 92:148]
+SELECT img[151:245, 34:128, 92:148]
+FROM tomo_cubed_16 AS img
+// [5]: [28:122, 68:162, 76:132]
+SELECT img[28:122, 68:162, 76:132]
+FROM tomo_cubed_16 AS img
+// [5]: [145:239, 98:192, 44:100]
+SELECT img[145:239, 98:192, 44:100]
+FROM tomo_cubed_16 AS img
+// [5]: [73:167, 122:216, 2:58]
+SELECT img[73:167, 122:216, 2:58]
+FROM tomo_cubed_16 AS img
+// [5]: [1:95, 107:201, 68:124]
+SELECT img[1:95, 107:201, 68:124]
+FROM tomo_cubed_16 AS img
+// [10]: [102:220, 43:161, 75:146]
+SELECT img[102:220, 43:161, 75:146]
+FROM tomo_cubed_16 AS img
+// [10]: [106:224, 36:154, 79:150]
+SELECT img[106:224, 36:154, 79:150]
+FROM tomo_cubed_16 AS img
+// [10]: [95:213, 56:174, 69:140]
+SELECT img[95:213, 56:174, 69:140]
+FROM tomo_cubed_16 AS img
+// [10]: [62:180, 126:244, 74:145]
+SELECT img[62:180, 126:244, 74:145]
+FROM tomo_cubed_16 AS img
+// [10]: [93:211, 63:181, 46:117]
+SELECT img[93:211, 63:181, 46:117]
+FROM tomo_cubed_16 AS img
+// [10]: [129:247, 74:192, 67:138]
+SELECT img[129:247, 74:192, 67:138]
+FROM tomo_cubed_16 AS img
+// [10]: [44:162, 84:202, 75:146]
+SELECT img[44:162, 84:202, 75:146]
+FROM tomo_cubed_16 AS img
+// [10]: [52:170, 107:225, 19:90]
+SELECT img[52:170, 107:225, 19:90]
+FROM tomo_cubed_16 AS img
+// [10]: [89:207, 94:212, 9:80]
+SELECT img[89:207, 94:212, 9:80]
+FROM tomo_cubed_16 AS img
+// [10]: [52:170, 120:238, 67:138]
+SELECT img[52:170, 120:238, 67:138]
+FROM tomo_cubed_16 AS img
+// [10]: [98:216, 51:169, 42:113]
+SELECT img[98:216, 51:169, 42:113]
+FROM tomo_cubed_16 AS img
+// [10]: [30:148, 109:227, 51:122]
+SELECT img[30:148, 109:227, 51:122]
+FROM tomo_cubed_16 AS img
+// [10]: [130:248, 118:236, 30:101]
+SELECT img[130:248, 118:236, 30:101]
+FROM tomo_cubed_16 AS img
+// [10]: [25:143, 25:143, 46:117]
+SELECT img[25:143, 25:143, 46:117]
+FROM tomo_cubed_16 AS img
+// [10]: [86:204, 119:237, 12:83]
+SELECT img[86:204, 119:237, 12:83]
+FROM tomo_cubed_16 AS img
+// [10]: [116:234, 18:136, 11:82]
+SELECT img[116:234, 18:136, 11:82]
+FROM tomo_cubed_16 AS img
+// [10]: [61:179, 24:142, 68:139]
+SELECT img[61:179, 24:142, 68:139]
+FROM tomo_cubed_16 AS img
+// [10]: [53:171, 14:132, 72:143]
+SELECT img[53:171, 14:132, 72:143]
+FROM tomo_cubed_16 AS img
+// [10]: [49:167, 84:202, 64:135]
+SELECT img[49:167, 84:202, 64:135]
+FROM tomo_cubed_16 AS img
+// [10]: [85:203, 80:198, 13:84]
+SELECT img[85:203, 80:198, 13:84]
+FROM tomo_cubed_16 AS img
+// [20]: [97:246, 85:234, 54:143]
+SELECT img[97:246, 85:234, 54:143]
+FROM tomo_cubed_16 AS img
+// [20]: [63:212, 18:167, 43:132]
+SELECT img[63:212, 18:167, 43:132]
+FROM tomo_cubed_16 AS img
+// [20]: [99:248, 28:177, 58:147]
+SELECT img[99:248, 28:177, 58:147]
+FROM tomo_cubed_16 AS img
+// [20]: [57:206, 16:165, 46:135]
+SELECT img[57:206, 16:165, 46:135]
+FROM tomo_cubed_16 AS img
+// [20]: [83:232, 93:242, 36:125]
+SELECT img[83:232, 93:242, 36:125]
+FROM tomo_cubed_16 AS img
+// [20]: [57:206, 31:180, 48:137]
+SELECT img[57:206, 31:180, 48:137]
+FROM tomo_cubed_16 AS img
+// [20]: [86:235, 70:219, 32:121]
+SELECT img[86:235, 70:219, 32:121]
+FROM tomo_cubed_16 AS img
+// [20]: [39:188, 49:198, 50:139]
+SELECT img[39:188, 49:198, 50:139]
+FROM tomo_cubed_16 AS img
+// [20]: [62:211, 104:253, 29:118]
+SELECT img[62:211, 104:253, 29:118]
+FROM tomo_cubed_16 AS img
+// [20]: [103:252, 44:193, 13:102]
+SELECT img[103:252, 44:193, 13:102]
+FROM tomo_cubed_16 AS img
+// [20]: [48:197, 14:163, 2:91]
+SELECT img[48:197, 14:163, 2:91]
+FROM tomo_cubed_16 AS img
+// [20]: [0:149, 79:228, 13:102]
+SELECT img[0:149, 79:228, 13:102]
+FROM tomo_cubed_16 AS img
+// [20]: [6:155, 103:252, 35:124]
+SELECT img[6:155, 103:252, 35:124]
+FROM tomo_cubed_16 AS img
+// [20]: [0:149, 91:240, 46:135]
+SELECT img[0:149, 91:240, 46:135]
+FROM tomo_cubed_16 AS img
+// [20]: [23:172, 50:199, 42:131]
+SELECT img[23:172, 50:199, 42:131]
+FROM tomo_cubed_16 AS img
+// [20]: [80:229, 33:182, 17:106]
+SELECT img[80:229, 33:182, 17:106]
+FROM tomo_cubed_16 AS img
+// [20]: [38:187, 41:190, 1:90]
+SELECT img[38:187, 41:190, 1:90]
+FROM tomo_cubed_16 AS img
+// [20]: [42:191, 17:166, 39:128]
+SELECT img[42:191, 17:166, 39:128]
+FROM tomo_cubed_16 AS img
+// [20]: [98:247, 95:244, 58:147]
+SELECT img[98:247, 95:244, 58:147]
+FROM tomo_cubed_16 AS img
+// [20]: [10:159, 51:200, 21:110]
+SELECT img[10:159, 51:200, 21:110]
+FROM tomo_cubed_16 AS img
+// [50]: [8:210, 13:215, 9:130]
+SELECT img[8:210, 13:215, 9:130]
+FROM tomo_cubed_16 AS img
+// [50]: [48:250, 45:247, 24:145]
+SELECT img[48:250, 45:247, 24:145]
+FROM tomo_cubed_16 AS img
+// [50]: [29:231, 6:208, 23:144]
+SELECT img[29:231, 6:208, 23:144]
+FROM tomo_cubed_16 AS img
+// [50]: [12:214, 44:246, 23:144]
+SELECT img[12:214, 44:246, 23:144]
+FROM tomo_cubed_16 AS img
+// [50]: [11:213, 27:229, 7:128]
+SELECT img[11:213, 27:229, 7:128]
+FROM tomo_cubed_16 AS img
+// [50]: [1:203, 2:204, 14:135]
+SELECT img[1:203, 2:204, 14:135]
+FROM tomo_cubed_16 AS img
+// [50]: [22:224, 50:252, 10:131]
+SELECT img[22:224, 50:252, 10:131]
+FROM tomo_cubed_16 AS img
+// [50]: [15:217, 35:237, 9:130]
+SELECT img[15:217, 35:237, 9:130]
+FROM tomo_cubed_16 AS img
+// [50]: [4:206, 51:253, 28:149]
+SELECT img[4:206, 51:253, 28:149]
+FROM tomo_cubed_16 AS img
+// [50]: [22:224, 20:222, 31:152]
+SELECT img[22:224, 20:222, 31:152]
+FROM tomo_cubed_16 AS img
+// [50]: [16:218, 42:244, 27:148]
+SELECT img[16:218, 42:244, 27:148]
+FROM tomo_cubed_16 AS img
+// [50]: [21:223, 32:234, 22:143]
+SELECT img[21:223, 32:234, 22:143]
+FROM tomo_cubed_16 AS img
+// [50]: [37:239, 44:246, 29:150]
+SELECT img[37:239, 44:246, 29:150]
+FROM tomo_cubed_16 AS img
+// [50]: [17:219, 49:251, 14:135]
+SELECT img[17:219, 49:251, 14:135]
+FROM tomo_cubed_16 AS img
+// [50]: [49:251, 50:252, 3:124]
+SELECT img[49:251, 50:252, 3:124]
+FROM tomo_cubed_16 AS img
+// [50]: [17:219, 15:217, 1:122]
+SELECT img[17:219, 15:217, 1:122]
+FROM tomo_cubed_16 AS img
+// [50]: [21:223, 51:253, 13:134]
+SELECT img[21:223, 51:253, 13:134]
+FROM tomo_cubed_16 AS img
+// [50]: [7:209, 47:249, 11:132]
+SELECT img[7:209, 47:249, 11:132]
+FROM tomo_cubed_16 AS img
+// [50]: [4:206, 22:224, 4:125]
+SELECT img[4:206, 22:224, 4:125]
+FROM tomo_cubed_16 AS img
+// [50]: [16:218, 51:253, 21:142]
+SELECT img[16:218, 51:253, 21:142]
+FROM tomo_cubed_16 AS img
diff --git a/rasodmg/test/tmov_32.ql b/rasodmg/test/tmov_32.ql
new file mode 100644
index 0000000..db9eb7d
--- /dev/null
+++ b/rasodmg/test/tmov_32.ql
@@ -0,0 +1,425 @@
+// This query tests different selectivities with moving query boxes
+// on tomo_cubed with 32kB tiles ([0:31,0:31,0:31]). Each selectivity
+// is repeated 20 times with query boxes of the same shape and size
+// starting at different origins.
+
+// [0.5]: [46:90, 176:220, 60:86]
+SELECT img[46:90, 176:220, 60:86]
+FROM tomo_cubed AS img
+// [0.5]: [143:187, 175:219, 106:132]
+SELECT img[143:187, 175:219, 106:132]
+FROM tomo_cubed AS img
+// [0.5]: [169:213, 75:119, 66:92]
+SELECT img[169:213, 75:119, 66:92]
+FROM tomo_cubed AS img
+// [0.5]: [90:134, 178:222, 48:74]
+SELECT img[90:134, 178:222, 48:74]
+FROM tomo_cubed AS img
+// [0.5]: [76:120, 136:180, 31:57]
+SELECT img[76:120, 136:180, 31:57]
+FROM tomo_cubed AS img
+// [0.5]: [7:51, 150:194, 89:115]
+SELECT img[7:51, 150:194, 89:115]
+FROM tomo_cubed AS img
+// [0.5]: [133:177, 113:157, 0:26]
+SELECT img[133:177, 113:157, 0:26]
+FROM tomo_cubed AS img
+// [0.5]: [114:158, 125:169, 108:134]
+SELECT img[114:158, 125:169, 108:134]
+FROM tomo_cubed AS img
+// [0.5]: [210:254, 12:56, 56:82]
+SELECT img[210:254, 12:56, 56:82]
+FROM tomo_cubed AS img
+// [0.5]: [176:220, 171:215, 83:109]
+SELECT img[176:220, 171:215, 83:109]
+FROM tomo_cubed AS img
+// [0.5]: [102:146, 50:94, 34:60]
+SELECT img[102:146, 50:94, 34:60]
+FROM tomo_cubed AS img
+// [0.5]: [134:178, 96:140, 97:123]
+SELECT img[134:178, 96:140, 97:123]
+FROM tomo_cubed AS img
+// [0.5]: [200:244, 43:87, 123:149]
+SELECT img[200:244, 43:87, 123:149]
+FROM tomo_cubed AS img
+// [0.5]: [155:199, 127:171, 48:74]
+SELECT img[155:199, 127:171, 48:74]
+FROM tomo_cubed AS img
+// [0.5]: [111:155, 80:124, 11:37]
+SELECT img[111:155, 80:124, 11:37]
+FROM tomo_cubed AS img
+// [0.5]: [164:208, 2:46, 64:90]
+SELECT img[164:208, 2:46, 64:90]
+FROM tomo_cubed AS img
+// [0.5]: [137:181, 102:146, 17:43]
+SELECT img[137:181, 102:146, 17:43]
+FROM tomo_cubed AS img
+// [0.5]: [100:144, 149:193, 121:147]
+SELECT img[100:144, 149:193, 121:147]
+FROM tomo_cubed AS img
+// [0.5]: [186:230, 38:82, 108:134]
+SELECT img[186:230, 38:82, 108:134]
+FROM tomo_cubed AS img
+// [0.5]: [48:92, 53:97, 14:40]
+SELECT img[48:92, 53:97, 14:40]
+FROM tomo_cubed AS img
+// [1]: [64:119, 65:120, 57:90]
+SELECT img[64:119, 65:120, 57:90]
+FROM tomo_cubed AS img
+// [1]: [13:68, 121:176, 20:53]
+SELECT img[13:68, 121:176, 20:53]
+FROM tomo_cubed AS img
+// [1]: [3:58, 115:170, 59:92]
+SELECT img[3:58, 115:170, 59:92]
+FROM tomo_cubed AS img
+// [1]: [174:229, 82:137, 93:126]
+SELECT img[174:229, 82:137, 93:126]
+FROM tomo_cubed AS img
+// [1]: [40:95, 143:198, 43:76]
+SELECT img[40:95, 143:198, 43:76]
+FROM tomo_cubed AS img
+// [1]: [126:181, 160:215, 86:119]
+SELECT img[126:181, 160:215, 86:119]
+FROM tomo_cubed AS img
+// [1]: [20:75, 44:99, 89:122]
+SELECT img[20:75, 44:99, 89:122]
+FROM tomo_cubed AS img
+// [1]: [15:70, 92:147, 23:56]
+SELECT img[15:70, 92:147, 23:56]
+FROM tomo_cubed AS img
+// [1]: [122:177, 62:117, 75:108]
+SELECT img[122:177, 62:117, 75:108]
+FROM tomo_cubed AS img
+// [1]: [183:238, 174:229, 70:103]
+SELECT img[183:238, 174:229, 70:103]
+FROM tomo_cubed AS img
+// [1]: [13:68, 82:137, 97:130]
+SELECT img[13:68, 82:137, 97:130]
+FROM tomo_cubed AS img
+// [1]: [174:229, 107:162, 91:124]
+SELECT img[174:229, 107:162, 91:124]
+FROM tomo_cubed AS img
+// [1]: [79:134, 83:138, 88:121]
+SELECT img[79:134, 83:138, 88:121]
+FROM tomo_cubed AS img
+// [1]: [3:58, 62:117, 39:72]
+SELECT img[3:58, 62:117, 39:72]
+FROM tomo_cubed AS img
+// [1]: [96:151, 25:80, 93:126]
+SELECT img[96:151, 25:80, 93:126]
+FROM tomo_cubed AS img
+// [1]: [124:179, 183:238, 21:54]
+SELECT img[124:179, 183:238, 21:54]
+FROM tomo_cubed AS img
+// [1]: [106:161, 111:166, 89:122]
+SELECT img[106:161, 111:166, 89:122]
+FROM tomo_cubed AS img
+// [1]: [66:121, 103:158, 74:107]
+SELECT img[66:121, 103:158, 74:107]
+FROM tomo_cubed AS img
+// [1]: [180:235, 131:186, 80:113]
+SELECT img[180:235, 131:186, 80:113]
+FROM tomo_cubed AS img
+// [1]: [4:59, 132:187, 59:92]
+SELECT img[4:59, 132:187, 59:92]
+FROM tomo_cubed AS img
+// [2]: [69:138, 184:253, 75:117]
+SELECT img[69:138, 184:253, 75:117]
+FROM tomo_cubed AS img
+// [2]: [58:127, 168:237, 87:129]
+SELECT img[58:127, 168:237, 87:129]
+FROM tomo_cubed AS img
+// [2]: [162:231, 145:214, 58:100]
+SELECT img[162:231, 145:214, 58:100]
+FROM tomo_cubed AS img
+// [2]: [129:198, 122:191, 7:49]
+SELECT img[129:198, 122:191, 7:49]
+FROM tomo_cubed AS img
+// [2]: [86:155, 170:239, 54:96]
+SELECT img[86:155, 170:239, 54:96]
+FROM tomo_cubed AS img
+// [2]: [0:69, 98:167, 70:112]
+SELECT img[0:69, 98:167, 70:112]
+FROM tomo_cubed AS img
+// [2]: [41:110, 33:102, 58:100]
+SELECT img[41:110, 33:102, 58:100]
+FROM tomo_cubed AS img
+// [2]: [37:106, 24:93, 65:107]
+SELECT img[37:106, 24:93, 65:107]
+FROM tomo_cubed AS img
+// [2]: [39:108, 114:183, 26:68]
+SELECT img[39:108, 114:183, 26:68]
+FROM tomo_cubed AS img
+// [2]: [166:235, 9:78, 38:80]
+SELECT img[166:235, 9:78, 38:80]
+FROM tomo_cubed AS img
+// [2]: [147:216, 174:243, 45:87]
+SELECT img[147:216, 174:243, 45:87]
+FROM tomo_cubed AS img
+// [2]: [121:190, 69:138, 58:100]
+SELECT img[121:190, 69:138, 58:100]
+FROM tomo_cubed AS img
+// [2]: [87:156, 78:147, 73:115]
+SELECT img[87:156, 78:147, 73:115]
+FROM tomo_cubed AS img
+// [2]: [31:100, 109:178, 75:117]
+SELECT img[31:100, 109:178, 75:117]
+FROM tomo_cubed AS img
+// [2]: [54:123, 155:224, 26:68]
+SELECT img[54:123, 155:224, 26:68]
+FROM tomo_cubed AS img
+// [2]: [150:219, 139:208, 25:67]
+SELECT img[150:219, 139:208, 25:67]
+FROM tomo_cubed AS img
+// [2]: [65:134, 119:188, 87:129]
+SELECT img[65:134, 119:188, 87:129]
+FROM tomo_cubed AS img
+// [2]: [159:228, 45:114, 47:89]
+SELECT img[159:228, 45:114, 47:89]
+FROM tomo_cubed AS img
+// [2]: [77:146, 60:129, 87:129]
+SELECT img[77:146, 60:129, 87:129]
+FROM tomo_cubed AS img
+// [2]: [169:238, 135:204, 4:46]
+SELECT img[169:238, 135:204, 4:46]
+FROM tomo_cubed AS img
+// [5]: [24:118, 61:155, 77:133]
+SELECT img[24:118, 61:155, 77:133]
+FROM tomo_cubed AS img
+// [5]: [137:231, 119:213, 11:67]
+SELECT img[137:231, 119:213, 11:67]
+FROM tomo_cubed AS img
+// [5]: [140:234, 131:225, 56:112]
+SELECT img[140:234, 131:225, 56:112]
+FROM tomo_cubed AS img
+// [5]: [154:248, 6:100, 54:110]
+SELECT img[154:248, 6:100, 54:110]
+FROM tomo_cubed AS img
+// [5]: [146:240, 62:156, 60:116]
+SELECT img[146:240, 62:156, 60:116]
+FROM tomo_cubed AS img
+// [5]: [78:172, 21:115, 3:59]
+SELECT img[78:172, 21:115, 3:59]
+FROM tomo_cubed AS img
+// [5]: [80:174, 33:127, 84:140]
+SELECT img[80:174, 33:127, 84:140]
+FROM tomo_cubed AS img
+// [5]: [138:232, 95:189, 52:108]
+SELECT img[138:232, 95:189, 52:108]
+FROM tomo_cubed AS img
+// [5]: [60:154, 136:230, 70:126]
+SELECT img[60:154, 136:230, 70:126]
+FROM tomo_cubed AS img
+// [5]: [79:173, 149:243, 65:121]
+SELECT img[79:173, 149:243, 65:121]
+FROM tomo_cubed AS img
+// [5]: [13:107, 53:147, 57:113]
+SELECT img[13:107, 53:147, 57:113]
+FROM tomo_cubed AS img
+// [5]: [13:107, 66:160, 44:100]
+SELECT img[13:107, 66:160, 44:100]
+FROM tomo_cubed AS img
+// [5]: [137:231, 47:141, 38:94]
+SELECT img[137:231, 47:141, 38:94]
+FROM tomo_cubed AS img
+// [5]: [11:105, 84:178, 42:98]
+SELECT img[11:105, 84:178, 42:98]
+FROM tomo_cubed AS img
+// [5]: [19:113, 31:125, 51:107]
+SELECT img[19:113, 31:125, 51:107]
+FROM tomo_cubed AS img
+// [5]: [27:121, 17:111, 29:85]
+SELECT img[27:121, 17:111, 29:85]
+FROM tomo_cubed AS img
+// [5]: [142:236, 76:170, 94:150]
+SELECT img[142:236, 76:170, 94:150]
+FROM tomo_cubed AS img
+// [5]: [153:247, 71:165, 83:139]
+SELECT img[153:247, 71:165, 83:139]
+FROM tomo_cubed AS img
+// [5]: [12:106, 108:202, 79:135]
+SELECT img[12:106, 108:202, 79:135]
+FROM tomo_cubed AS img
+// [5]: [146:240, 26:120, 59:115]
+SELECT img[146:240, 26:120, 59:115]
+FROM tomo_cubed AS img
+// 1[0]: [3:121, 62:180, 39:110]
+SELECT img[3:121, 62:180, 39:110]
+FROM tomo_cubed AS img
+// 1[0]: [11:129, 26:144, 19:90]
+SELECT img[11:129, 26:144, 19:90]
+FROM tomo_cubed AS img
+// 1[0]: [49:167, 76:194, 77:148]
+SELECT img[49:167, 76:194, 77:148]
+FROM tomo_cubed AS img
+// [10]: [55:173, 86:204, 21:92]
+SELECT img[55:173, 86:204, 21:92]
+FROM tomo_cubed AS img
+// [10]: [110:228, 98:216, 80:151]
+SELECT img[110:228, 98:216, 80:151]
+FROM tomo_cubed AS img
+// [10]: [123:241, 28:146, 59:130]
+SELECT img[123:241, 28:146, 59:130]
+FROM tomo_cubed AS img
+// [10]: [89:207, 90:208, 34:105]
+SELECT img[89:207, 90:208, 34:105]
+FROM tomo_cubed AS img
+// [10]: [111:229, 51:169, 5:76]
+SELECT img[111:229, 51:169, 5:76]
+FROM tomo_cubed AS img
+// [10]: [15:133, 74:192, 12:83]
+SELECT img[15:133, 74:192, 12:83]
+FROM tomo_cubed AS img
+// [10]: [103:221, 94:212, 74:145]
+SELECT img[103:221, 94:212, 74:145]
+FROM tomo_cubed AS img
+// [10]: [107:225, 111:229, 16:87]
+SELECT img[107:225, 111:229, 16:87]
+FROM tomo_cubed AS img
+// [10]: [14:132, 80:198, 58:129]
+SELECT img[14:132, 80:198, 58:129]
+FROM tomo_cubed AS img
+// [10]: [2:120, 64:182, 25:96]
+SELECT img[2:120, 64:182, 25:96]
+FROM tomo_cubed AS img
+// [10]: [74:192, 130:248, 3:74]
+SELECT img[74:192, 130:248, 3:74]
+FROM tomo_cubed AS img
+// [10]: [96:214, 61:179, 14:85]
+SELECT img[96:214, 61:179, 14:85]
+FROM tomo_cubed AS img
+// [10]: [73:191, 93:211, 6:77]
+SELECT img[73:191, 93:211, 6:77]
+FROM tomo_cubed AS img
+// [10]: [55:173, 12:130, 54:125]
+SELECT img[55:173, 12:130, 54:125]
+FROM tomo_cubed AS img
+// [10]: [1:119, 123:241, 51:122]
+SELECT img[1:119, 123:241, 51:122]
+FROM tomo_cubed AS img
+// [10]: [117:235, 101:219, 55:126]
+SELECT img[117:235, 101:219, 55:126]
+FROM tomo_cubed AS img
+// [10]: [24:142, 26:144, 33:104]
+SELECT img[24:142, 26:144, 33:104]
+FROM tomo_cubed AS img
+// [20]: [36:185, 0:149, 39:128]
+SELECT img[36:185, 0:149, 39:128]
+FROM tomo_cubed AS img
+// [20]: [85:234, 31:180, 54:143]
+SELECT img[85:234, 31:180, 54:143]
+FROM tomo_cubed AS img
+// [20]: [55:204, 78:227, 20:109]
+SELECT img[55:204, 78:227, 20:109]
+FROM tomo_cubed AS img
+// [20]: [28:177, 98:247, 26:115]
+SELECT img[28:177, 98:247, 26:115]
+FROM tomo_cubed AS img
+// [20]: [53:202, 14:163, 15:104]
+SELECT img[53:202, 14:163, 15:104]
+FROM tomo_cubed AS img
+// [20]: [84:233, 59:208, 28:117]
+SELECT img[84:233, 59:208, 28:117]
+FROM tomo_cubed AS img
+// [20]: [24:173, 81:230, 21:110]
+SELECT img[24:173, 81:230, 21:110]
+FROM tomo_cubed AS img
+// [20]: [70:219, 103:252, 59:148]
+SELECT img[70:219, 103:252, 59:148]
+FROM tomo_cubed AS img
+// [20]: [75:224, 32:181, 36:125]
+SELECT img[75:224, 32:181, 36:125]
+FROM tomo_cubed AS img
+// [20]: [80:229, 65:214, 22:111]
+SELECT img[80:229, 65:214, 22:111]
+FROM tomo_cubed AS img
+// [20]: [5:154, 34:183, 20:109]
+SELECT img[5:154, 34:183, 20:109]
+FROM tomo_cubed AS img
+// [20]: [16:165, 72:221, 57:146]
+SELECT img[16:165, 72:221, 57:146]
+FROM tomo_cubed AS img
+// [20]: [90:239, 27:176, 55:144]
+SELECT img[90:239, 27:176, 55:144]
+FROM tomo_cubed AS img
+// [20]: [81:230, 63:212, 61:150]
+SELECT img[81:230, 63:212, 61:150]
+FROM tomo_cubed AS img
+// [20]: [87:236, 79:228, 61:150]
+SELECT img[87:236, 79:228, 61:150]
+FROM tomo_cubed AS img
+// [20]: [100:249, 33:182, 35:124]
+SELECT img[100:249, 33:182, 35:124]
+FROM tomo_cubed AS img
+// [20]: [14:163, 91:240, 38:127]
+SELECT img[14:163, 91:240, 38:127]
+FROM tomo_cubed AS img
+// [20]: [60:209, 95:244, 11:100]
+SELECT img[60:209, 95:244, 11:100]
+FROM tomo_cubed AS img
+// [20]: [99:248, 4:153, 29:118]
+SELECT img[99:248, 4:153, 29:118]
+FROM tomo_cubed AS img
+// [20]: [10:159, 64:213, 32:121]
+SELECT img[10:159, 64:213, 32:121]
+FROM tomo_cubed AS img
+// [50]: [8:210, 0:202, 1:122]
+SELECT img[8:210, 0:202, 1:122]
+FROM tomo_cubed AS img
+// [50]: [17:219, 21:223, 6:127]
+SELECT img[17:219, 21:223, 6:127]
+FROM tomo_cubed AS img
+// [50]: [49:251, 0:202, 4:125]
+SELECT img[49:251, 0:202, 4:125]
+FROM tomo_cubed AS img
+// [50]: [11:213, 37:239, 15:136]
+SELECT img[11:213, 37:239, 15:136]
+FROM tomo_cubed AS img
+// [50]: [29:231, 36:238, 18:139]
+SELECT img[29:231, 36:238, 18:139]
+FROM tomo_cubed AS img
+// [50]: [38:240, 21:223, 2:123]
+SELECT img[38:240, 21:223, 2:123]
+FROM tomo_cubed AS img
+// [50]: [26:228, 4:206, 9:130]
+SELECT img[26:228, 4:206, 9:130]
+FROM tomo_cubed AS img
+// [50]: [1:203, 41:243, 21:142]
+SELECT img[1:203, 41:243, 21:142]
+FROM tomo_cubed AS img
+// [50]: [39:241, 37:239, 10:131]
+SELECT img[39:241, 37:239, 10:131]
+FROM tomo_cubed AS img
+// [50]: [6:208, 49:251, 2:123]
+SELECT img[6:208, 49:251, 2:123]
+FROM tomo_cubed AS img
+// [50]: [2:204, 51:253, 8:129]
+SELECT img[2:204, 51:253, 8:129]
+FROM tomo_cubed AS img
+// [50]: [23:225, 51:253, 9:130]
+SELECT img[23:225, 51:253, 9:130]
+FROM tomo_cubed AS img
+// [50]: [32:234, 43:245, 10:131]
+SELECT img[32:234, 43:245, 10:131]
+FROM tomo_cubed AS img
+// [50]: [33:235, 9:211, 31:152]
+SELECT img[33:235, 9:211, 31:152]
+FROM tomo_cubed AS img
+// [50]: [28:230, 36:238, 4:125]
+SELECT img[28:230, 36:238, 4:125]
+FROM tomo_cubed AS img
+// [50]: [25:227, 40:242, 3:124]
+SELECT img[25:227, 40:242, 3:124]
+FROM tomo_cubed AS img
+// [50]: [33:235, 28:230, 25:146]
+SELECT img[33:235, 28:230, 25:146]
+FROM tomo_cubed AS img
+// [50]: [42:244, 34:236, 1:122]
+SELECT img[42:244, 34:236, 1:122]
+FROM tomo_cubed AS img
+// [50]: [34:236, 47:249, 6:127]
+SELECT img[34:236, 47:249, 6:127]
+FROM tomo_cubed AS img
+// [50]: [35:237, 22:224, 31:152]
+SELECT img[35:237, 22:224, 31:152]
+FROM tomo_cubed AS img
diff --git a/rasodmg/test/tmov_64.ql b/rasodmg/test/tmov_64.ql
new file mode 100644
index 0000000..1ca53e6
--- /dev/null
+++ b/rasodmg/test/tmov_64.ql
@@ -0,0 +1,425 @@
+// This query tests different selectivities with moving query boxes
+// on tomo_cubed with 64kB tiles ([0:39,0:39,0:39]). Each selectivity
+// is repeated 20 times with query boxes of the same shape and size
+// starting at different origins.
+
+// [0.5]: [205:249, 154:198, 39:65]
+SELECT img[205:249, 154:198, 39:65]
+FROM tomo_cubed_64 AS img
+// [0.5]: [125:169, 124:168, 15:41]
+SELECT img[125:169, 124:168, 15:41]
+FROM tomo_cubed_64 AS img
+// [0.5]: [197:241, 71:115, 82:108]
+SELECT img[197:241, 71:115, 82:108]
+FROM tomo_cubed_64 AS img
+// [0.5]: [53:97, 192:236, 122:148]
+SELECT img[53:97, 192:236, 122:148]
+FROM tomo_cubed_64 AS img
+// [0.5]: [140:184, 93:137, 121:147]
+SELECT img[140:184, 93:137, 121:147]
+FROM tomo_cubed_64 AS img
+// [0.5]: [154:198, 82:126, 120:146]
+SELECT img[154:198, 82:126, 120:146]
+FROM tomo_cubed_64 AS img
+// [0.5]: [209:253, 51:95, 47:73]
+SELECT img[209:253, 51:95, 47:73]
+FROM tomo_cubed_64 AS img
+// [0.5]: [57:101, 159:203, 113:139]
+SELECT img[57:101, 159:203, 113:139]
+FROM tomo_cubed_64 AS img
+// [0.5]: [98:142, 166:210, 12:38]
+SELECT img[98:142, 166:210, 12:38]
+FROM tomo_cubed_64 AS img
+// [0.5]: [194:238, 88:132, 52:78]
+SELECT img[194:238, 88:132, 52:78]
+FROM tomo_cubed_64 AS img
+// [0.5]: [162:206, 101:145, 53:79]
+SELECT img[162:206, 101:145, 53:79]
+FROM tomo_cubed_64 AS img
+// [0.5]: [166:210, 60:104, 126:152]
+SELECT img[166:210, 60:104, 126:152]
+FROM tomo_cubed_64 AS img
+// [0.5]: [127:171, 157:201, 92:118]
+SELECT img[127:171, 157:201, 92:118]
+FROM tomo_cubed_64 AS img
+// [0.5]: [46:90, 94:138, 53:79]
+SELECT img[46:90, 94:138, 53:79]
+FROM tomo_cubed_64 AS img
+// [0.5]: [19:63, 42:86, 17:43]
+SELECT img[19:63, 42:86, 17:43]
+FROM tomo_cubed_64 AS img
+// [0.5]: [182:226, 0:44, 97:123]
+SELECT img[182:226, 0:44, 97:123]
+FROM tomo_cubed_64 AS img
+// [0.5]: [139:183, 98:142, 47:73]
+SELECT img[139:183, 98:142, 47:73]
+FROM tomo_cubed_64 AS img
+// [0.5]: [106:150, 182:226, 11:37]
+SELECT img[106:150, 182:226, 11:37]
+FROM tomo_cubed_64 AS img
+// [0.5]: [193:237, 200:244, 23:49]
+SELECT img[193:237, 200:244, 23:49]
+FROM tomo_cubed_64 AS img
+// [0.5]: [40:84, 2:46, 5:31]
+SELECT img[40:84, 2:46, 5:31]
+FROM tomo_cubed_64 AS img
+// [1]: [51:106, 169:224, 105:138]
+SELECT img[51:106, 169:224, 105:138]
+FROM tomo_cubed_64 AS img
+// [1]: [72:127, 30:85, 113:146]
+SELECT img[72:127, 30:85, 113:146]
+FROM tomo_cubed_64 AS img
+// [1]: [104:159, 82:137, 48:81]
+SELECT img[104:159, 82:137, 48:81]
+FROM tomo_cubed_64 AS img
+// [1]: [91:146, 86:141, 40:73]
+SELECT img[91:146, 86:141, 40:73]
+FROM tomo_cubed_64 AS img
+// [1]: [121:176, 19:74, 59:92]
+SELECT img[121:176, 19:74, 59:92]
+FROM tomo_cubed_64 AS img
+// [1]: [69:124, 156:211, 27:60]
+SELECT img[69:124, 156:211, 27:60]
+FROM tomo_cubed_64 AS img
+// [1]: [24:79, 64:119, 25:58]
+SELECT img[24:79, 64:119, 25:58]
+FROM tomo_cubed_64 AS img
+// [1]: [70:125, 193:248, 90:123]
+SELECT img[70:125, 193:248, 90:123]
+FROM tomo_cubed_64 AS img
+// [1]: [193:248, 1:56, 38:71]
+SELECT img[193:248, 1:56, 38:71]
+FROM tomo_cubed_64 AS img
+// [1]: [118:173, 178:233, 56:89]
+SELECT img[118:173, 178:233, 56:89]
+FROM tomo_cubed_64 AS img
+// [1]: [118:173, 23:78, 21:54]
+SELECT img[118:173, 23:78, 21:54]
+FROM tomo_cubed_64 AS img
+// [1]: [9:64, 166:221, 44:77]
+SELECT img[9:64, 166:221, 44:77]
+FROM tomo_cubed_64 AS img
+// [1]: [66:121, 65:120, 93:126]
+SELECT img[66:121, 65:120, 93:126]
+FROM tomo_cubed_64 AS img
+// [1]: [63:118, 141:196, 31:64]
+SELECT img[63:118, 141:196, 31:64]
+FROM tomo_cubed_64 AS img
+// [1]: [89:144, 58:113, 39:72]
+SELECT img[89:144, 58:113, 39:72]
+FROM tomo_cubed_64 AS img
+// [1]: [72:127, 124:179, 93:126]
+SELECT img[72:127, 124:179, 93:126]
+FROM tomo_cubed_64 AS img
+// [1]: [46:101, 178:233, 41:74]
+SELECT img[46:101, 178:233, 41:74]
+FROM tomo_cubed_64 AS img
+// [1]: [52:107, 10:65, 49:82]
+SELECT img[52:107, 10:65, 49:82]
+FROM tomo_cubed_64 AS img
+// [1]: [151:206, 5:60, 1:34]
+SELECT img[151:206, 5:60, 1:34]
+FROM tomo_cubed_64 AS img
+// [1]: [95:150, 71:126, 85:118]
+SELECT img[95:150, 71:126, 85:118]
+FROM tomo_cubed_64 AS img
+// [2]: [31:100, 166:235, 7:49]
+SELECT img[31:100, 166:235, 7:49]
+FROM tomo_cubed_64 AS img
+// [2]: [109:178, 174:243, 31:73]
+SELECT img[109:178, 174:243, 31:73]
+FROM tomo_cubed_64 AS img
+// [2]: [24:93, 32:101, 91:133]
+SELECT img[24:93, 32:101, 91:133]
+FROM tomo_cubed_64 AS img
+// [2]: [76:145, 52:121, 33:75]
+SELECT img[76:145, 52:121, 33:75]
+FROM tomo_cubed_64 AS img
+// [2]: [82:151, 5:74, 17:59]
+SELECT img[82:151, 5:74, 17:59]
+FROM tomo_cubed_64 AS img
+// [2]: [48:117, 100:169, 72:114]
+SELECT img[48:117, 100:169, 72:114]
+FROM tomo_cubed_64 AS img
+// [2]: [81:150, 183:252, 39:81]
+SELECT img[81:150, 183:252, 39:81]
+FROM tomo_cubed_64 AS img
+// [2]: [8:77, 122:191, 5:47]
+SELECT img[8:77, 122:191, 5:47]
+FROM tomo_cubed_64 AS img
+// [2]: [170:239, 145:214, 23:65]
+SELECT img[170:239, 145:214, 23:65]
+FROM tomo_cubed_64 AS img
+// [2]: [84:153, 101:170, 86:128]
+SELECT img[84:153, 101:170, 86:128]
+FROM tomo_cubed_64 AS img
+// [2]: [72:141, 147:216, 32:74]
+SELECT img[72:141, 147:216, 32:74]
+FROM tomo_cubed_64 AS img
+// [2]: [12:81, 25:94, 108:150]
+SELECT img[12:81, 25:94, 108:150]
+FROM tomo_cubed_64 AS img
+// [2]: [94:163, 125:194, 29:71]
+SELECT img[94:163, 125:194, 29:71]
+FROM tomo_cubed_64 AS img
+// [2]: [4:73, 44:113, 0:42]
+SELECT img[4:73, 44:113, 0:42]
+FROM tomo_cubed_64 AS img
+// [2]: [134:203, 7:76, 85:127]
+SELECT img[134:203, 7:76, 85:127]
+FROM tomo_cubed_64 AS img
+// [2]: [84:153, 168:237, 3:45]
+SELECT img[84:153, 168:237, 3:45]
+FROM tomo_cubed_64 AS img
+// [2]: [166:235, 140:209, 41:83]
+SELECT img[166:235, 140:209, 41:83]
+FROM tomo_cubed_64 AS img
+// [2]: [98:167, 43:112, 81:123]
+SELECT img[98:167, 43:112, 81:123]
+FROM tomo_cubed_64 AS img
+// [2]: [5:74, 137:206, 29:71]
+SELECT img[5:74, 137:206, 29:71]
+FROM tomo_cubed_64 AS img
+// [2]: [177:246, 45:114, 28:70]
+SELECT img[177:246, 45:114, 28:70]
+FROM tomo_cubed_64 AS img
+// [5]: [52:146, 5:99, 72:128]
+SELECT img[52:146, 5:99, 72:128]
+FROM tomo_cubed_64 AS img
+// [5]: [147:241, 45:139, 90:146]
+SELECT img[147:241, 45:139, 90:146]
+FROM tomo_cubed_64 AS img
+// [5]: [156:250, 145:239, 7:63]
+SELECT img[156:250, 145:239, 7:63]
+FROM tomo_cubed_64 AS img
+// [5]: [30:124, 108:202, 74:130]
+SELECT img[30:124, 108:202, 74:130]
+FROM tomo_cubed_64 AS img
+// [5]: [140:234, 44:138, 25:81]
+SELECT img[140:234, 44:138, 25:81]
+FROM tomo_cubed_64 AS img
+// [5]: [48:142, 9:103, 8:64]
+SELECT img[48:142, 9:103, 8:64]
+FROM tomo_cubed_64 AS img
+// [5]: [0:94, 157:251, 73:129]
+SELECT img[0:94, 157:251, 73:129]
+FROM tomo_cubed_64 AS img
+// [5]: [125:219, 53:147, 7:63]
+SELECT img[125:219, 53:147, 7:63]
+FROM tomo_cubed_64 AS img
+// [5]: [26:120, 133:227, 38:94]
+SELECT img[26:120, 133:227, 38:94]
+FROM tomo_cubed_64 AS img
+// [5]: [157:251, 41:135, 74:130]
+SELECT img[157:251, 41:135, 74:130]
+FROM tomo_cubed_64 AS img
+// [5]: [41:135, 120:214, 31:87]
+SELECT img[41:135, 120:214, 31:87]
+FROM tomo_cubed_64 AS img
+// [5]: [33:127, 116:210, 71:127]
+SELECT img[33:127, 116:210, 71:127]
+FROM tomo_cubed_64 AS img
+// [5]: [138:232, 127:221, 20:76]
+SELECT img[138:232, 127:221, 20:76]
+FROM tomo_cubed_64 AS img
+// [5]: [13:107, 9:103, 60:116]
+SELECT img[13:107, 9:103, 60:116]
+FROM tomo_cubed_64 AS img
+// [5]: [124:218, 139:233, 74:130]
+SELECT img[124:218, 139:233, 74:130]
+FROM tomo_cubed_64 AS img
+// [5]: [117:211, 86:180, 91:147]
+SELECT img[117:211, 86:180, 91:147]
+FROM tomo_cubed_64 AS img
+// [5]: [143:237, 52:146, 71:127]
+SELECT img[143:237, 52:146, 71:127]
+FROM tomo_cubed_64 AS img
+// [5]: [10:104, 35:129, 19:75]
+SELECT img[10:104, 35:129, 19:75]
+FROM tomo_cubed_64 AS img
+// [5]: [110:204, 64:158, 64:120]
+SELECT img[110:204, 64:158, 64:120]
+FROM tomo_cubed_64 AS img
+// [5]: [12:106, 103:197, 96:152]
+SELECT img[12:106, 103:197, 96:152]
+FROM tomo_cubed_64 AS img
+// [10]: [108:226, 53:171, 9:80]
+SELECT img[108:226, 53:171, 9:80]
+FROM tomo_cubed_64 AS img
+// [10]: [46:164, 103:221, 10:81]
+SELECT img[46:164, 103:221, 10:81]
+FROM tomo_cubed_64 AS img
+// [10]: [80:198, 73:191, 38:109]
+SELECT img[80:198, 73:191, 38:109]
+FROM tomo_cubed_64 AS img
+// [10]: [38:156, 132:250, 26:97]
+SELECT img[38:156, 132:250, 26:97]
+FROM tomo_cubed_64 AS img
+// [10]: [11:129, 86:204, 77:148]
+SELECT img[11:129, 86:204, 77:148]
+FROM tomo_cubed_64 AS img
+// [10]: [46:164, 90:208, 17:88]
+SELECT img[46:164, 90:208, 17:88]
+FROM tomo_cubed_64 AS img
+// [10]: [86:204, 125:243, 6:77]
+SELECT img[86:204, 125:243, 6:77]
+FROM tomo_cubed_64 AS img
+// [10]: [54:172, 49:167, 69:140]
+SELECT img[54:172, 49:167, 69:140]
+FROM tomo_cubed_64 AS img
+// [10]: [11:129, 111:229, 23:94]
+SELECT img[11:129, 111:229, 23:94]
+FROM tomo_cubed_64 AS img
+// [10]: [46:164, 66:184, 2:73]
+SELECT img[46:164, 66:184, 2:73]
+FROM tomo_cubed_64 AS img
+// [10]: [88:206, 88:206, 39:110]
+SELECT img[88:206, 88:206, 39:110]
+FROM tomo_cubed_64 AS img
+// [10]: [46:164, 22:140, 43:114]
+SELECT img[46:164, 22:140, 43:114]
+FROM tomo_cubed_64 AS img
+// [10]: [4:122, 59:177, 47:118]
+SELECT img[4:122, 59:177, 47:118]
+FROM tomo_cubed_64 AS img
+// [10]: [22:140, 37:155, 31:102]
+SELECT img[22:140, 37:155, 31:102]
+FROM tomo_cubed_64 AS img
+// [10]: [109:227, 71:189, 81:152]
+SELECT img[109:227, 71:189, 81:152]
+FROM tomo_cubed_64 AS img
+// [10]: [96:214, 76:194, 67:138]
+SELECT img[96:214, 76:194, 67:138]
+FROM tomo_cubed_64 AS img
+// [10]: [4:122, 126:244, 10:81]
+SELECT img[4:122, 126:244, 10:81]
+FROM tomo_cubed_64 AS img
+// [10]: [38:156, 90:208, 31:102]
+SELECT img[38:156, 90:208, 31:102]
+FROM tomo_cubed_64 AS img
+// [10]: [12:130, 67:185, 70:141]
+SELECT img[12:130, 67:185, 70:141]
+FROM tomo_cubed_64 AS img
+// [10]: [108:226, 59:177, 70:141]
+SELECT img[108:226, 59:177, 70:141]
+FROM tomo_cubed_64 AS img
+// [20]: [60:209, 12:161, 15:104]
+SELECT img[60:209, 12:161, 15:104]
+FROM tomo_cubed_64 AS img
+// [20]: [36:185, 68:217, 31:120]
+SELECT img[36:185, 68:217, 31:120]
+FROM tomo_cubed_64 AS img
+// [20]: [19:168, 96:245, 50:139]
+SELECT img[19:168, 96:245, 50:139]
+FROM tomo_cubed_64 AS img
+// [20]: [68:217, 96:245, 4:93]
+SELECT img[68:217, 96:245, 4:93]
+FROM tomo_cubed_64 AS img
+// [20]: [16:165, 44:193, 49:138]
+SELECT img[16:165, 44:193, 49:138]
+FROM tomo_cubed_64 AS img
+// [20]: [71:220, 91:240, 11:100]
+SELECT img[71:220, 91:240, 11:100]
+FROM tomo_cubed_64 AS img
+// [20]: [96:245, 58:207, 4:93]
+SELECT img[96:245, 58:207, 4:93]
+FROM tomo_cubed_64 AS img
+// [20]: [40:189, 6:155, 11:100]
+SELECT img[40:189, 6:155, 11:100]
+FROM tomo_cubed_64 AS img
+// [20]: [91:240, 22:171, 7:96]
+SELECT img[91:240, 22:171, 7:96]
+FROM tomo_cubed_64 AS img
+// [20]: [79:228, 85:234, 39:128]
+SELECT img[79:228, 85:234, 39:128]
+FROM tomo_cubed_64 AS img
+// [20]: [97:246, 104:253, 6:95]
+SELECT img[97:246, 104:253, 6:95]
+FROM tomo_cubed_64 AS img
+// [20]: [62:211, 26:175, 7:96]
+SELECT img[62:211, 26:175, 7:96]
+FROM tomo_cubed_64 AS img
+// [20]: [35:184, 5:154, 29:118]
+SELECT img[35:184, 5:154, 29:118]
+FROM tomo_cubed_64 AS img
+// [20]: [20:169, 92:241, 5:94]
+SELECT img[20:169, 92:241, 5:94]
+FROM tomo_cubed_64 AS img
+// [20]: [77:226, 33:182, 45:134]
+SELECT img[77:226, 33:182, 45:134]
+FROM tomo_cubed_64 AS img
+// [20]: [6:155, 40:189, 55:144]
+SELECT img[6:155, 40:189, 55:144]
+FROM tomo_cubed_64 AS img
+// [20]: [102:251, 25:174, 20:109]
+SELECT img[102:251, 25:174, 20:109]
+FROM tomo_cubed_64 AS img
+// [20]: [35:184, 70:219, 31:120]
+SELECT img[35:184, 70:219, 31:120]
+FROM tomo_cubed_64 AS img
+// [20]: [99:248, 88:237, 10:99]
+SELECT img[99:248, 88:237, 10:99]
+FROM tomo_cubed_64 AS img
+// [20]: [67:216, 63:212, 60:149]
+SELECT img[67:216, 63:212, 60:149]
+FROM tomo_cubed_64 AS img
+// [50]: [46:248, 7:209, 31:152]
+SELECT img[46:248, 7:209, 31:152]
+FROM tomo_cubed_64 AS img
+// [50]: [45:247, 24:226, 17:138]
+SELECT img[45:247, 24:226, 17:138]
+FROM tomo_cubed_64 AS img
+// [50]: [22:224, 30:232, 9:130]
+SELECT img[22:224, 30:232, 9:130]
+FROM tomo_cubed_64 AS img
+// [50]: [29:231, 39:241, 4:125]
+SELECT img[29:231, 39:241, 4:125]
+FROM tomo_cubed_64 AS img
+// [50]: [19:221, 51:253, 6:127]
+SELECT img[19:221, 51:253, 6:127]
+FROM tomo_cubed_64 AS img
+// [50]: [27:229, 14:216, 10:131]
+SELECT img[27:229, 14:216, 10:131]
+FROM tomo_cubed_64 AS img
+// [50]: [33:235, 15:217, 26:147]
+SELECT img[33:235, 15:217, 26:147]
+FROM tomo_cubed_64 AS img
+// [50]: [48:250, 1:203, 18:139]
+SELECT img[48:250, 1:203, 18:139]
+FROM tomo_cubed_64 AS img
+// [50]: [24:226, 23:225, 23:144]
+SELECT img[24:226, 23:225, 23:144]
+FROM tomo_cubed_64 AS img
+// [50]: [31:233, 12:214, 8:129]
+SELECT img[31:233, 12:214, 8:129]
+FROM tomo_cubed_64 AS img
+// [50]: [34:236, 1:203, 24:145]
+SELECT img[34:236, 1:203, 24:145]
+FROM tomo_cubed_64 AS img
+// [50]: [27:229, 17:219, 22:143]
+SELECT img[27:229, 17:219, 22:143]
+FROM tomo_cubed_64 AS img
+// [50]: [15:217, 50:252, 16:137]
+SELECT img[15:217, 50:252, 16:137]
+FROM tomo_cubed_64 AS img
+// [50]: [49:251, 3:205, 29:150]
+SELECT img[49:251, 3:205, 29:150]
+FROM tomo_cubed_64 AS img
+// [50]: [11:213, 33:235, 17:138]
+SELECT img[11:213, 33:235, 17:138]
+FROM tomo_cubed_64 AS img
+// [50]: [15:217, 23:225, 29:150]
+SELECT img[15:217, 23:225, 29:150]
+FROM tomo_cubed_64 AS img
+// [50]: [46:248, 28:230, 30:151]
+SELECT img[46:248, 28:230, 30:151]
+FROM tomo_cubed_64 AS img
+// [50]: [11:213, 6:208, 1:122]
+SELECT img[11:213, 6:208, 1:122]
+FROM tomo_cubed_64 AS img
+// [50]: [13:215, 16:218, 24:145]
+SELECT img[13:215, 16:218, 24:145]
+FROM tomo_cubed_64 AS img
+// [50]: [44:246, 46:248, 28:149]
+SELECT img[44:246, 46:248, 28:149]
+FROM tomo_cubed_64 AS img
diff --git a/rasodmg/test/tomo_ops.ql b/rasodmg/test/tomo_ops.ql
new file mode 100644
index 0000000..fce9bf5
--- /dev/null
+++ b/rasodmg/test/tomo_ops.ql
@@ -0,0 +1,27 @@
+// This test evaluates performance of binary operations on parts
+// of tomo. Selectivity fixed at 10%
+
+// cubed, no operation
+
+select img[0:117,0:117,0:69]
+from tomo_cubed as img
+
+// cubed, one MDD operation
+
+select img[0:117,0:117,0:69] + img[0:117,0:117,0:69]
+from tomo_cubed as img
+
+// cubed, two MDD operations
+
+select img[0:117,0:117,0:69] + img[0:117,0:117,0:69] + img[0:117,0:117,0:69]
+from tomo_cubed as img
+
+// cubed, three MDD operations
+
+select img[0:117,0:117,0:69] + img[0:117,0:117,0:69] + img[0:117,0:117,0:69] + img[0:117,0:117,0:69]
+from tomo_cubed as img
+
+// cubed, four MDD operations
+
+select img[0:117,0:117,0:69] + img[0:117,0:117,0:69] + img[0:117,0:117,0:69] + img[0:117,0:117,0:69] + img[0:117,0:117,0:69]
+from tomo_cubed as img
diff --git a/rasodmg/test/tomo_select.ql b/rasodmg/test/tomo_select.ql
new file mode 100644
index 0000000..7584f12
--- /dev/null
+++ b/rasodmg/test/tomo_select.ql
@@ -0,0 +1,72 @@
+// This test evaluates different selectivities in tomo stored both
+// in slices and cubes.
+
+// sliced, selectivity 0,5%
+
+select img[0:43,0:43,0:25]
+from tomo_sliced as img
+
+// sliced, selectivity 1%
+
+select img[0:55,0:55,0:32]
+from tomo_sliced as img
+
+// sliced, selectivity 2%
+
+select img[0:68,0:68,0:41]
+from tomo_sliced as img
+
+// sliced, selectivity 5%
+
+select img[0:91,0:91,0:54]
+from tomo_sliced as img
+
+// sliced, selectivity 10%
+
+select img[0:117,0:117,0:69]
+from tomo_sliced as img
+
+// sliced, selectivity 50%
+
+select img[0:201,0:201,0:121]
+from tomo_sliced as img
+
+// sliced, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from tomo_sliced as img
+
+// cubed, selectivity 0,5%
+
+select img[0:43,0:43,0:25]
+from tomo_cubed as img
+
+// cubed, selectivity 1%
+
+select img[0:55,0:55,0:32]
+from tomo_cubed as img
+
+// cubed, selectivity 2%
+
+select img[0:68,0:68,0:41]
+from tomo_cubed as img
+
+// cubed, selectivity 5%
+
+select img[0:91,0:91,0:54]
+from tomo_cubed as img
+
+// cubed, selectivity 10%
+
+select img[0:117,0:117,0:69]
+from tomo_cubed as img
+
+// cubed, selectivity 50%
+
+select img[0:201,0:201,0:121]
+from tomo_cubed as img
+
+// cubed, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from tomo_cubed as img
diff --git a/rasodmg/test/troll_16.ql b/rasodmg/test/troll_16.ql
new file mode 100644
index 0000000..e15110e
--- /dev/null
+++ b/rasodmg/test/troll_16.ql
@@ -0,0 +1,180 @@
+// ["x"] tomo_cubed_16 [232:238,*:*,*:*]
+SELECT img[232,*:*,*:*]+img[233,*:*,*:*]+img[234,*:*,*:*]+img[235,*:*,*:*]+img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [179:185,*:*,*:*]
+SELECT img[179,*:*,*:*]+img[180,*:*,*:*]+img[181,*:*,*:*]+img[182,*:*,*:*]+img[183,*:*,*:*]+img[184,*:*,*:*]+img[185,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [24:30,*:*,*:*]
+SELECT img[24,*:*,*:*]+img[25,*:*,*:*]+img[26,*:*,*:*]+img[27,*:*,*:*]+img[28,*:*,*:*]+img[29,*:*,*:*]+img[30,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [188:194,*:*,*:*]
+SELECT img[188,*:*,*:*]+img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]+img[192,*:*,*:*]+img[193,*:*,*:*]+img[194,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [238:244,*:*,*:*]
+SELECT img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [76:82,*:*,*:*]
+SELECT img[76,*:*,*:*]+img[77,*:*,*:*]+img[78,*:*,*:*]+img[79,*:*,*:*]+img[80,*:*,*:*]+img[81,*:*,*:*]+img[82,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [239:245,*:*,*:*]
+SELECT img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]+img[245,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [119:125,*:*,*:*]
+SELECT img[119,*:*,*:*]+img[120,*:*,*:*]+img[121,*:*,*:*]+img[122,*:*,*:*]+img[123,*:*,*:*]+img[124,*:*,*:*]+img[125,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [176:182,*:*,*:*]
+SELECT img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]+img[180,*:*,*:*]+img[181,*:*,*:*]+img[182,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [51:57,*:*,*:*]
+SELECT img[51,*:*,*:*]+img[52,*:*,*:*]+img[53,*:*,*:*]+img[54,*:*,*:*]+img[55,*:*,*:*]+img[56,*:*,*:*]+img[57,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [8:14,*:*,*:*]
+SELECT img[8,*:*,*:*]+img[9,*:*,*:*]+img[10,*:*,*:*]+img[11,*:*,*:*]+img[12,*:*,*:*]+img[13,*:*,*:*]+img[14,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [173:179,*:*,*:*]
+SELECT img[173,*:*,*:*]+img[174,*:*,*:*]+img[175,*:*,*:*]+img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [237:243,*:*,*:*]
+SELECT img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [84:90,*:*,*:*]
+SELECT img[84,*:*,*:*]+img[85,*:*,*:*]+img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]+img[90,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [14:20,*:*,*:*]
+SELECT img[14,*:*,*:*]+img[15,*:*,*:*]+img[16,*:*,*:*]+img[17,*:*,*:*]+img[18,*:*,*:*]+img[19,*:*,*:*]+img[20,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [144:150,*:*,*:*]
+SELECT img[144,*:*,*:*]+img[145,*:*,*:*]+img[146,*:*,*:*]+img[147,*:*,*:*]+img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [215:221,*:*,*:*]
+SELECT img[215,*:*,*:*]+img[216,*:*,*:*]+img[217,*:*,*:*]+img[218,*:*,*:*]+img[219,*:*,*:*]+img[220,*:*,*:*]+img[221,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [86:92,*:*,*:*]
+SELECT img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]+img[90,*:*,*:*]+img[91,*:*,*:*]+img[92,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [136:142,*:*,*:*]
+SELECT img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]+img[141,*:*,*:*]+img[142,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["x"] tomo_cubed_16 [135:141,*:*,*:*]
+SELECT img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]+img[141,*:*,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 146:152, *:*]
+SELECT img[*:*,146,*:*]+img[*:*,147,*:*]+img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 15:21, *:*]
+SELECT img[*:*,15,*:*]+img[*:*,16,*:*]+img[*:*,17,*:*]+img[*:*,18,*:*]+img[*:*,19,*:*]+img[*:*,20,*:*]+img[*:*,21,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 148:154, *:*]
+SELECT img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]+img[*:*,153,*:*]+img[*:*,154,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 82:88, *:*]
+SELECT img[*:*,82,*:*]+img[*:*,83,*:*]+img[*:*,84,*:*]+img[*:*,85,*:*]+img[*:*,86,*:*]+img[*:*,87,*:*]+img[*:*,88,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 149:155, *:*]
+SELECT img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]+img[*:*,153,*:*]+img[*:*,154,*:*]+img[*:*,155,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 154:160, *:*]
+SELECT img[*:*,154,*:*]+img[*:*,155,*:*]+img[*:*,156,*:*]+img[*:*,157,*:*]+img[*:*,158,*:*]+img[*:*,159,*:*]+img[*:*,160,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 46:52, *:*]
+SELECT img[*:*,46,*:*]+img[*:*,47,*:*]+img[*:*,48,*:*]+img[*:*,49,*:*]+img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 3:9, *:*]
+SELECT img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 20:26, *:*]
+SELECT img[*:*,20,*:*]+img[*:*,21,*:*]+img[*:*,22,*:*]+img[*:*,23,*:*]+img[*:*,24,*:*]+img[*:*,25,*:*]+img[*:*,26,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 17:23, *:*]
+SELECT img[*:*,17,*:*]+img[*:*,18,*:*]+img[*:*,19,*:*]+img[*:*,20,*:*]+img[*:*,21,*:*]+img[*:*,22,*:*]+img[*:*,23,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 236:242, *:*]
+SELECT img[*:*,236,*:*]+img[*:*,237,*:*]+img[*:*,238,*:*]+img[*:*,239,*:*]+img[*:*,240,*:*]+img[*:*,241,*:*]+img[*:*,242,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 98:104, *:*]
+SELECT img[*:*,98,*:*]+img[*:*,99,*:*]+img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]+img[*:*,103,*:*]+img[*:*,104,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 4:10, *:*]
+SELECT img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 199:205, *:*]
+SELECT img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 197:203, *:*]
+SELECT img[*:*,197,*:*]+img[*:*,198,*:*]+img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 19:25, *:*]
+SELECT img[*:*,19,*:*]+img[*:*,20,*:*]+img[*:*,21,*:*]+img[*:*,22,*:*]+img[*:*,23,*:*]+img[*:*,24,*:*]+img[*:*,25,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 64:70, *:*]
+SELECT img[*:*,64,*:*]+img[*:*,65,*:*]+img[*:*,66,*:*]+img[*:*,67,*:*]+img[*:*,68,*:*]+img[*:*,69,*:*]+img[*:*,70,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 169:175, *:*]
+SELECT img[*:*,169,*:*]+img[*:*,170,*:*]+img[*:*,171,*:*]+img[*:*,172,*:*]+img[*:*,173,*:*]+img[*:*,174,*:*]+img[*:*,175,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 109:115, *:*]
+SELECT img[*:*,109,*:*]+img[*:*,110,*:*]+img[*:*,111,*:*]+img[*:*,112,*:*]+img[*:*,113,*:*]+img[*:*,114,*:*]+img[*:*,115,*:*]
+FROM tomo_cubed_16 as img
+// ["y"] tomo_cubed_16 [*:*, 148:154, *:*]
+SELECT img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]+img[*:*,153,*:*]+img[*:*,154,*:*]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 35:41]
+SELECT img[*:*,*:*,35]+img[*:*,*:*,36]+img[*:*,*:*,37]+img[*:*,*:*,38]+img[*:*,*:*,39]+img[*:*,*:*,40]+img[*:*,*:*,41]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 24:30]
+SELECT img[*:*,*:*,24]+img[*:*,*:*,25]+img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]+img[*:*,*:*,29]+img[*:*,*:*,30]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 38:44]
+SELECT img[*:*,*:*,38]+img[*:*,*:*,39]+img[*:*,*:*,40]+img[*:*,*:*,41]+img[*:*,*:*,42]+img[*:*,*:*,43]+img[*:*,*:*,44]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 129:135]
+SELECT img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 88:94]
+SELECT img[*:*,*:*,88]+img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]+img[*:*,*:*,94]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 49:55]
+SELECT img[*:*,*:*,49]+img[*:*,*:*,50]+img[*:*,*:*,51]+img[*:*,*:*,52]+img[*:*,*:*,53]+img[*:*,*:*,54]+img[*:*,*:*,55]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 70:76]
+SELECT img[*:*,*:*,70]+img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 76:82]
+SELECT img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]+img[*:*,*:*,82]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 60:66]
+SELECT img[*:*,*:*,60]+img[*:*,*:*,61]+img[*:*,*:*,62]+img[*:*,*:*,63]+img[*:*,*:*,64]+img[*:*,*:*,65]+img[*:*,*:*,66]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 9:15]
+SELECT img[*:*,*:*,9]+img[*:*,*:*,10]+img[*:*,*:*,11]+img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 14:20]
+SELECT img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]+img[*:*,*:*,19]+img[*:*,*:*,20]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 2:8]
+SELECT img[*:*,*:*,2]+img[*:*,*:*,3]+img[*:*,*:*,4]+img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 29:35]
+SELECT img[*:*,*:*,29]+img[*:*,*:*,30]+img[*:*,*:*,31]+img[*:*,*:*,32]+img[*:*,*:*,33]+img[*:*,*:*,34]+img[*:*,*:*,35]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 48:54]
+SELECT img[*:*,*:*,48]+img[*:*,*:*,49]+img[*:*,*:*,50]+img[*:*,*:*,51]+img[*:*,*:*,52]+img[*:*,*:*,53]+img[*:*,*:*,54]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 89:95]
+SELECT img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]+img[*:*,*:*,94]+img[*:*,*:*,95]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 75:81]
+SELECT img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 83:89]
+SELECT img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]+img[*:*,*:*,86]+img[*:*,*:*,87]+img[*:*,*:*,88]+img[*:*,*:*,89]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 125:131]
+SELECT img[*:*,*:*,125]+img[*:*,*:*,126]+img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 132:138]
+SELECT img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]
+FROM tomo_cubed_16 as img
+// ["z"] tomo_cubed_16 [*:*, *:*, 32:38]
+SELECT img[*:*,*:*,32]+img[*:*,*:*,33]+img[*:*,*:*,34]+img[*:*,*:*,35]+img[*:*,*:*,36]+img[*:*,*:*,37]+img[*:*,*:*,38]
+FROM tomo_cubed_16 as img
diff --git a/rasodmg/test/troll_32.ql b/rasodmg/test/troll_32.ql
new file mode 100644
index 0000000..cb407ee
--- /dev/null
+++ b/rasodmg/test/troll_32.ql
@@ -0,0 +1,180 @@
+// ["x"] tomo_cubed [133:139,*:*,*:*]
+SELECT img[133,*:*,*:*]+img[134,*:*,*:*]+img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [248:254,*:*,*:*]
+SELECT img[248,*:*,*:*]+img[249,*:*,*:*]+img[250,*:*,*:*]+img[251,*:*,*:*]+img[252,*:*,*:*]+img[253,*:*,*:*]+img[254,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [94:100,*:*,*:*]
+SELECT img[94,*:*,*:*]+img[95,*:*,*:*]+img[96,*:*,*:*]+img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]+img[100,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [3:9,*:*,*:*]
+SELECT img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]+img[9,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [93:99,*:*,*:*]
+SELECT img[93,*:*,*:*]+img[94,*:*,*:*]+img[95,*:*,*:*]+img[96,*:*,*:*]+img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [62:68,*:*,*:*]
+SELECT img[62,*:*,*:*]+img[63,*:*,*:*]+img[64,*:*,*:*]+img[65,*:*,*:*]+img[66,*:*,*:*]+img[67,*:*,*:*]+img[68,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [174:180,*:*,*:*]
+SELECT img[174,*:*,*:*]+img[175,*:*,*:*]+img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]+img[180,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [97:103,*:*,*:*]
+SELECT img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]+img[100,*:*,*:*]+img[101,*:*,*:*]+img[102,*:*,*:*]+img[103,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [43:49,*:*,*:*]
+SELECT img[43,*:*,*:*]+img[44,*:*,*:*]+img[45,*:*,*:*]+img[46,*:*,*:*]+img[47,*:*,*:*]+img[48,*:*,*:*]+img[49,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [41:47,*:*,*:*]
+SELECT img[41,*:*,*:*]+img[42,*:*,*:*]+img[43,*:*,*:*]+img[44,*:*,*:*]+img[45,*:*,*:*]+img[46,*:*,*:*]+img[47,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [38:44,*:*,*:*]
+SELECT img[38,*:*,*:*]+img[39,*:*,*:*]+img[40,*:*,*:*]+img[41,*:*,*:*]+img[42,*:*,*:*]+img[43,*:*,*:*]+img[44,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [75:81,*:*,*:*]
+SELECT img[75,*:*,*:*]+img[76,*:*,*:*]+img[77,*:*,*:*]+img[78,*:*,*:*]+img[79,*:*,*:*]+img[80,*:*,*:*]+img[81,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [189:195,*:*,*:*]
+SELECT img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]+img[192,*:*,*:*]+img[193,*:*,*:*]+img[194,*:*,*:*]+img[195,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [3:9,*:*,*:*]
+SELECT img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]+img[9,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [38:44,*:*,*:*]
+SELECT img[38,*:*,*:*]+img[39,*:*,*:*]+img[40,*:*,*:*]+img[41,*:*,*:*]+img[42,*:*,*:*]+img[43,*:*,*:*]+img[44,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [5:11,*:*,*:*]
+SELECT img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]+img[9,*:*,*:*]+img[10,*:*,*:*]+img[11,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [83:89,*:*,*:*]
+SELECT img[83,*:*,*:*]+img[84,*:*,*:*]+img[85,*:*,*:*]+img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [23:29,*:*,*:*]
+SELECT img[23,*:*,*:*]+img[24,*:*,*:*]+img[25,*:*,*:*]+img[26,*:*,*:*]+img[27,*:*,*:*]+img[28,*:*,*:*]+img[29,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [185:191,*:*,*:*]
+SELECT img[185,*:*,*:*]+img[186,*:*,*:*]+img[187,*:*,*:*]+img[188,*:*,*:*]+img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]
+FROM tomo_cubed as img
+// ["x"] tomo_cubed [148:154,*:*,*:*]
+SELECT img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]+img[151,*:*,*:*]+img[152,*:*,*:*]+img[153,*:*,*:*]+img[154,*:*,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 100:106, *:*]
+SELECT img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]+img[*:*,103,*:*]+img[*:*,104,*:*]+img[*:*,105,*:*]+img[*:*,106,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 2:8, *:*]
+SELECT img[*:*,2,*:*]+img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 166:172, *:*]
+SELECT img[*:*,166,*:*]+img[*:*,167,*:*]+img[*:*,168,*:*]+img[*:*,169,*:*]+img[*:*,170,*:*]+img[*:*,171,*:*]+img[*:*,172,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 246:252, *:*]
+SELECT img[*:*,246,*:*]+img[*:*,247,*:*]+img[*:*,248,*:*]+img[*:*,249,*:*]+img[*:*,250,*:*]+img[*:*,251,*:*]+img[*:*,252,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 78:84, *:*]
+SELECT img[*:*,78,*:*]+img[*:*,79,*:*]+img[*:*,80,*:*]+img[*:*,81,*:*]+img[*:*,82,*:*]+img[*:*,83,*:*]+img[*:*,84,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 174:180, *:*]
+SELECT img[*:*,174,*:*]+img[*:*,175,*:*]+img[*:*,176,*:*]+img[*:*,177,*:*]+img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 233:239, *:*]
+SELECT img[*:*,233,*:*]+img[*:*,234,*:*]+img[*:*,235,*:*]+img[*:*,236,*:*]+img[*:*,237,*:*]+img[*:*,238,*:*]+img[*:*,239,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 131:137, *:*]
+SELECT img[*:*,131,*:*]+img[*:*,132,*:*]+img[*:*,133,*:*]+img[*:*,134,*:*]+img[*:*,135,*:*]+img[*:*,136,*:*]+img[*:*,137,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 25:31, *:*]
+SELECT img[*:*,25,*:*]+img[*:*,26,*:*]+img[*:*,27,*:*]+img[*:*,28,*:*]+img[*:*,29,*:*]+img[*:*,30,*:*]+img[*:*,31,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 170:176, *:*]
+SELECT img[*:*,170,*:*]+img[*:*,171,*:*]+img[*:*,172,*:*]+img[*:*,173,*:*]+img[*:*,174,*:*]+img[*:*,175,*:*]+img[*:*,176,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 85:91, *:*]
+SELECT img[*:*,85,*:*]+img[*:*,86,*:*]+img[*:*,87,*:*]+img[*:*,88,*:*]+img[*:*,89,*:*]+img[*:*,90,*:*]+img[*:*,91,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 178:184, *:*]
+SELECT img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]+img[*:*,181,*:*]+img[*:*,182,*:*]+img[*:*,183,*:*]+img[*:*,184,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 198:204, *:*]
+SELECT img[*:*,198,*:*]+img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 54:60, *:*]
+SELECT img[*:*,54,*:*]+img[*:*,55,*:*]+img[*:*,56,*:*]+img[*:*,57,*:*]+img[*:*,58,*:*]+img[*:*,59,*:*]+img[*:*,60,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 227:233, *:*]
+SELECT img[*:*,227,*:*]+img[*:*,228,*:*]+img[*:*,229,*:*]+img[*:*,230,*:*]+img[*:*,231,*:*]+img[*:*,232,*:*]+img[*:*,233,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 4:10, *:*]
+SELECT img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 7:13, *:*]
+SELECT img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]+img[*:*,11,*:*]+img[*:*,12,*:*]+img[*:*,13,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 217:223, *:*]
+SELECT img[*:*,217,*:*]+img[*:*,218,*:*]+img[*:*,219,*:*]+img[*:*,220,*:*]+img[*:*,221,*:*]+img[*:*,222,*:*]+img[*:*,223,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 200:206, *:*]
+SELECT img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]+img[*:*,206,*:*]
+FROM tomo_cubed as img
+// ["y"] tomo_cubed [*:*, 181:187, *:*]
+SELECT img[*:*,181,*:*]+img[*:*,182,*:*]+img[*:*,183,*:*]+img[*:*,184,*:*]+img[*:*,185,*:*]+img[*:*,186,*:*]+img[*:*,187,*:*]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 4:10]
+SELECT img[*:*,*:*,4]+img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]+img[*:*,*:*,9]+img[*:*,*:*,10]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 29:35]
+SELECT img[*:*,*:*,29]+img[*:*,*:*,30]+img[*:*,*:*,31]+img[*:*,*:*,32]+img[*:*,*:*,33]+img[*:*,*:*,34]+img[*:*,*:*,35]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 74:80]
+SELECT img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 71:77]
+SELECT img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 125:131]
+SELECT img[*:*,*:*,125]+img[*:*,*:*,126]+img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 146:152]
+SELECT img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]+img[*:*,*:*,149]+img[*:*,*:*,150]+img[*:*,*:*,151]+img[*:*,*:*,152]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 138:144]
+SELECT img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]+img[*:*,*:*,141]+img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 81:87]
+SELECT img[*:*,*:*,81]+img[*:*,*:*,82]+img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]+img[*:*,*:*,86]+img[*:*,*:*,87]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 133:139]
+SELECT img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]+img[*:*,*:*,139]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 131:137]
+SELECT img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 52:58]
+SELECT img[*:*,*:*,52]+img[*:*,*:*,53]+img[*:*,*:*,54]+img[*:*,*:*,55]+img[*:*,*:*,56]+img[*:*,*:*,57]+img[*:*,*:*,58]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 67:73]
+SELECT img[*:*,*:*,67]+img[*:*,*:*,68]+img[*:*,*:*,69]+img[*:*,*:*,70]+img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 104:110]
+SELECT img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]+img[*:*,*:*,109]+img[*:*,*:*,110]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 95:101]
+SELECT img[*:*,*:*,95]+img[*:*,*:*,96]+img[*:*,*:*,97]+img[*:*,*:*,98]+img[*:*,*:*,99]+img[*:*,*:*,100]+img[*:*,*:*,101]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 71:77]
+SELECT img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 5:11]
+SELECT img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]+img[*:*,*:*,9]+img[*:*,*:*,10]+img[*:*,*:*,11]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 127:133]
+SELECT img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 4:10]
+SELECT img[*:*,*:*,4]+img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]+img[*:*,*:*,9]+img[*:*,*:*,10]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 141:147]
+SELECT img[*:*,*:*,141]+img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]+img[*:*,*:*,145]+img[*:*,*:*,146]+img[*:*,*:*,147]
+FROM tomo_cubed as img
+// ["z"] tomo_cubed [*:*, *:*, 82:88]
+SELECT img[*:*,*:*,82]+img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]+img[*:*,*:*,86]+img[*:*,*:*,87]+img[*:*,*:*,88]
+FROM tomo_cubed as img
diff --git a/rasodmg/test/troll_64.ql b/rasodmg/test/troll_64.ql
new file mode 100644
index 0000000..c74f21e
--- /dev/null
+++ b/rasodmg/test/troll_64.ql
@@ -0,0 +1,180 @@
+// ["x"] tomo_cubed_64 [32:38,*:*,*:*]
+SELECT img[32,*:*,*:*]+img[33,*:*,*:*]+img[34,*:*,*:*]+img[35,*:*,*:*]+img[36,*:*,*:*]+img[37,*:*,*:*]+img[38,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [134:140,*:*,*:*]
+SELECT img[134,*:*,*:*]+img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [116:122,*:*,*:*]
+SELECT img[116,*:*,*:*]+img[117,*:*,*:*]+img[118,*:*,*:*]+img[119,*:*,*:*]+img[120,*:*,*:*]+img[121,*:*,*:*]+img[122,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [244:250,*:*,*:*]
+SELECT img[244,*:*,*:*]+img[245,*:*,*:*]+img[246,*:*,*:*]+img[247,*:*,*:*]+img[248,*:*,*:*]+img[249,*:*,*:*]+img[250,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [182:188,*:*,*:*]
+SELECT img[182,*:*,*:*]+img[183,*:*,*:*]+img[184,*:*,*:*]+img[185,*:*,*:*]+img[186,*:*,*:*]+img[187,*:*,*:*]+img[188,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [233:239,*:*,*:*]
+SELECT img[233,*:*,*:*]+img[234,*:*,*:*]+img[235,*:*,*:*]+img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [134:140,*:*,*:*]
+SELECT img[134,*:*,*:*]+img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [216:222,*:*,*:*]
+SELECT img[216,*:*,*:*]+img[217,*:*,*:*]+img[218,*:*,*:*]+img[219,*:*,*:*]+img[220,*:*,*:*]+img[221,*:*,*:*]+img[222,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [176:182,*:*,*:*]
+SELECT img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]+img[180,*:*,*:*]+img[181,*:*,*:*]+img[182,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [200:206,*:*,*:*]
+SELECT img[200,*:*,*:*]+img[201,*:*,*:*]+img[202,*:*,*:*]+img[203,*:*,*:*]+img[204,*:*,*:*]+img[205,*:*,*:*]+img[206,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [140:146,*:*,*:*]
+SELECT img[140,*:*,*:*]+img[141,*:*,*:*]+img[142,*:*,*:*]+img[143,*:*,*:*]+img[144,*:*,*:*]+img[145,*:*,*:*]+img[146,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [54:60,*:*,*:*]
+SELECT img[54,*:*,*:*]+img[55,*:*,*:*]+img[56,*:*,*:*]+img[57,*:*,*:*]+img[58,*:*,*:*]+img[59,*:*,*:*]+img[60,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [94:100,*:*,*:*]
+SELECT img[94,*:*,*:*]+img[95,*:*,*:*]+img[96,*:*,*:*]+img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]+img[100,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [14:20,*:*,*:*]
+SELECT img[14,*:*,*:*]+img[15,*:*,*:*]+img[16,*:*,*:*]+img[17,*:*,*:*]+img[18,*:*,*:*]+img[19,*:*,*:*]+img[20,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [211:217,*:*,*:*]
+SELECT img[211,*:*,*:*]+img[212,*:*,*:*]+img[213,*:*,*:*]+img[214,*:*,*:*]+img[215,*:*,*:*]+img[216,*:*,*:*]+img[217,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [156:162,*:*,*:*]
+SELECT img[156,*:*,*:*]+img[157,*:*,*:*]+img[158,*:*,*:*]+img[159,*:*,*:*]+img[160,*:*,*:*]+img[161,*:*,*:*]+img[162,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [196:202,*:*,*:*]
+SELECT img[196,*:*,*:*]+img[197,*:*,*:*]+img[198,*:*,*:*]+img[199,*:*,*:*]+img[200,*:*,*:*]+img[201,*:*,*:*]+img[202,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [181:187,*:*,*:*]
+SELECT img[181,*:*,*:*]+img[182,*:*,*:*]+img[183,*:*,*:*]+img[184,*:*,*:*]+img[185,*:*,*:*]+img[186,*:*,*:*]+img[187,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [80:86,*:*,*:*]
+SELECT img[80,*:*,*:*]+img[81,*:*,*:*]+img[82,*:*,*:*]+img[83,*:*,*:*]+img[84,*:*,*:*]+img[85,*:*,*:*]+img[86,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["x"] tomo_cubed_64 [1:7,*:*,*:*]
+SELECT img[1,*:*,*:*]+img[2,*:*,*:*]+img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 72:78, *:*]
+SELECT img[*:*,72,*:*]+img[*:*,73,*:*]+img[*:*,74,*:*]+img[*:*,75,*:*]+img[*:*,76,*:*]+img[*:*,77,*:*]+img[*:*,78,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 211:217, *:*]
+SELECT img[*:*,211,*:*]+img[*:*,212,*:*]+img[*:*,213,*:*]+img[*:*,214,*:*]+img[*:*,215,*:*]+img[*:*,216,*:*]+img[*:*,217,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 199:205, *:*]
+SELECT img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 92:98, *:*]
+SELECT img[*:*,92,*:*]+img[*:*,93,*:*]+img[*:*,94,*:*]+img[*:*,95,*:*]+img[*:*,96,*:*]+img[*:*,97,*:*]+img[*:*,98,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 233:239, *:*]
+SELECT img[*:*,233,*:*]+img[*:*,234,*:*]+img[*:*,235,*:*]+img[*:*,236,*:*]+img[*:*,237,*:*]+img[*:*,238,*:*]+img[*:*,239,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 201:207, *:*]
+SELECT img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]+img[*:*,206,*:*]+img[*:*,207,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 59:65, *:*]
+SELECT img[*:*,59,*:*]+img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]+img[*:*,63,*:*]+img[*:*,64,*:*]+img[*:*,65,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 208:214, *:*]
+SELECT img[*:*,208,*:*]+img[*:*,209,*:*]+img[*:*,210,*:*]+img[*:*,211,*:*]+img[*:*,212,*:*]+img[*:*,213,*:*]+img[*:*,214,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 1:7, *:*]
+SELECT img[*:*,1,*:*]+img[*:*,2,*:*]+img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 4:10, *:*]
+SELECT img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 5:11, *:*]
+SELECT img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]+img[*:*,11,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 98:104, *:*]
+SELECT img[*:*,98,*:*]+img[*:*,99,*:*]+img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]+img[*:*,103,*:*]+img[*:*,104,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 74:80, *:*]
+SELECT img[*:*,74,*:*]+img[*:*,75,*:*]+img[*:*,76,*:*]+img[*:*,77,*:*]+img[*:*,78,*:*]+img[*:*,79,*:*]+img[*:*,80,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 49:55, *:*]
+SELECT img[*:*,49,*:*]+img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]+img[*:*,53,*:*]+img[*:*,54,*:*]+img[*:*,55,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 177:183, *:*]
+SELECT img[*:*,177,*:*]+img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]+img[*:*,181,*:*]+img[*:*,182,*:*]+img[*:*,183,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 146:152, *:*]
+SELECT img[*:*,146,*:*]+img[*:*,147,*:*]+img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 105:111, *:*]
+SELECT img[*:*,105,*:*]+img[*:*,106,*:*]+img[*:*,107,*:*]+img[*:*,108,*:*]+img[*:*,109,*:*]+img[*:*,110,*:*]+img[*:*,111,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 46:52, *:*]
+SELECT img[*:*,46,*:*]+img[*:*,47,*:*]+img[*:*,48,*:*]+img[*:*,49,*:*]+img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 56:62, *:*]
+SELECT img[*:*,56,*:*]+img[*:*,57,*:*]+img[*:*,58,*:*]+img[*:*,59,*:*]+img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]
+FROM tomo_cubed_64 as img
+// ["y"] tomo_cubed_64 [*:*, 154:160, *:*]
+SELECT img[*:*,154,*:*]+img[*:*,155,*:*]+img[*:*,156,*:*]+img[*:*,157,*:*]+img[*:*,158,*:*]+img[*:*,159,*:*]+img[*:*,160,*:*]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 127:133]
+SELECT img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 79:85]
+SELECT img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]+img[*:*,*:*,82]+img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 134:140]
+SELECT img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 12:18]
+SELECT img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 142:148]
+SELECT img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]+img[*:*,*:*,145]+img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 128:134]
+SELECT img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 75:81]
+SELECT img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 118:124]
+SELECT img[*:*,*:*,118]+img[*:*,*:*,119]+img[*:*,*:*,120]+img[*:*,*:*,121]+img[*:*,*:*,122]+img[*:*,*:*,123]+img[*:*,*:*,124]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 87:93]
+SELECT img[*:*,*:*,87]+img[*:*,*:*,88]+img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 23:29]
+SELECT img[*:*,*:*,23]+img[*:*,*:*,24]+img[*:*,*:*,25]+img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]+img[*:*,*:*,29]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 69:75]
+SELECT img[*:*,*:*,69]+img[*:*,*:*,70]+img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 146:152]
+SELECT img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]+img[*:*,*:*,149]+img[*:*,*:*,150]+img[*:*,*:*,151]+img[*:*,*:*,152]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 99:105]
+SELECT img[*:*,*:*,99]+img[*:*,*:*,100]+img[*:*,*:*,101]+img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 135:141]
+SELECT img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]+img[*:*,*:*,141]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 76:82]
+SELECT img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]+img[*:*,*:*,82]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 26:32]
+SELECT img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]+img[*:*,*:*,29]+img[*:*,*:*,30]+img[*:*,*:*,31]+img[*:*,*:*,32]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 56:62]
+SELECT img[*:*,*:*,56]+img[*:*,*:*,57]+img[*:*,*:*,58]+img[*:*,*:*,59]+img[*:*,*:*,60]+img[*:*,*:*,61]+img[*:*,*:*,62]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 94:100]
+SELECT img[*:*,*:*,94]+img[*:*,*:*,95]+img[*:*,*:*,96]+img[*:*,*:*,97]+img[*:*,*:*,98]+img[*:*,*:*,99]+img[*:*,*:*,100]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 13:19]
+SELECT img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]+img[*:*,*:*,19]
+FROM tomo_cubed_64 as img
+// ["z"] tomo_cubed_64 [*:*, *:*, 22:28]
+SELECT img[*:*,*:*,22]+img[*:*,*:*,23]+img[*:*,*:*,24]+img[*:*,*:*,25]+img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]
+FROM tomo_cubed_64 as img
diff --git a/rasodmg/test/troll_sliced.ql b/rasodmg/test/troll_sliced.ql
new file mode 100644
index 0000000..5b6ae0f
--- /dev/null
+++ b/rasodmg/test/troll_sliced.ql
@@ -0,0 +1,180 @@
+// ["x"] tomo_sliced [2:8,*:*,*:*]
+SELECT img[2,*:*,*:*]+img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [86:92,*:*,*:*]
+SELECT img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]+img[90,*:*,*:*]+img[91,*:*,*:*]+img[92,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [2:8,*:*,*:*]
+SELECT img[2,*:*,*:*]+img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [104:110,*:*,*:*]
+SELECT img[104,*:*,*:*]+img[105,*:*,*:*]+img[106,*:*,*:*]+img[107,*:*,*:*]+img[108,*:*,*:*]+img[109,*:*,*:*]+img[110,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [236:242,*:*,*:*]
+SELECT img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [145:151,*:*,*:*]
+SELECT img[145,*:*,*:*]+img[146,*:*,*:*]+img[147,*:*,*:*]+img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]+img[151,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [242:248,*:*,*:*]
+SELECT img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]+img[245,*:*,*:*]+img[246,*:*,*:*]+img[247,*:*,*:*]+img[248,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [236:242,*:*,*:*]
+SELECT img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [246:252,*:*,*:*]
+SELECT img[246,*:*,*:*]+img[247,*:*,*:*]+img[248,*:*,*:*]+img[249,*:*,*:*]+img[250,*:*,*:*]+img[251,*:*,*:*]+img[252,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [189:195,*:*,*:*]
+SELECT img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]+img[192,*:*,*:*]+img[193,*:*,*:*]+img[194,*:*,*:*]+img[195,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [136:142,*:*,*:*]
+SELECT img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]+img[141,*:*,*:*]+img[142,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [100:106,*:*,*:*]
+SELECT img[100,*:*,*:*]+img[101,*:*,*:*]+img[102,*:*,*:*]+img[103,*:*,*:*]+img[104,*:*,*:*]+img[105,*:*,*:*]+img[106,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [49:55,*:*,*:*]
+SELECT img[49,*:*,*:*]+img[50,*:*,*:*]+img[51,*:*,*:*]+img[52,*:*,*:*]+img[53,*:*,*:*]+img[54,*:*,*:*]+img[55,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [101:107,*:*,*:*]
+SELECT img[101,*:*,*:*]+img[102,*:*,*:*]+img[103,*:*,*:*]+img[104,*:*,*:*]+img[105,*:*,*:*]+img[106,*:*,*:*]+img[107,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [238:244,*:*,*:*]
+SELECT img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [56:62,*:*,*:*]
+SELECT img[56,*:*,*:*]+img[57,*:*,*:*]+img[58,*:*,*:*]+img[59,*:*,*:*]+img[60,*:*,*:*]+img[61,*:*,*:*]+img[62,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [57:63,*:*,*:*]
+SELECT img[57,*:*,*:*]+img[58,*:*,*:*]+img[59,*:*,*:*]+img[60,*:*,*:*]+img[61,*:*,*:*]+img[62,*:*,*:*]+img[63,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [146:152,*:*,*:*]
+SELECT img[146,*:*,*:*]+img[147,*:*,*:*]+img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]+img[151,*:*,*:*]+img[152,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [212:218,*:*,*:*]
+SELECT img[212,*:*,*:*]+img[213,*:*,*:*]+img[214,*:*,*:*]+img[215,*:*,*:*]+img[216,*:*,*:*]+img[217,*:*,*:*]+img[218,*:*,*:*]
+FROM tomo_sliced as img
+// ["x"] tomo_sliced [172:178,*:*,*:*]
+SELECT img[172,*:*,*:*]+img[173,*:*,*:*]+img[174,*:*,*:*]+img[175,*:*,*:*]+img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 57:63, *:*]
+SELECT img[*:*,57,*:*]+img[*:*,58,*:*]+img[*:*,59,*:*]+img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]+img[*:*,63,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 225:231, *:*]
+SELECT img[*:*,225,*:*]+img[*:*,226,*:*]+img[*:*,227,*:*]+img[*:*,228,*:*]+img[*:*,229,*:*]+img[*:*,230,*:*]+img[*:*,231,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 96:102, *:*]
+SELECT img[*:*,96,*:*]+img[*:*,97,*:*]+img[*:*,98,*:*]+img[*:*,99,*:*]+img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 3:9, *:*]
+SELECT img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 60:66, *:*]
+SELECT img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]+img[*:*,63,*:*]+img[*:*,64,*:*]+img[*:*,65,*:*]+img[*:*,66,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 133:139, *:*]
+SELECT img[*:*,133,*:*]+img[*:*,134,*:*]+img[*:*,135,*:*]+img[*:*,136,*:*]+img[*:*,137,*:*]+img[*:*,138,*:*]+img[*:*,139,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 62:68, *:*]
+SELECT img[*:*,62,*:*]+img[*:*,63,*:*]+img[*:*,64,*:*]+img[*:*,65,*:*]+img[*:*,66,*:*]+img[*:*,67,*:*]+img[*:*,68,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 112:118, *:*]
+SELECT img[*:*,112,*:*]+img[*:*,113,*:*]+img[*:*,114,*:*]+img[*:*,115,*:*]+img[*:*,116,*:*]+img[*:*,117,*:*]+img[*:*,118,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 206:212, *:*]
+SELECT img[*:*,206,*:*]+img[*:*,207,*:*]+img[*:*,208,*:*]+img[*:*,209,*:*]+img[*:*,210,*:*]+img[*:*,211,*:*]+img[*:*,212,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 136:142, *:*]
+SELECT img[*:*,136,*:*]+img[*:*,137,*:*]+img[*:*,138,*:*]+img[*:*,139,*:*]+img[*:*,140,*:*]+img[*:*,141,*:*]+img[*:*,142,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 22:28, *:*]
+SELECT img[*:*,22,*:*]+img[*:*,23,*:*]+img[*:*,24,*:*]+img[*:*,25,*:*]+img[*:*,26,*:*]+img[*:*,27,*:*]+img[*:*,28,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 121:127, *:*]
+SELECT img[*:*,121,*:*]+img[*:*,122,*:*]+img[*:*,123,*:*]+img[*:*,124,*:*]+img[*:*,125,*:*]+img[*:*,126,*:*]+img[*:*,127,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 42:48, *:*]
+SELECT img[*:*,42,*:*]+img[*:*,43,*:*]+img[*:*,44,*:*]+img[*:*,45,*:*]+img[*:*,46,*:*]+img[*:*,47,*:*]+img[*:*,48,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 110:116, *:*]
+SELECT img[*:*,110,*:*]+img[*:*,111,*:*]+img[*:*,112,*:*]+img[*:*,113,*:*]+img[*:*,114,*:*]+img[*:*,115,*:*]+img[*:*,116,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 75:81, *:*]
+SELECT img[*:*,75,*:*]+img[*:*,76,*:*]+img[*:*,77,*:*]+img[*:*,78,*:*]+img[*:*,79,*:*]+img[*:*,80,*:*]+img[*:*,81,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 162:168, *:*]
+SELECT img[*:*,162,*:*]+img[*:*,163,*:*]+img[*:*,164,*:*]+img[*:*,165,*:*]+img[*:*,166,*:*]+img[*:*,167,*:*]+img[*:*,168,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 80:86, *:*]
+SELECT img[*:*,80,*:*]+img[*:*,81,*:*]+img[*:*,82,*:*]+img[*:*,83,*:*]+img[*:*,84,*:*]+img[*:*,85,*:*]+img[*:*,86,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 50:56, *:*]
+SELECT img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]+img[*:*,53,*:*]+img[*:*,54,*:*]+img[*:*,55,*:*]+img[*:*,56,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 174:180, *:*]
+SELECT img[*:*,174,*:*]+img[*:*,175,*:*]+img[*:*,176,*:*]+img[*:*,177,*:*]+img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]
+FROM tomo_sliced as img
+// ["y"] tomo_sliced [*:*, 33:39, *:*]
+SELECT img[*:*,33,*:*]+img[*:*,34,*:*]+img[*:*,35,*:*]+img[*:*,36,*:*]+img[*:*,37,*:*]+img[*:*,38,*:*]+img[*:*,39,*:*]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 125:131]
+SELECT img[*:*,*:*,125]+img[*:*,*:*,126]+img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 99:105]
+SELECT img[*:*,*:*,99]+img[*:*,*:*,100]+img[*:*,*:*,101]+img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 138:144]
+SELECT img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]+img[*:*,*:*,141]+img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 102:108]
+SELECT img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 89:95]
+SELECT img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]+img[*:*,*:*,94]+img[*:*,*:*,95]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 106:112]
+SELECT img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]+img[*:*,*:*,109]+img[*:*,*:*,110]+img[*:*,*:*,111]+img[*:*,*:*,112]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 38:44]
+SELECT img[*:*,*:*,38]+img[*:*,*:*,39]+img[*:*,*:*,40]+img[*:*,*:*,41]+img[*:*,*:*,42]+img[*:*,*:*,43]+img[*:*,*:*,44]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 11:17]
+SELECT img[*:*,*:*,11]+img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 112:118]
+SELECT img[*:*,*:*,112]+img[*:*,*:*,113]+img[*:*,*:*,114]+img[*:*,*:*,115]+img[*:*,*:*,116]+img[*:*,*:*,117]+img[*:*,*:*,118]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 127:133]
+SELECT img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 71:77]
+SELECT img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 57:63]
+SELECT img[*:*,*:*,57]+img[*:*,*:*,58]+img[*:*,*:*,59]+img[*:*,*:*,60]+img[*:*,*:*,61]+img[*:*,*:*,62]+img[*:*,*:*,63]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 144:150]
+SELECT img[*:*,*:*,144]+img[*:*,*:*,145]+img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]+img[*:*,*:*,149]+img[*:*,*:*,150]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 130:136]
+SELECT img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 101:107]
+SELECT img[*:*,*:*,101]+img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 104:110]
+SELECT img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]+img[*:*,*:*,109]+img[*:*,*:*,110]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 116:122]
+SELECT img[*:*,*:*,116]+img[*:*,*:*,117]+img[*:*,*:*,118]+img[*:*,*:*,119]+img[*:*,*:*,120]+img[*:*,*:*,121]+img[*:*,*:*,122]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 12:18]
+SELECT img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 86:92]
+SELECT img[*:*,*:*,86]+img[*:*,*:*,87]+img[*:*,*:*,88]+img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]
+FROM tomo_sliced as img
+// ["z"] tomo_sliced [*:*, *:*, 44:50]
+SELECT img[*:*,*:*,44]+img[*:*,*:*,45]+img[*:*,*:*,46]+img[*:*,*:*,47]+img[*:*,*:*,48]+img[*:*,*:*,49]+img[*:*,*:*,50]
+FROM tomo_sliced as img
diff --git a/rasodmg/test/tsel_16.ql b/rasodmg/test/tsel_16.ql
new file mode 100644
index 0000000..defdca1
--- /dev/null
+++ b/rasodmg/test/tsel_16.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on tomo_cubed_16.
+
+// [0.5] cubed_16, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from tomo_cubed_16 as img
+
+// [1] cubed_16, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from tomo_cubed_16 as img
+
+// [2] cubed_16, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from tomo_cubed_16 as img
+
+// [5] cubed_16, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from tomo_cubed_16 as img
+
+// [10] cubed_16, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from tomo_cubed_16 as img
+
+// [20] cubed_16, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from tomo_cubed_16 as img
+
+// [50] cubed_16, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from tomo_cubed_16 as img
+
+// [100] cubed_16, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from tomo_cubed_16 as img
+
diff --git a/rasodmg/test/tsel_32.ql b/rasodmg/test/tsel_32.ql
new file mode 100644
index 0000000..e2360a5
--- /dev/null
+++ b/rasodmg/test/tsel_32.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on tomo_cubed.
+
+// [0.5] cubed, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from tomo_cubed as img
+
+// [1] cubed, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from tomo_cubed as img
+
+// [2] cubed, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from tomo_cubed as img
+
+// [5] cubed, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from tomo_cubed as img
+
+// [10] cubed, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from tomo_cubed as img
+
+// [20] cubed, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from tomo_cubed as img
+
+// [50] cubed, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from tomo_cubed as img
+
+// [100] cubed, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from tomo_cubed as img
+
diff --git a/rasodmg/test/tsel_64.ql b/rasodmg/test/tsel_64.ql
new file mode 100644
index 0000000..da24627
--- /dev/null
+++ b/rasodmg/test/tsel_64.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on tomo_cubed_64.
+
+// [0.5] cubed_64, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from tomo_cubed_64 as img
+
+// [1] cubed_64, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from tomo_cubed_64 as img
+
+// [2] cubed_64, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from tomo_cubed_64 as img
+
+// [5] cubed_64, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from tomo_cubed_64 as img
+
+// [10] cubed_64, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from tomo_cubed_64 as img
+
+// [20] cubed_64, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from tomo_cubed_64 as img
+
+// [50] cubed_64, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from tomo_cubed_64 as img
+
+// [100] cubed_64, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from tomo_cubed_64 as img
+
diff --git a/rasodmg/test/tsel_sliced.ql b/rasodmg/test/tsel_sliced.ql
new file mode 100644
index 0000000..4755357
--- /dev/null
+++ b/rasodmg/test/tsel_sliced.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on tomo_sliced.
+
+// [0.5] sliced, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from tomo_sliced as img
+
+// [1] sliced, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from tomo_sliced as img
+
+// [2] sliced, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from tomo_sliced as img
+
+// [5] sliced, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from tomo_sliced as img
+
+// [10] sliced, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from tomo_sliced as img
+
+// [20] sliced, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from tomo_sliced as img
+
+// [50] sliced, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from tomo_sliced as img
+
+// [100] sliced, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from tomo_sliced as img
+
diff --git a/rasodmg/tiling.cc b/rasodmg/tiling.cc
new file mode 100644
index 0000000..89801c3
--- /dev/null
+++ b/rasodmg/tiling.cc
@@ -0,0 +1,309 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: tiling.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Tiling
+ *
+ * COMMENTS:
+ * None
+ *
+*/
+
+//for max min
+#include <algorithm>
+
+//for pow
+#include <math.h>
+#include <iostream>
+#include "rasodmg/tiling.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/minterval.hh"
+#include "rasodmg/gmarray.hh"
+#include "raslib/dlist.hh"
+
+const char*
+r_Tiling::ASTERIX = "*";
+const char*
+r_Tiling::COLON = ";";
+const char*
+r_Tiling::COMMA = ",";
+const char*
+r_Tiling::LSQRBRA = "[";
+const char*
+r_Tiling::RSQRBRA = "]";
+const long
+r_Tiling::DefaultBase = 10;
+
+r_Tiling::~r_Tiling()
+ {
+ }
+
+const char*
+r_No_Tiling::description = "no parameters";
+
+r_No_Tiling::r_No_Tiling(const char* encoded) throw(r_Error)
+ {
+ //we don't use encoded string, it is present in order to have
+ //uniform interface "char* constructor" for every tiling strategy
+ }
+
+r_No_Tiling::r_No_Tiling()
+ {
+ }
+
+r_No_Tiling::~r_No_Tiling()
+ {
+ }
+
+void
+r_No_Tiling::print_status(std::ostream& os) const
+ {
+ os << "r_No_Tiling[ ]";
+ }
+
+bool
+r_No_Tiling::is_compatible(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const
+ {
+ return true;
+ }
+
+std::vector<r_Minterval>*
+r_No_Tiling::compute_tiles(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const throw (r_Error)
+ {
+ RMDBGENTER(4, RMDebug::module_rasodmg, "r_No_Tiling", "compute_tiles(" << obj_domain << ", " << cellTypeSize << ")")
+ std::vector<r_Minterval>* result = new std::vector<r_Minterval>;
+ result->push_back(obj_domain);
+ RMDBGEXIT(4, RMDebug::module_rasodmg, "r_No_Tiling", "compute_tiles() " << *result)
+ return result;
+ }
+
+r_Tiling*
+r_No_Tiling::clone() const
+ {
+ r_Tiling* clo = new r_No_Tiling();
+ return clo;
+ }
+
+r_Tiling_Scheme
+r_No_Tiling::get_tiling_scheme() const
+ {
+ return r_NoTiling;
+ }
+
+std::ostream&
+operator<<(std::ostream& os, const r_Tiling& t)
+ {
+ t.print_status(os);
+ return os;
+ }
+
+const char*
+r_Size_Tiling::description = "tile configuration or tile dimension and tile size (in bytes) (ex: \"[0:9,0:9];100\" or \"2;100\")";
+
+r_Size_Tiling::r_Size_Tiling(const char* encoded) throw (r_Error)
+ : tile_size(0)
+{
+ if(!encoded) {
+ RMInit::logOut << "r_Size_Tiling::r_Size_Tiling(" << (encoded?encoded:"NULL") << ")" << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ r_Bytes tileS=strtol(encoded, (char**)NULL, DefaultBase);
+ if(tileS<=0) {
+ RMInit::logOut << "r_Size_Tiling::r_Size_Tiling(" << encoded << "): Error decoding tile size." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ tile_size = tileS;
+}
+
+r_Size_Tiling::r_Size_Tiling(r_Bytes ts) :
+ tile_size(ts)
+ {
+ }
+
+r_Size_Tiling::~r_Size_Tiling()
+ {
+ }
+
+r_Bytes
+r_Size_Tiling::get_tile_size() const
+ {
+ return tile_size;
+ }
+
+void
+r_Size_Tiling::print_status(std::ostream& os) const
+ {
+ os << "r_Size_Tiling[ tile size = " << tile_size << " ]";
+ }
+
+bool
+r_Size_Tiling::is_compatible(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const
+ {
+ return ((cellTypeSize <= tile_size) && (obj_domain.dimension() != 0));
+ }
+
+std::vector<r_Minterval>*
+r_Size_Tiling::compute_tiles(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const throw (r_Error)
+ {
+ RMDBGENTER(4, RMDebug::module_rasodmg, "r_Size_Tiling", "compute_tiles(" << obj_domain << ", " << cellTypeSize << ")")
+ if (cellTypeSize > tile_size)
+ {
+ RMInit::logOut << "r_Size_Tiling::compute_tiles(" << obj_domain << ", " << cellTypeSize << ") tile size (" << tile_size << ") is smaller than type length (" << cellTypeSize << ")" << endl;
+ throw r_Error(TILESIZETOOSMALL);
+ }
+ std::vector<r_Minterval>* result = new std::vector<r_Minterval>;
+ r_Minterval bigDom = obj_domain;
+ r_Dimension dim = bigDom.dimension();
+ r_Minterval tileDom(dim);
+ // compute the domain of the small tiles
+ // tiles are n-dimensional cubes with edge length n-th root of max tile size
+ RMDBGMIDDLE(4, RMDebug::module_rasodmg, "r_Size_Tiling", "tile size " << get_tile_size())
+ r_Range edgeLength = (r_Range)std::max((r_Range)floor(pow(get_tile_size()/cellTypeSize, 1/(double)dim)), 1);
+ r_Dimension dimcnt = 0;
+ for (dimcnt = 0; dimcnt < dim; dimcnt++)
+ tileDom << r_Sinterval((r_Range)0, edgeLength - 1);
+
+ r_Minterval currDom(dim);
+ r_Point cursor(dim);
+ r_Point tileSize;
+ r_Point origin;
+ bool done = 0;
+
+ // initialize cursor
+ for (dimcnt = 0; dimcnt < dim; dimcnt++)
+ cursor[dimcnt] = 0;
+
+ // calculate size of Tiles
+ tileSize = tileDom.get_extent();
+
+ // origin of bigTile
+ origin = bigDom.get_origin();
+
+ // initialize currDom
+ for (dimcnt=0; dimcnt < dim; dimcnt++)
+ currDom << r_Sinterval((r_Range)origin[dimcnt], (r_Range)(origin[dimcnt] + tileSize[dimcnt] - 1));
+ // resets tileDom to lower left side of bigTile
+ tileDom = currDom;
+
+ // intersect with bigTile
+ currDom.intersection_with(bigDom);
+
+ // iterate with smallTile over bigTile
+ while (!done)
+ {
+ currDom.intersection_with(bigDom);
+ // create new smallTile
+ r_Minterval smallTile(dim);
+
+ smallTile = currDom;
+ // insert tile in set
+ result->push_back(smallTile);
+
+ // increment cursor, start with highest dimension
+ r_Dimension i = cursor.dimension() - 1;
+ cursor[i] += tileSize[i];
+ // move cursor
+ currDom = tileDom.create_translation(cursor);
+ while (!(currDom.intersects_with( bigDom )))
+ {
+ cursor[i] = 0;
+ if (i == 0)
+ {
+ done = true;
+ break;
+ }
+ i--;
+ cursor[i] += tileSize[i];
+ // move cursor
+ currDom = tileDom.create_translation(cursor);
+ }
+ }
+ RMDBGEXIT(4, RMDebug::module_rasodmg, "r_Size_Tiling", "compute_tiles() " << *result)
+ return result;
+ }
+
+r_Tiling*
+r_Size_Tiling::clone() const
+ {
+ r_Tiling* clo = new r_Size_Tiling(tile_size);
+ return clo;
+ }
+
+r_Tiling_Scheme
+r_Size_Tiling::get_tiling_scheme() const
+ {
+ return r_SizeTiling;
+ }
+
+/*
+std::ostream&
+operator<<(std::ostream& os, const r_Size_Tiling& t)
+ {
+ t.print_status(os);
+ return os;
+ }
+*/
+
+r_Dimension_Tiling::r_Dimension_Tiling(r_Dimension dim, r_Bytes ts)
+ : r_Size_Tiling(ts),
+ dimension(dim)
+ {
+ }
+
+r_Dimension_Tiling::~r_Dimension_Tiling()
+ {
+ }
+
+r_Dimension
+r_Dimension_Tiling::get_dimension() const
+ {
+ return dimension;
+ }
+
+void
+r_Dimension_Tiling::print_status(std::ostream& os) const
+ {
+ os << "r_Dimension_Tiling[ ";
+ r_Size_Tiling::print_status(os);
+ os << " dimension = " << dimension << " ]";
+ }
+
+bool
+r_Dimension_Tiling::is_compatible(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const
+ {
+ return ((obj_domain.dimension() == dimension) && r_Size_Tiling::is_compatible(obj_domain, cellTypeSize));
+ }
+
+/*
+std::ostream&
+operator<<(std::ostream& os, const r_Dimension_Tiling& t)
+ {
+ t.print_status(os);
+ return os;
+ }
+*/
+
+
diff --git a/rasodmg/tiling.hh b/rasodmg/tiling.hh
new file mode 100644
index 0000000..e178e0a
--- /dev/null
+++ b/rasodmg/tiling.hh
@@ -0,0 +1,228 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: tiling.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Tiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_TILING_HH_
+#define _R_TILING_HH_
+
+class r_Tiling;
+class r_No_Tiling;
+class r_Size_Tiling;
+class r_Dimension_Tiling;
+class r_Minterval;
+
+// Include statements
+
+#include <vector>
+#include <iostream>
+using std::cout;
+
+#include "raslib/rminit.hh"
+#include "raslib/odmgtypes.hh"
+#include "raslib/mddtypes.hh"
+#include "raslib/error.hh"
+
+//@ManMemo: Module {\bf rasodmg}
+
+/*@Doc:
+
+ The {\tt r_Tiling} class is used to specify in which way the tiling is done
+ by the system. The core method that does that is called {\tt decomposeMDD()}
+ and must be implemented by all derived classes. It takes an object that
+ hasn't yet been split and divides it into tiles. Each derived class
+ implements a diferent decomposition method.
+*/
+
+class r_Tiling
+ {
+ public:
+
+ /// does not do anything
+ virtual ~r_Tiling();
+
+ /// Prints the current status of the object
+ virtual void print_status(std::ostream& os) const = 0;
+
+ /// Check compatibility of object domain with this tiling
+ virtual bool is_compatible(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const = 0;
+
+ /// Decompose an object in tiles
+ virtual std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error) = 0;
+ /**
+ This method provides the core funcionality of this class. All derived
+ classes must implement it. As input parameters it takes the big object to
+ be decomposed and returns a set of tiles that compose the big object.
+ This method throws an exeception when the dimension specified, extend or
+ the cell_size are incompatible with the current tiling. You can check
+ compatibility by invoking is_compatible.
+ */
+
+ /// Clones this object
+ virtual r_Tiling* clone() const = 0;
+ /**
+ This method is similar to a copy constructor, this is, is returns a copy of
+ the current object. Derived classes must explicitly implement this method.
+ */
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const = 0;
+ /**
+ return the type of tiling scheme
+ */
+
+ static const char* ASTERIX;
+ static const char* COLON;
+ static const char* COMMA;
+ static const char* LSQRBRA;
+ static const char* RSQRBRA;
+ static const long DefaultBase;
+ };
+
+class r_Size_Tiling : public r_Tiling
+ {
+ public:
+ /// Constructor that reads everything from a string
+ /// e.g."100"
+ r_Size_Tiling(const char* encoded) throw (r_Error);
+
+ /// Constructor for this object (Takes tile size as parameter)
+ r_Size_Tiling(r_Bytes ts = RMInit::clientTileSize);
+
+ /// does not do anything
+ virtual ~r_Size_Tiling();
+
+ /// Gets the current tile size
+ r_Bytes get_tile_size() const;
+
+ virtual void print_status(std::ostream& os) const;
+
+ /// returns true if the cellTypeSize is smaller or equal to the tile size and obj_domain has more than 0 dimensions
+ virtual bool is_compatible(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const;
+
+ virtual std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const throw (r_Error);
+
+ virtual r_Tiling* clone() const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ static const char* description;
+
+ protected:
+
+ /// Tile size
+ r_Bytes tile_size;
+ };
+
+
+class r_Dimension_Tiling : public r_Size_Tiling
+ {
+ public:
+ /// Constructor for this object (Takes dim (no of dimension) and tile size as parameter)
+ r_Dimension_Tiling(r_Dimension dim, r_Bytes ts = RMInit::clientTileSize);
+
+ /// does not do anything
+ virtual ~r_Dimension_Tiling();
+
+ /// Gets the current dimension
+ r_Dimension get_dimension() const;
+
+ virtual void print_status(std::ostream& os) const;
+
+ virtual bool is_compatible(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const;
+ /// returns true if the cellTypeSize is smaller or equal to the tile size and the dimension fits the obj_domain
+
+ virtual std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const throw (r_Error) = 0;
+
+ virtual r_Tiling* clone() const = 0;
+
+ protected:
+
+ /// dimension the mdd must have
+ r_Dimension dimension;
+ };
+
+
+class r_No_Tiling : public r_Tiling
+ {
+ public:
+ /// Constructor that reads everything from a string e.g."100"
+ /// This string is ignored in the constructor, it is present
+ /// in order to have an uniform interface
+ r_No_Tiling(const char* encoded) throw (r_Error);
+ /// Constructor for this object
+ r_No_Tiling();
+
+ /// does not do anything
+ virtual ~r_No_Tiling();
+
+ /// Prints the current status of the object
+ virtual void print_status(std::ostream& os) const;
+
+ /// Check compatibility of object domain with this tiling
+ virtual bool is_compatible(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const;
+ /// returns true
+
+ /// Decompose an object in tiles
+ virtual std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const throw (r_Error);
+ /// returns obj_domain
+
+ virtual r_Tiling* clone() const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ static const char* description;
+ };
+
+
+/*@Doc:
+ Prints the status of a Tiling object to a stream
+*/
+//extern std::ostream& operator<<(std::ostream& os, const r_Size_Tiling& t);
+
+/*@Doc:
+ Prints the status of a Tiling object to a stream
+*/
+//extern std::ostream& operator<<(std::ostream& os, const r_No_Tiling& t);
+
+/*@Doc:
+ Prints the status of a Tiling object to a stream
+*/
+extern std::ostream& operator<<(std::ostream& os, const r_Tiling& t);
+
+#include "rasodmg/tiling.hh"
+#if (defined(__VISUALC__) && !defined(__EXECUTABLE__))
+ #define __EXECUTABLE__
+ #include "raslib/dlist.hh"
+ #undef __EXECUTABLE__
+#else
+ #include "raslib/dlist.hh"
+#endif
+
+#endif
diff --git a/rasodmg/transaction.cc b/rasodmg/transaction.cc
new file mode 100644
index 0000000..792b8d9
--- /dev/null
+++ b/rasodmg/transaction.cc
@@ -0,0 +1,377 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: transaction.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Transaction
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg, r_Transaction: $Id: transaction.cc,v 1.38 2005/09/03 20:39:35 rasdev Exp $";
+
+
+#ifdef __VISUALC__
+ #ifndef __EXECUTABLE__
+ #define __EXECUTABLE__
+ #define TRANSACTION_NOT_SET
+ #endif
+#endif
+
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+
+#include "raslib/rmdebug.hh"
+#include "raslib/scalar.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef __VISUALC__
+ #ifdef TRANSACTION_NOT_SET
+ #undef __EXECUTABLE__
+ #endif
+
+ template class r_Set< r_Ref<r_Object> >;
+#endif
+
+#include <iostream>
+
+// Initially there is no transaction active.
+r_Transaction* r_Transaction::actual_transaction = 0;
+
+
+
+r_Transaction::r_Transaction()
+ : ta_state( inactive ), ta_mode( read_write )
+{
+}
+
+
+
+r_Transaction::~r_Transaction()
+{
+ if( ta_state == active )
+ abort();
+}
+
+
+
+void
+r_Transaction::begin( r_Transaction::r_TAMode mode ) throw( r_Error )
+{
+ // check if no other transaction is running
+ if( ta_state != inactive || actual_transaction )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionOpen );
+ throw err;
+ }
+
+ // check if a database is opened
+ if( r_Database::actual_database == 0 )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ ta_state = active;
+
+ // if a database is opened, a communication object is existing
+ //r_Database::actual_database->communication->openTA( mode == read_only ? 1 : 0 );
+ r_Database::actual_database->getComm()->openTA( mode == read_only ? 1 : 0 );
+
+ actual_transaction = this;
+ ta_mode = mode;
+}
+
+
+
+void
+r_Transaction::commit() throw( r_Error )
+{
+ if( ta_state != active )
+ {
+ throw( new r_Error( r_Error::r_Error_TransactionNotOpen ) );
+ }
+ else
+ {
+ RMInit::logOut << std::endl << "Commit Log:" << std::endl;
+
+ //
+ // Commit list of r_Object references.
+ //
+
+ r_Iterator< r_Ref<r_Object> > iter = object_list.create_iterator();
+
+ for( iter.reset(); iter.not_done(); iter++ )
+ {
+ if( (*iter)->get_oid().is_valid() )
+ {
+ RMInit::logOut << " Object " << (*iter)->get_oid() << " " << std::flush;
+
+ switch( (*iter)->get_status() )
+ {
+ case r_Object::deleted:
+ RMInit::logOut << "state DELETED, deleting ... " << std::flush;
+ (*iter)->r_Object::delete_obj_from_db();
+ RMInit::logOut << "OK" << std::endl;
+ break;
+
+ case r_Object::created:
+ RMInit::logOut << "state CREATED, writing ... " << std::flush;
+ (*iter)->insert_obj_into_db();
+ RMInit::logOut << "OK" << std::endl;
+ break;
+
+ case r_Object::modified:
+ RMInit::logOut << "state MODIFIED, modifying ... " << std::endl;
+ (*iter)->update_obj_in_db();
+ break;
+
+ case r_Object::read:
+ RMInit::logOut << "state READ, OK" << std::endl;
+ break;
+
+ case r_Object::transient:
+ RMInit::logOut << "state TRANSIENT, OK" << std::endl;
+ break;
+
+ default:
+ RMInit::logOut << "state UNKNOWN" << std::endl;
+ break;
+ }
+ }
+ else
+ RMInit::logOut << " Object with no oid, state TRANSIENT query result" << std::endl;
+ }
+
+ // Don't do the r_deactivate() in the first loop because if a collection is not
+ // before its elements in the list, it tries to save non existing objects.
+
+ for( iter.reset(); iter.not_done(); iter++ )
+ {
+ if( !(*iter)->test_status( r_Object::deleted ) )
+ (*iter)->r_deactivate();
+
+ (*iter)->r_Object::r_deactivate();
+
+ free( (*iter).get_memory_ptr() );
+ }
+
+ object_list.remove_all();
+
+ //
+ // Commit list of non-r_Object references.
+ //
+
+ r_Iterator< GenRefElement* > iter2 = non_object_list.create_iterator();
+
+ for( iter2.reset(); iter2.not_done(); iter2++ )
+ {
+ RMInit::logOut << " Value " << std::flush;
+
+ switch( (*iter2)->type )
+ {
+ case POINT:
+ RMInit::logOut << "transient Point DELETED" << std::endl;
+ delete ((r_Point*)(*iter2)->ref);
+ break;
+
+ case SINTERVAL:
+ RMInit::logOut << "transient Sinterval DELETED" << std::endl;
+ delete ((r_Sinterval*)(*iter2)->ref);
+ break;
+
+ case MINTERVAL:
+ RMInit::logOut << "transient Minterval DELETED" << std::endl;
+ delete ((r_Minterval*)(*iter2)->ref);
+ break;
+
+ case OID:
+ RMInit::logOut << "transient OId DELETED" << std::endl;
+ delete ((r_OId*)(*iter2)->ref);
+ break;
+
+ default:
+ RMInit::logOut << "transient Scalar DELETED" << std::endl;
+ delete ((r_Scalar*)(*iter2)->ref);
+ break;
+ }
+
+ delete *iter2;
+ }
+
+ non_object_list.remove_all();
+
+
+ //
+ // commit transaction on the server
+ //
+
+// r_Database::actual_database->communication->commitTA();
+ r_Database::actual_database->getComm()->commitTA();
+
+ ta_state = inactive;
+ actual_transaction = 0;
+ }
+}
+
+
+
+void
+r_Transaction::abort()
+{
+ if( ta_state != active )
+ {
+ throw( r_Error( r_Error::r_Error_TransactionNotOpen ) );
+ }
+ else
+ {
+ RMInit::logOut << std::endl << "Abort Log:" << std::endl;
+
+ //
+ // Abort list of r_Object references.
+ //
+
+ r_Iterator< r_Ref<r_Object> > iter = object_list.create_iterator();
+
+ for( iter.reset(); iter.not_done(); iter++ )
+ {
+ RMInit::logOut << " Object DELETED" << std::endl;
+
+ if( !(*iter)->test_status( r_Object::deleted ) )
+ (*iter)->r_deactivate();
+
+ (*iter)->r_Object::r_deactivate();
+
+ free( (*iter).get_memory_ptr() );
+ }
+
+ object_list.remove_all();
+
+ //
+ // Abort list of non-r_Object references.
+ //
+
+ r_Iterator< GenRefElement* > iter2 = non_object_list.create_iterator();
+
+ for( iter2.reset(); iter2.not_done(); iter2++ )
+ {
+ switch( (*iter2)->type )
+ {
+ case POINT:
+ RMInit::logOut << " Transient Point DELETED" << std::endl;
+ delete ((r_Point*)(*iter2)->ref);
+ break;
+
+ case SINTERVAL:
+ RMInit::logOut << " Transient Sinterval DELETED" << std::endl;
+ delete ((r_Sinterval*)(*iter2)->ref);
+ break;
+
+ case MINTERVAL:
+ RMInit::logOut << " Transient Minterval DELETED" << std::endl;
+ delete ((r_Minterval*)(*iter2)->ref);
+ break;
+
+ case OID:
+ RMInit::logOut << " Transient OId DELETED" << std::endl;
+ delete ((r_OId*)(*iter2)->ref);
+ break;
+
+ default:
+ RMInit::logOut << " Transient Scalar DELETED" << std::endl;
+ delete ((r_Scalar*)(*iter2)->ref);
+ break;
+ }
+
+ delete *iter2;
+ }
+
+ non_object_list.remove_all();
+
+ //
+ // Abort transaction on the server.
+ //
+ if (r_Database::actual_database)
+// r_Database::actual_database->communication->abortTA();
+ r_Database::actual_database->getComm()->abortTA();
+ else
+ RMInit::logOut << " Database was already closed. Please abort every transaction before closing the database. Please also check for any try/catches with a close database but without transaction abort." << std::endl;
+
+ ta_state = inactive;
+ actual_transaction = 0;
+ }
+}
+
+
+
+r_Ref_Any
+r_Transaction::load_object( const r_OId& oid )
+{
+ // check, if object is already loaded
+ unsigned int found = 0;
+ r_Iterator< r_Ref<r_Object> > iter = object_list.create_iterator();
+
+ iter.reset();
+ while( iter.not_done() && !found )
+ {
+ found = ( (*iter)->get_oid() == oid );
+ if( !found ) iter++;
+ }
+
+ if( found )
+ {
+ // return reference of loaded object
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Transaction", "load_object( oid ) - object already loaded")
+ return *iter;
+ }
+ else
+ {
+ // load object and return reference
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Transaction", "load_object( oid ) - load object")
+ return r_Database::actual_database->lookup_object( oid );
+ }
+}
+
+
+
+void
+r_Transaction::add_object_list( const r_Ref<r_Object> &obj )
+{
+ object_list.insert_element( obj );
+}
+
+
+
+void
+r_Transaction::add_object_list( GenRefType type, void* ref )
+{
+ GenRefElement* element = new GenRefElement;
+
+ element->type = type;
+ element->ref = ref;
+
+ non_object_list.insert_element( element );
+}
+
diff --git a/rasodmg/transaction.hh b/rasodmg/transaction.hh
new file mode 100644
index 0000000..443855a
--- /dev/null
+++ b/rasodmg/transaction.hh
@@ -0,0 +1,167 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: transaction.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Transaction
+ *
+ * COMMENTS:
+ * None
+*/
+
+//@ManMemo: Module: {\bf rasodmg}
+
+#ifndef _D_TRANSACTION_
+#define _D_TRANSACTION_
+
+#include "raslib/error.hh"
+#include "raslib/oid.hh"
+
+class r_Object;
+
+#include "rasodmg/set.hh"
+#include "rasodmg/ref.hh"
+
+/*@Doc:
+
+ Transactions can be started, committed, aborted, and checkpointed.
+ It is important to note that all access, creation, modification,
+ and deletion of persistent objects must be done within a transaction.
+ Right now, only one transaction can be active at a time.
+
+*/
+
+class r_Transaction
+{
+ public:
+ /// possible states of the transaction
+ enum r_TAStatus { active, inactive, comiting, aborting };
+
+ /// possible transaction modes
+ enum r_TAMode { read_write, read_only };
+
+ /// default constructor
+ r_Transaction();
+
+ /// destructor, an active transaction is aborted
+ ~r_Transaction();
+
+ /// start the transaction
+ void begin( r_TAMode mode = read_write ) throw( r_Error );
+ /**
+ By default, a transaction is started in write mode. If the read_only
+ mode is specified, no write operations are allowed within the transaction
+ anymore.
+ If any write operation occurs in read_only mode, the exception r_Error with
+ kind {\tt r_Error_TransactionReadOnly} will be raised and the transaction will
+ be aborted.
+ In order to achieve maximal performance, read-only transactions should be used
+ whenever posssible, i.e., when no update operations occur within this transaction.
+ */
+
+ /// commit transaction and make changes persistent
+ void commit() throw( r_Error );
+ /**
+ The transaction is committed and changes are made persistent
+ in the database.
+ While committing, the following errors can occur:
+
+ \begin{tabular}{lll}
+ r_Error_TransferFailed && Server communication problem.\\
+ r_Error_ObjectUnknown && Name of object is unknown.\\
+ r_Error_DatabaseClassUndefined && Type name of object not known by the database.\\
+ r_Error_CollectionElementTypeMismatch && Collection and MDD type mismatch.\\
+ \end{tabular}
+ */
+
+ /// abort transaction and forget changes within transaction
+ void abort();
+
+ /// returns the current state
+ inline r_TAStatus get_status() const;
+
+ /// returns current mode
+ inline r_TAMode get_mode() const;
+
+ //@Man: Methods and types for internal use only:
+ //@{
+ ///
+
+ /// store a pointer to the actual transaction
+ static r_Transaction* actual_transaction;
+
+ /// load an object (internal use only)
+ r_Ref_Any load_object( const r_OId& oid );
+
+ /// possible non-r_Object values maintained by the transaction
+ enum GenRefType { MINTERVAL, SINTERVAL, POINT, OID, SCALAR };
+
+ /// adds a non-r_Object to the list of persistent objects
+ void add_object_list( GenRefType type, void* ref );
+
+ ///
+ //@}
+
+ private:
+ /// adds an object of type \Ref{r_Object} to the list of persistent objects
+ void add_object_list( const r_Ref<r_Object>& );
+
+ /// current transaction state
+ r_TAStatus ta_state;
+
+ /// current transaction mode (just valid if transaction is active)
+ r_TAMode ta_mode;
+
+ /// list of \Ref{r_Object} references which have been created within the transaction
+ r_Set< r_Ref<r_Object> > object_list;
+
+ // element type of non \Ref{r_Object} list maintained by the transaction
+ typedef struct{ GenRefType type; void* ref; } GenRefElement;
+
+ /// list of non \Ref{r_Object} references which have been created within the transaction
+ r_Set< GenRefElement* > non_object_list;
+
+ friend class r_Object;
+};
+
+#define DEF_TRANSACTION
+
+#include "rasodmg/iterator.hh"
+// For HP cfront compiler each template instantiation used in a library
+// must be defined in an included header.
+typedef r_Iterator<r_Object*> r_Iterator_r_Object_dummy;
+#include "rasodmg/transaction.icc"
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#ifdef __VISUALC__
+#include "rasodmg/ref.cpp"
+#else
+#include "rasodmg/ref.cc"
+#endif
+#endif
+#endif
+
+
+#endif
diff --git a/rasodmg/transaction.icc b/rasodmg/transaction.icc
new file mode 100644
index 0000000..58e662f
--- /dev/null
+++ b/rasodmg/transaction.icc
@@ -0,0 +1,46 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INLINE SOURCE: transaction.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Transaction
+ *
+ * COMMENTS:
+ * None
+*/
+
+inline
+r_Transaction::r_TAStatus
+r_Transaction::get_status() const
+{
+ return ta_state;
+}
+
+
+inline
+r_Transaction::r_TAMode
+r_Transaction::get_mode() const
+{
+ return ta_mode;
+}