/*
* 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 .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
/
/**
* 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
#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 // for memcpy()
#include
#include
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() : "") << endl;
s << " Type Schema...........: " << std::flush;
if (typeSchema)
typeSchema->print_status(s);
else
s << "" << std::flush;
s << endl;
s << " Domain................: " << domain << endl;
s << " Base Type Schema......: " << std::flush;
if (baseTypeSchema)
baseTypeSchema->print_status(s);
else
s << "" << 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 << "" << 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; jprint_value(data, s );
else s << "" << 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;
}