ClassConversion.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 #include "eyedb_p.h"
00026 #include <assert.h>
00027 #define DSPID 0
00028 #include <sstream>
00029 using std::ostringstream;
00030 
00031 //
00032 // needs:
00033 //  hash table
00034 // warning to memory leaks!
00035 //
00036 
00037 namespace eyedb {
00038 
00039 static Bool dont_use_oql = getenv("EYEDBDONTUSEOQL") ? True : False;
00040 
00041 static int
00042 cmp(const void *o1, const void *o2)
00043 {
00044   ClassConversion *c1 = *(ClassConversion **)o1;
00045   ClassConversion *c2 = *(ClassConversion **)o2;
00046   ClassUpdateType t1 = c1->getUpdtype();
00047   ClassUpdateType t2 = c2->getUpdtype();
00048 
00049   if (t1 == RMV_ATTR) {
00050     if (t2 == ADD_ATTR)
00051       return -1;
00052     if (t2 == CNV_ATTR)
00053       return -1;
00054     if (t2 == RMV_ATTR)
00055       return c2->getOffsetN() - c1->getOffsetN();
00056   }
00057 
00058   if (t1 == ADD_ATTR) {
00059     if (t2 == RMV_ATTR)
00060       return 1;
00061     if (t2 == CNV_ATTR || t2 == ADD_ATTR)
00062       return c1->getOffsetN() - c2->getOffsetN();
00063   }
00064 
00065   if (t1 == CNV_ATTR) {
00066     if (t2 == RMV_ATTR)
00067       return 1;
00068     if (t2 == CNV_ATTR || t2 == ADD_ATTR)
00069       return c1->getOffsetN() - c2->getOffsetN();
00070   }
00071 
00072   assert(0); // for now
00073   return 0;
00074 }
00075 
00076 static void
00077 sort_array(ObjectArray *obj_arr_pt)
00078 {
00079   Object **objs = new Object*[obj_arr_pt->getCount()];
00080   int cnt = obj_arr_pt->getCount();
00081   for (int i = 0; i < cnt; i++)
00082     objs[i] = const_cast<Object *>((*obj_arr_pt)[i]);
00083   qsort(objs, cnt, sizeof(Object *), cmp);
00084   obj_arr_pt->set(objs, cnt);
00085 }
00086 
00087 ClassConversion::Context::Context()
00088 {
00089   cls = 0;
00090   next = 0;
00091 }
00092 
00093 ClassConversion::Context::~Context()
00094 {
00095 }
00096 
00097 #define CLSCNV(X) ((ClassConversion *)(X))
00098 
00099 /* static method */
00100 Status
00101 ClassConversion::getClass_(Database *_db, const Oid &ocloid,
00102                            const Class *&cls,
00103                            ClassConversion::Context *&conv_ctx,
00104                            Bool class_to_class)
00105 {
00106   assert(!_db->isOpeningState());
00107   assert(ocloid.isValid());
00108 
00109   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("looking for old class %s\n", ocloid.toString()));
00110   conv_ctx = (Context *)_db->getConvCache().getObject(ocloid);
00111 
00112   if (conv_ctx && conv_ctx->cls) // added && conv_ctx->cls on the 5/06/01
00113     {
00114       cls = conv_ctx->cls;
00115       IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("... found in cache %s\n", cls->getName()));
00116       return Success;
00117     }
00118 
00119   Status s;
00120   conv_ctx = new Context();
00121   ObjectArray *obj_arr_pt = &conv_ctx->obj_arr;
00122 
00123   if (dont_use_oql) {
00124     ObjectArray tmp_obj_arr;
00125     Iterator iter(_db->getSchema()->getClass("class_conversion"));
00126     s = iter.scan(tmp_obj_arr);
00127     if (s) return s;
00128     int cnt = tmp_obj_arr.getCount();
00129     Object **objs = new Object *[cnt];
00130     int n = 0;
00131     for (int i = 0; i < cnt; i++) {
00132       ClassConversion *cls_cnv = (ClassConversion *)tmp_obj_arr[i];
00133       if (cls_cnv->getOidO() == ocloid)
00134         objs[n++] = const_cast<Object *>(tmp_obj_arr[i]);
00135     }
00136 
00137     obj_arr_pt->set(objs, n);
00138     delete [] objs;
00139     //printf("dont_use_oql found %d\n", obj_arr_pt->getCount());
00140   }
00141   else {
00142     OQL q(_db, "select class_conversion.oid_o = %s", ocloid.toString());
00143 
00144     s = q.execute(*obj_arr_pt);
00145     if (s) return s;
00146     //printf("use_oql found %d\n", obj_arr_pt->getCount());
00147   }
00148 
00149   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("..... %d object(s) found\n", obj_arr_pt->getCount()));
00150   if (!obj_arr_pt->getCount())
00151     {
00152       delete conv_ctx;
00153       Class *xcls;
00154       s = _db->reloadObject(ocloid, (Object *&)xcls);
00155       if (!s && xcls->isRemoved()) {
00156         xcls->release();
00157         return Exception::make(IDB_ERROR, "dynamic schema module "
00158                                "internal error: class %s is removed",
00159                                ocloid.toString());
00160       }
00161 
00162       if (s)
00163         return s;
00164       return Exception::make(IDB_ERROR,
00165                              "dynamic schema module internal error: "
00166                              "class %s not found", ocloid.toString());
00167     }
00168 
00169   sort_array(obj_arr_pt);
00170   _db->getConvCache().insertObject(ocloid, conv_ctx);
00171 
00172   if (eyedblib::log_mask & IDB_LOG_SCHEMA_EVOLVE)
00173     for (int i = 0; i < obj_arr_pt->getCount(); i++)
00174       {
00175         IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("conv[%d] = ", i));
00176         (*obj_arr_pt)[i]->trace(stdout, CMTimeTrace);
00177     }
00178 
00179   ClassConversion *conv = CLSCNV((*obj_arr_pt)[0]);
00180   conv_ctx->cls = cls = _db->getSchema()->getClass(conv->getOidN());
00181   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("new class oid=%s, class=%p\n", conv->getOidN().toString(), cls));
00182 
00183   if (cls || class_to_class)
00184     return Success;
00185     
00186   s = getClass_(_db, conv->getOidN(), cls, conv_ctx->next);
00187   if (s) return s;
00188   conv_ctx->cls = cls;
00189   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("...class=%p\n", cls));
00190   return Success;
00191 }
00192 
00193 /* static method */
00194 Size
00195 ClassConversion::computeSize(ClassConversion::Context *conv_ctx,
00196                                 Size start_size)
00197 {
00198   Size cur_size = start_size;
00199   Size max_size = cur_size;
00200 
00201   while (conv_ctx)
00202     {
00203       const ObjectArray *obj_arr_pt = &conv_ctx->obj_arr;
00204       
00205       for (int i = 0; i < obj_arr_pt->getCount(); i++)
00206         {
00207           CLSCNV((*obj_arr_pt)[i])->computeSize(cur_size);
00208           if (cur_size > max_size)
00209             max_size = cur_size;
00210         }
00211 
00212       conv_ctx = conv_ctx->next;
00213     }
00214 
00215   return max_size;
00216 }
00217 
00218 static Status (*cnv_convert[NIL_CNV+1])(Database *db,
00219                                               ClassConversion *clscnv,
00220                                               Data in_idr,
00221                                               Size &in_size);
00222 static void (*cnv_computeSize[NIL_CNV+1])(ClassConversion *clscnv,
00223                                              Size &cur_size);
00224 
00225 void
00226 ClassConversion::computeSize(Size &cur_size)
00227 {
00228   switch(getUpdtype())
00229     {
00230     case ADD_ATTR:
00231       cur_size += getSizeN();
00232       break;
00233 
00234     case RMV_ATTR:
00235       cur_size -= getSizeN();
00236       break;
00237 
00238     case CNV_ATTR:
00239       cnv_computeSize[getCnvtype()](this, cur_size);
00240       break;
00241 
00242     default:
00243       assert(0);
00244       break;
00245     }
00246 }
00247 
00248 /* static method */
00249 Status
00250 ClassConversion::convert(Database *_db,
00251                             const ClassConversion::Context *conv_ctx,
00252                             Data in_idr, Size in_size)
00253 {
00254   int n = 0;
00255   while (conv_ctx)
00256     {
00257       const ObjectArray *obj_arr_pt = &conv_ctx->obj_arr;
00258       
00259       int cnt = obj_arr_pt->getCount();
00260       IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("converting #%d {\n", n++));
00261       for (int i = 0; i < cnt; i++)
00262         {
00263           IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\tconvert hint #%d\n", i));
00264           Status s = CLSCNV((*obj_arr_pt)[i])->convert(_db, in_idr, in_size);
00265           if (s) return s;
00266         }
00267 
00268       IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("}\n\n"));
00269       conv_ctx = conv_ctx->next;
00270     }
00271 
00272   return Success;
00273 }
00274 
00275 /* instance method */
00276 Status
00277 ClassConversion::convert(Database *_db, Data in_idr, Size &in_size)
00278 {
00279   switch(getUpdtype())
00280    {
00281     case ADD_ATTR: {
00282       Offset offset = getOffsetN();
00283       Data start = in_idr + offset;
00284       Size size = getSizeN();
00285 
00286       IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tadd attribute %s::%s offsetN=%d sizeN=%d "
00287              "in_size=%d sizemoved=%d\n",
00288              getClsname().c_str(), getAttrname().c_str(), offset, size,
00289              in_size, in_size - size - offset));
00290 
00291       // changed the 6/6/01
00292       // memmove(start + size, start, in_size - size - offset);
00293       memmove(start + size, start, in_size - offset);
00294       memset(start, 0, size);
00295       in_size += size;
00296       return Success;
00297     }
00298 
00299     case RMV_ATTR: {
00300       Offset offset = getOffsetN();
00301       Data start = in_idr + offset;
00302       Size size = getSizeN();
00303       IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\trmv attribute %s::%s offsetN=%d sizeN=%d "
00304              "in_size=%d sizemoved=%d\n",
00305              getClsname().c_str(), getAttrname().c_str(), offset, size,
00306              in_size, in_size - size - offset));
00307 
00308       memmove(start, start + size, in_size - size - offset);
00309       in_size -= size;
00310       return Success;
00311     }
00312 
00313    case CNV_ATTR: {
00314       Offset offset = getOffsetN();
00315       Size size = getSizeN();
00316       IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tcnv attribute %s::%s offsetN=%d sizeN=%d "
00317              "in_size=%d, srcdim=%d, destdim=%d\n",
00318              getClsname().c_str(), getAttrname().c_str(), offset, size,
00319              in_size, getSrcDim(), getDestDim()));
00320       return cnv_convert[getCnvtype()](_db, this, in_idr, in_size);
00321       //return Exception::make(IDB_ERROR, "converting attribute is not yet implemented");
00322    }
00323 
00324     default:
00325       return Exception::make(IDB_ERROR, "conversion %d is not yet implemented", getUpdtype());
00326    }
00327 }
00328 
00329 void
00330 ClassConversion::userInitialize()
00331 {
00332   cls_ = 0;
00333   attr_ = 0;
00334 }
00335 
00336 void
00337 ClassConversion::userCopy(const Object &)
00338 {
00339   ClassConversion::userInitialize();
00340 }
00341 
00342 void
00343 ClassConversion::userGarbage()
00344 {
00345 }
00346 
00347 //
00348 // CNV_ATTR family conversions
00349 //
00350 
00351 // !!!!!! WARNING: duplicated code from attr.cc !!!!!!
00352 #define IS_LOADED_MASK        (unsigned int)0x40000000
00353 #define SZ_MASK               (unsigned int)0x80000000
00354 
00355 #define IS_LOADED(X)          (((X) & IS_LOADED_MASK) ? True : False)
00356 #define SET_IS_LOADED(X, B)   ((B) ? (((X) | IS_LOADED_MASK)) : ((X) & ~IS_LOADED_MASK))
00357 
00358 #define IS_SIZE_CHANGED(X)     (((X) & SZ_MASK) ? True : False)
00359 #define SET_SIZE_CHANGED(X, B) ((B) ? (((X) | SZ_MASK)) : ((X) & ~SZ_MASK))
00360 
00361 #define CLEAN_SIZE(X)          ((X) & ~(SZ_MASK|IS_LOADED_MASK))
00362 
00363 static int inline iniSize(int dim)
00364 {
00365   if (!dim)
00366     return 0;
00367   return ((dim-1) >> 3) + 1;
00368 }
00369 // !!!!!! END OF WARNING !!!!!!
00370 
00371 extern eyedbsm::DbHandle *IDB_get_se_DbHandle(Database *db);
00372 
00373 //
00374 // Macro definitions
00375 //
00376 
00377 static const char wrerr[] =  "schema flexibility process: to perform "
00378 "some conversions database should be opened in read or read/write mode "
00379 "not in strict read mode";
00380 
00381 #define CNV_VD_SRC_DST(SRCTYP, DSTTYP) \
00382 { \
00383   Offset offset = clscnv->getOffsetN(); \
00384   Data start = in_idr + offset; \
00385  \
00386   Size count; \
00387   mcp(&count, start, sizeof(count)); \
00388   count = CLEAN_SIZE(count); \
00389  \
00390   Size inisize_s = iniSize(count); \
00391   Size wpsize_s = sizeof(SRCTYP) * count * (-dim_s) + inisize_s; \
00392  \
00393   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_VD_SRC_DST: count=%d, inisize_s=%d, wpsize_s=%d\n", count, inisize_s, wpsize_s)); \
00394   Oid oid_s; \
00395   mcp(&oid_s, start + sizeof(Size), sizeof(oid_s)); \
00396  \
00397   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_VD_SRC_DST OID=%s\n", oid_s.toString())); \
00398   unsigned char *pdata_s = new unsigned char[wpsize_s]; \
00399   eyedbsm::Status se_status; \
00400   eyedbsm::DbHandle *sedbh = IDB_get_se_DbHandle(db); \
00401   se_status = eyedbsm::objectRead(sedbh, 0, wpsize_s, pdata_s, eyedbsm::DefaultLock, 0, 0, \
00402                              oid_s.getOid()); \
00403  \
00404   if (se_status) { \
00405     delete[] pdata_s; \
00406     return Exception::make(IDB_ERROR, eyedbsm::statusGet(se_status)); \
00407   }   \
00408  \
00409   Size wpsize_d = sizeof(DSTTYP) * count * (-dim_d) + inisize_s; \
00410   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_VD_SRC_DST: wpsize_ds=%d\n", wpsize_d)); \
00411   unsigned char *pdata_d = new unsigned char[wpsize_d]; \
00412   memcpy(pdata_d, pdata_s, inisize_s); \
00413    \
00414   Data start_s = pdata_s + inisize_s; \
00415   Data start_d = pdata_d + inisize_s; \
00416  \
00417   for (int i = 0; i < count; i++) {  \
00418     SRCTYP data_s; \
00419     mcp(&data_s, start_s, sizeof(SRCTYP)); \
00420     DSTTYP data_d = (DSTTYP)data_s; \
00421     mcp(start_d, &data_d, sizeof(DSTTYP)); \
00422     start_s += sizeof(SRCTYP); \
00423     start_d += sizeof(DSTTYP); \
00424   } \
00425  \
00426   delete[] pdata_s; \
00427   se_status = eyedbsm::objectSizeModify(sedbh, wpsize_d, eyedbsm::True, oid_s.getOid()); \
00428   if (se_status) { \
00429     delete[] pdata_d; \
00430     return Exception::make(IDB_ERROR, eyedbsm::statusGet(se_status)); \
00431   }   \
00432  \
00433   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_VD_SRC_DST: writing back\n")); \
00434  \
00435   if (!db->writeBackConvertedObjects()) \
00436     return Exception::make(IDB_ERROR, wrerr); \
00437  \
00438   se_status = eyedbsm::objectWrite(sedbh, 0, wpsize_d, pdata_d, oid_s.getOid()); \
00439     delete[] pdata_d; \
00440   if (se_status) \
00441     return Exception::make(IDB_ERROR, eyedbsm::statusGet(se_status)); \
00442  \
00443   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_VD_SRC_DST: writing back done\n")); \
00444   return Success; \
00445 }
00446 
00447 static int
00448 get_top(Data start, int dim)
00449 {
00450   for (int d = dim-1; d >= 0; d--)
00451     if (!Attribute::isNull(start, 1, d))
00452       return d+1;
00453 
00454   return 0;
00455 }
00456 
00457 #define CNV_VD_DST(SRCTYP, DSTTYP) \
00458 { \
00459   Offset offset = clscnv->getOffsetN(); \
00460   Data start = in_idr + offset; \
00461  \
00462   Size inisize_s = iniSize(dim_s); \
00463   Size wpsize_s = sizeof(SRCTYP) * dim_s + inisize_s; \
00464  \
00465   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_VD_DST: inisize_s=%d, wpsize_s=%d\n", inisize_s, wpsize_s)); \
00466  \
00467   eyedbsm::Status se_status; \
00468   eyedbsm::DbHandle *sedbh = IDB_get_se_DbHandle(db); \
00469  \
00470   int ndim_d = get_top(start, dim_s); \
00471   Oid oid_d; \
00472   if (ndim_d) { \
00473     Size inisize_d = iniSize(ndim_d); \
00474     Size wpsize_d = sizeof(DSTTYP) * ndim_d + inisize_d; \
00475     IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_VD_DST: ndim_d=%d, wpsize_d=%d\n", ndim_d, wpsize_d)); \
00476     unsigned char *pdata_d = new unsigned char[wpsize_d]; \
00477     memcpy(pdata_d, start, inisize_d); \
00478      \
00479     Data start_s = start + inisize_s; \
00480     Data start_d = pdata_d + inisize_d; \
00481    \
00482     for (int i = 0; i < ndim_d; i++) {  \
00483       SRCTYP data_s; \
00484       mcp(&data_s, start_s, sizeof(SRCTYP)); \
00485       DSTTYP data_d = (DSTTYP)data_s; \
00486       IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_VD_DST: DATA_S %f %d\n", data_s, data_d)); \
00487       mcp(start_d, &data_d, sizeof(DSTTYP)); \
00488       start_s += sizeof(SRCTYP); \
00489       start_d += sizeof(DSTTYP); \
00490     } \
00491    \
00492     se_status = eyedbsm::objectCreate(sedbh, pdata_d, wpsize_d, DSPID, oid_d.getOid()); \
00493     delete[] pdata_d; \
00494     if (se_status) \
00495       return Exception::make(IDB_ERROR, eyedbsm::statusGet(se_status)); \
00496    \
00497   } \
00498  \
00499   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_VD_DST: new oid is %s\n", oid_d.toString())); \
00500  \
00501   memmove(start + sizeof(Size) + sizeof(Oid), \
00502           start + wpsize_s, \
00503           in_size - offset - wpsize_s); \
00504   \
00505   mcp(start, &ndim_d, sizeof(Size)); \
00506   mcp(start + sizeof(Size), oid_d.getOid(), sizeof(eyedbsm::Oid)); \
00507  \
00508   in_size += sizeof(Size) + sizeof(Oid) - wpsize_s; \
00509   return Success; \
00510 }
00511 
00512 #define CNV_VD_SRC(x, y) return Success
00513 
00514 #define BASIC_CONVERT(SRCTYP, DSTTYP) \
00515   int dim_s = clscnv->getSrcDim(); \
00516   int dim_d = clscnv->getDestDim(); \
00517  \
00518   if (dim_s == 1 && dim_d == 1) { \
00519      Offset offset = clscnv->getOffsetN(); \
00520      Data start = in_idr + offset + 1; \
00521      SRCTYP data_s; \
00522      DSTTYP data_d; \
00523      \
00524      mcp(&data_s, start, sizeof(SRCTYP)); \
00525      memmove(start + sizeof(DSTTYP), start + sizeof(SRCTYP), \
00526              in_size - sizeof(SRCTYP) - offset - 1); \
00527      data_d = (DSTTYP)data_s; \
00528      ostringstream ostr; \
00529      ostr << "\t\tfrom: " << data_s << " to: " << data_d; \
00530      IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("%s\n", ostr.str().c_str())); \
00531      mcp(start, &data_d, sizeof(DSTTYP)); \
00532      in_size += sizeof(DSTTYP) - sizeof(SRCTYP); \
00533      return Success; \
00534   } \
00535  \
00536   if (dim_s < 0 && dim_d < 0) \
00537     CNV_VD_SRC_DST(SRCTYP, DSTTYP); \
00538  \
00539   if (dim_d < 0) \
00540     CNV_VD_DST(SRCTYP, DSTTYP); \
00541  \
00542   if (dim_s < 0) \
00543     CNV_VD_SRC(SRCTYP, DSTTYP); \
00544  \
00545   Offset offset = clscnv->getOffsetN(); \
00546   Data start = in_idr + offset; \
00547   Size inisize_s = iniSize(dim_s); \
00548   Size inisize_d = iniSize(dim_d); \
00549   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tinisizes %d %d\n", inisize_s, inisize_d)); \
00550   Data start_s = start + inisize_s; \
00551   Data start_d = start + inisize_d; \
00552   SRCTYP *pdata_s = new SRCTYP[dim_s]; \
00553  \
00554   for (int i = 0; i < dim_s; i++) { \
00555     mcp(&pdata_s[i], start_s, sizeof(SRCTYP)); \
00556     start_s += sizeof(SRCTYP); \
00557   } \
00558   \
00559   unsigned char *inidata_s; \
00560   if (dim_d < dim_s) { \
00561      inidata_s = new unsigned char[inisize_s]; \
00562      memcpy(inidata_s, start, inisize_s); \
00563   } \
00564  \
00565   memmove(start_d + dim_d * sizeof(DSTTYP), \
00566           start + inisize_s + dim_s * sizeof(SRCTYP), \
00567           in_size - dim_s * sizeof(SRCTYP) - offset - inisize_s); \
00568   \
00569   if (dim_d < dim_s) { \
00570     memcpy(start, inidata_s, inisize_s); \
00571     delete [] inidata_s; \
00572   } \
00573  \
00574   int dim = (dim_s < dim_d ? dim_s : dim_d); \
00575   for (int i = 0; i < dim; i++) { \
00576     DSTTYP data_d = (DSTTYP)pdata_s[i]; \
00577     mcp(start_d, &data_d, sizeof(DSTTYP)); \
00578     start_d += sizeof(DSTTYP); \
00579   } \
00580  \
00581   delete [] pdata_s; \
00582  \
00583   if (dim_d > dim_s) { \
00584     memset(start + inisize_s, 0, inisize_d - inisize_s); \
00585     memset(start_d, 0, (dim_d - dim_s) * sizeof(DSTTYP)); \
00586   } \
00587  \
00588   in_size += inisize_d - inisize_s + dim_d * sizeof(DSTTYP) - dim_s * sizeof(SRCTYP); \
00589   return Success
00590 
00591 #define CNV_MAKE_CONVERT(CNVTYP, SRCTYP, DSTTYP) \
00592 static Status \
00593 CNVTYP##_convert(Database *db, ClassConversion *clscnv, Data in_idr, Size &in_size) \
00594 { \
00595   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\t" #CNVTYP " conversion\n")); \
00596   BASIC_CONVERT(SRCTYP, DSTTYP); \
00597 }
00598 
00599 // WANING DID NOT WORK FOR VARIABLE DIMENSION like x[][2]
00600 // should take -dim_d and dim_s into account!!
00601 // but the most simple is to forbid multi dimensionnal array conversion!
00602 #define CNV_MAKE_COMPSIZE(CNVTYP, SRCTYP, DSTTYP) \
00603 static void \
00604 CNVTYP##_computeSize(ClassConversion *clscnv, Size &cur_size) \
00605 { \
00606   int dim_d = clscnv->getDestDim(); \
00607   int dim_s = clscnv->getSrcDim(); \
00608   if (dim_d > 0 && dim_s > 0) \
00609     cur_size += iniSize(dim_d) - iniSize(dim_s) + dim_d * sizeof(DSTTYP) - dim_s * sizeof(SRCTYP); \
00610   else if (dim_d < 0 && dim_s > 0) \
00611     cur_size += sizeof(Size) + sizeof(Oid) - iniSize(dim_s) - dim_s * sizeof(SRCTYP); \
00612 }
00613 
00614 #define CNV_MAKE(CNVTYP, SRCTYP, DSTTYP) \
00615   CNV_MAKE_CONVERT(CNVTYP, SRCTYP, DSTTYP) \
00616   CNV_MAKE_COMPSIZE(CNVTYP, SRCTYP, DSTTYP)
00617 
00618 //
00619 // CNV_NYI (i.e. Not Yet Implemented) macro family
00620 //
00621 
00622 #define CNV_MAKE_NYI_CONVERT(CNVTYP, SRCTYP, DSTTYP) \
00623 static Status \
00624 CNVTYP##_convert(Database *db, ClassConversion *clscnv, Data in_idr, Size &in_size) \
00625 { \
00626   return Exception::make(IDB_ERROR, #CNVTYP " conversion not yet implemented"); \
00627 }
00628 
00629 #define CNV_MAKE_NYI_COMPSIZE(CNVTYP, SRCTYP, DSTTYP) \
00630 static void \
00631 CNVTYP##_computeSize(ClassConversion *clscnv, Size &cur_size) \
00632 { \
00633   cur_size += 0; \
00634 }
00635 
00636 #define CNV_MAKE_NYI(CNVTYP, SRCTYP, DSTTYP) \
00637   CNV_MAKE_NYI_CONVERT(CNVTYP, SRCTYP, DSTTYP) \
00638   CNV_MAKE_NYI_COMPSIZE(CNVTYP, SRCTYP, DSTTYP)
00639 
00640 //
00641 // CNV_2STR macro family
00642 //
00643 
00644 #define VARS_INISZ 3
00645 #define VARS_SZ   24
00646 #define VARS_TSZ  (VARS_INISZ+VARS_SZ)
00647 #define VARS_OFFSET (sizeof(Size) + sizeof(Oid))
00648 #define VARS_DATA(IDR) ((IDR) + idr_poff + VARS_OFFSET)
00649 
00650 #define CNV_MAKE_2STR_CONVERT(CNVTYP, SRCTYP) \
00651 static Status \
00652 CNVTYP##_convert(Database *db, ClassConversion *clscnv, Data in_idr, Size &in_size) \
00653 { \
00654   int dim_s = clscnv->getSrcDim(); \
00655   Offset offset = clscnv->getOffsetN(); \
00656   Data start = in_idr + offset; \
00657  \
00658   Size inisize_s = iniSize(dim_s); \
00659   Size wpsize_s = sizeof(SRCTYP) * dim_s + inisize_s; \
00660  \
00661   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_2STR: inisize_s=%d, wpsize_s=%d\n", inisize_s, wpsize_s)); \
00662  \
00663   eyedbsm::Status se_status; \
00664   eyedbsm::DbHandle *sedbh = IDB_get_se_DbHandle(db); \
00665  \
00666   int ndim_d = get_top(start, dim_s); \
00667   Oid oid_d; \
00668   unsigned char *pdata_d = 0; \
00669   if (ndim_d) { \
00670     SRCTYP data_s; \
00671     mcp(&data_s, start + inisize_s + (ndim_d - 1) * sizeof(SRCTYP), sizeof(SRCTYP)); \
00672     if (data_s) ndim_d++; \
00673     mcp(&data_s, start + inisize_s + ndim_d, sizeof(SRCTYP)); \
00674     Size inisize_d = iniSize(ndim_d); \
00675     Size wpsize_d = (ndim_d > VARS_SZ ? ndim_d + inisize_d : VARS_TSZ); \
00676     pdata_d = new unsigned char[wpsize_d]; \
00677    \
00678     mcp(pdata_d, start, inisize_d); \
00679     \
00680     Data start_s = start + inisize_s; \
00681     Data start_d = pdata_d + inisize_d; \
00682    \
00683     for (int i = 0; i < ndim_d; i++) {  \
00684       mcp(&data_s, start_s, sizeof(SRCTYP)); \
00685       *start_d++ = (char)data_s; \
00686       start_s += sizeof(SRCTYP); \
00687     } \
00688    \
00689     IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_2STR: ndim_d=%d, wpsize_d=%d, string '%s'\n", ndim_d, wpsize_d, pdata_d + inisize_d)); \
00690      \
00691     if (ndim_d > VARS_SZ) { \
00692       se_status = eyedbsm::objectCreate(sedbh, start, wpsize_d, DSPID, oid_d.getOid()); \
00693       delete [] pdata_d; \
00694       pdata_d = 0; \
00695       if (se_status) \
00696         return Exception::make(IDB_ERROR, eyedbsm::statusGet(se_status)); \
00697      } \
00698    } \
00699   else { \
00700      pdata_d = new unsigned char[VARS_TSZ]; \
00701      memset(pdata_d, 0, VARS_INISZ); \
00702   } \
00703   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("\t\tCNV_2STR: new oid is %s\n", oid_d.toString())); \
00704  \
00705   memmove(start + VARS_OFFSET + VARS_TSZ, \
00706           start + wpsize_s, \
00707           in_size - offset - wpsize_s); \
00708   \
00709   if (pdata_d) { \
00710      memcpy(start + VARS_OFFSET, pdata_d, VARS_TSZ); \
00711      IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("pdata[0] = %d\n", pdata_d[0])); \
00712      delete [] pdata_d; \
00713   } \
00714  \
00715   mcp(start, &ndim_d, sizeof(Size)); \
00716   mcp(start + sizeof(Size), oid_d.getOid(), sizeof(eyedbsm::Oid)); \
00717  \
00718   in_size += VARS_OFFSET + VARS_TSZ - wpsize_s; \
00719   return Success; \
00720 }
00721 
00722 #define CNV_MAKE_2STR_COMPSIZE(CNVTYP, SRCTYP) \
00723 static void \
00724 CNVTYP##_computeSize(ClassConversion *clscnv, Size &cur_size) \
00725 { \
00726   int dim_s = clscnv->getSrcDim(); \
00727   cur_size += VARS_OFFSET + VARS_TSZ - iniSize(dim_s) - dim_s * sizeof(SRCTYP); \
00728 }
00729 
00730 #define CNV_MAKE_2STR(CNVTYP, SRCTYP) \
00731   CNV_MAKE_2STR_CONVERT(CNVTYP, SRCTYP) \
00732   CNV_MAKE_2STR_COMPSIZE(CNVTYP, SRCTYP)
00733 
00734 //
00735 // Macro instantiations
00736 //
00737 
00738 CNV_MAKE(INT16_TO_INT16, eyedblib::int16, eyedblib::int16)
00739 CNV_MAKE(INT16_TO_INT32, eyedblib::int16, eyedblib::int32)
00740 CNV_MAKE(INT16_TO_INT64, eyedblib::int16, eyedblib::int64)
00741 CNV_MAKE(INT16_TO_FLOAT, eyedblib::int16, eyedblib::float64)
00742 CNV_MAKE(INT16_TO_BYTE, eyedblib::int16, eyedblib::uchar)
00743 CNV_MAKE(INT16_TO_CHAR, eyedblib::int16, eyedblib::uchar)
00744 
00745 CNV_MAKE(INT32_TO_INT32, eyedblib::int32, eyedblib::int32)
00746 CNV_MAKE(INT32_TO_INT16, eyedblib::int32, eyedblib::int16)
00747 CNV_MAKE(INT32_TO_INT64, eyedblib::int32, eyedblib::int64)
00748 CNV_MAKE(INT32_TO_FLOAT, eyedblib::int32, eyedblib::float64)
00749 CNV_MAKE(INT32_TO_BYTE, eyedblib::int32, eyedblib::uchar)
00750 CNV_MAKE(INT32_TO_CHAR, eyedblib::int32, eyedblib::uchar)
00751 
00752 CNV_MAKE(INT64_TO_INT64, eyedblib::int64, eyedblib::int64)
00753 CNV_MAKE(INT64_TO_INT16, eyedblib::int64, eyedblib::int16)
00754 CNV_MAKE(INT64_TO_INT32, eyedblib::int64, eyedblib::int32)
00755 CNV_MAKE(INT64_TO_FLOAT, eyedblib::int64, eyedblib::float64)
00756 CNV_MAKE(INT64_TO_BYTE, eyedblib::int64, eyedblib::uchar)
00757 CNV_MAKE(INT64_TO_CHAR, eyedblib::int64, char)
00758 
00759 CNV_MAKE(FLOAT_TO_FLOAT, eyedblib::float64, eyedblib::float64)
00760 CNV_MAKE(FLOAT_TO_INT16, eyedblib::float64, eyedblib::int16)
00761 CNV_MAKE(FLOAT_TO_INT32, eyedblib::float64, eyedblib::int32)
00762 CNV_MAKE(FLOAT_TO_INT64, eyedblib::float64, eyedblib::int64)
00763 CNV_MAKE(FLOAT_TO_BYTE, eyedblib::float64, eyedblib::uchar)
00764 CNV_MAKE(FLOAT_TO_CHAR, eyedblib::float64, char)
00765 
00766 CNV_MAKE(CHAR_TO_CHAR, eyedblib::uchar, eyedblib::uchar)
00767 CNV_MAKE(CHAR_TO_INT16, eyedblib::uchar, eyedblib::int16)
00768 CNV_MAKE(CHAR_TO_INT32, eyedblib::uchar, eyedblib::int32)
00769 CNV_MAKE(CHAR_TO_INT64, eyedblib::uchar, eyedblib::int64)
00770 CNV_MAKE(CHAR_TO_FLOAT, eyedblib::uchar, eyedblib::float64)
00771 CNV_MAKE(CHAR_TO_BYTE, eyedblib::uchar, eyedblib::uchar) // could be nil
00772 
00773 CNV_MAKE_NYI(BYTE_TO_BYTE, eyedblib::uchar, eyedblib::uchar)
00774 CNV_MAKE(BYTE_TO_INT16, eyedblib::uchar, eyedblib::int16)
00775 CNV_MAKE(BYTE_TO_INT32, eyedblib::uchar, eyedblib::int32)
00776 CNV_MAKE(BYTE_TO_INT64, eyedblib::uchar, eyedblib::int64)
00777 CNV_MAKE(BYTE_TO_FLOAT, eyedblib::uchar, eyedblib::float64)
00778 CNV_MAKE(BYTE_TO_CHAR, eyedblib::uchar, eyedblib::uchar) // could be nil
00779 
00780 // ? conversions to enum should be manual ?
00781 CNV_MAKE_NYI(INT16_TO_ENUM, eyedblib::int16, eyedblib::int32)
00782 CNV_MAKE_NYI(INT32_TO_ENUM, eyedblib::int32, eyedblib::int32)
00783 CNV_MAKE_NYI(INT64_TO_ENUM, eyedblib::int64, eyedblib::int32)
00784 CNV_MAKE_NYI(FLOAT_TO_ENUM, float, eyedblib::int32)
00785 CNV_MAKE_NYI(CHAR_TO_ENUM, char, eyedblib::int32)
00786 CNV_MAKE_NYI(BYTE_TO_ENUM, eyedblib::uchar, eyedblib::int32)
00787 
00788 // ? conversions from enum should be manual ?
00789 CNV_MAKE_NYI(ENUM_TO_ENUM, eyedblib::int16, eyedblib::int32)
00790 CNV_MAKE_NYI(ENUM_TO_INT16, eyedblib::int16, eyedblib::int32)
00791 CNV_MAKE_NYI(ENUM_TO_INT32, eyedblib::int16, eyedblib::int32)
00792 CNV_MAKE_NYI(ENUM_TO_INT64, eyedblib::int16, eyedblib::int32)
00793 CNV_MAKE_NYI(ENUM_TO_FLOAT, eyedblib::int16, eyedblib::int32)
00794 CNV_MAKE_NYI(ENUM_TO_CHAR, eyedblib::int16, eyedblib::int32)
00795 CNV_MAKE_NYI(ENUM_TO_BYTE, eyedblib::int16, eyedblib::int32)
00796 
00797 // to string conversions
00798 CNV_MAKE_2STR(CHAR_TO_STRING, eyedblib::uchar)
00799 CNV_MAKE_2STR(INT16_TO_STRING, eyedblib::int16)
00800 CNV_MAKE_2STR(INT32_TO_STRING, eyedblib::int32)
00801 CNV_MAKE_2STR(INT64_TO_STRING, eyedblib::int64)
00802 CNV_MAKE_2STR(FLOAT_TO_STRING, eyedblib::float64)
00803 CNV_MAKE_2STR(BYTE_TO_STRING, eyedblib::uchar)
00804 
00805 // collection conversions should be manual
00806 CNV_MAKE_NYI(SET_TO_BAG, eyedblib::int16, eyedblib::int32)
00807 CNV_MAKE_NYI(SET_TO_ARRAY, eyedblib::int16, eyedblib::int32)
00808 CNV_MAKE_NYI(SET_TO_LIST, eyedblib::int16, eyedblib::int32)
00809 CNV_MAKE_NYI(BAG_TO_SET, eyedblib::int16, eyedblib::int32)
00810 CNV_MAKE_NYI(BAG_TO_ARRAY, eyedblib::int16, eyedblib::int32)
00811 CNV_MAKE_NYI(BAG_TO_LIST, eyedblib::int16, eyedblib::int32)
00812 CNV_MAKE_NYI(ARRAY_TO_BAG, eyedblib::int16, eyedblib::int32)
00813 CNV_MAKE_NYI(ARRAY_TO_SET, eyedblib::int16, eyedblib::int32)
00814 CNV_MAKE_NYI(ARRAY_TO_LIST, eyedblib::int16, eyedblib::int32)
00815 CNV_MAKE_NYI(LIST_TO_BAG, eyedblib::int16, eyedblib::int32)
00816 CNV_MAKE_NYI(LIST_TO_ARRAY, eyedblib::int16, eyedblib::int32)
00817 CNV_MAKE_NYI(LIST_TO_SET, eyedblib::int16, eyedblib::int32)
00818 
00819 //
00820 // CLASS_TO_CLASS conversions
00821 //
00822 
00823 // fixed size arrays: source and destination
00824 
00825 static Status
00826 CLASS_TO_CLASS_convert_1(Database *db, ClassConversion *clscnv,
00827                          ClassConversion::Context *conv_ctx,
00828                          int dim_s, int dim_d,
00829                          Data in_idr, Size &in_size)
00830 {
00831   Size osize = clscnv->getSizeO();
00832   Size nsize = clscnv->getSizeN();
00833   Offset offset = clscnv->getOffsetN();
00834   Data start = in_idr + offset;
00835   Size nxsize = ClassConversion::computeSize(conv_ctx, osize);
00836 
00837   int ndim_d = (dim_d < dim_s ? dim_d : dim_s);
00838   unsigned char **pdata = new unsigned char*[ndim_d];
00839   Data start_s = start;
00840 
00841   Size asize = nxsize + IDB_OBJ_HEAD_SIZE;
00842   Size bsize = osize + IDB_OBJ_HEAD_SIZE;
00843 
00844   for (int i = 0; i < ndim_d; i++) {
00845     pdata[i] = new unsigned char[asize];
00846     memcpy(pdata[i] + IDB_OBJ_HEAD_SIZE, start_s, osize);
00847     Status s = ClassConversion::convert(db, conv_ctx, pdata[i], bsize);
00848     if (s) {
00849       for (int j = 0; j < i; j++)
00850         delete [] pdata[j];
00851       delete [] pdata;
00852       return s;
00853     }
00854     start_s += osize;
00855   }
00856 
00857   memmove(start + dim_d * nsize,
00858           start + dim_s * osize,
00859           in_size - dim_s * osize - offset);
00860 
00861   Data start_d = start;
00862   for (int i = 0; i < ndim_d; i++) {
00863     memcpy(start_d, pdata[i] + IDB_OBJ_HEAD_SIZE, nsize);
00864     start_d += nsize;
00865     delete [] pdata[i];
00866   }
00867 
00868   delete [] pdata;
00869 
00870   for (int i = dim_s; i < dim_d; i++) {
00871     memset(start_d, 0, nsize);
00872     start_d += nsize;
00873   }
00874 
00875   in_size += dim_d * nsize - dim_s * osize;
00876   return Success;
00877 }
00878 
00879 // variable size arrays: source and destination
00880 
00881 static Status
00882 CLASS_TO_CLASS_convert_2(Database *db, ClassConversion *clscnv,
00883                          ClassConversion::Context *conv_ctx,
00884                          int dim_s, int dim_d,
00885                          Data in_idr, Size &in_size)
00886 {
00887   Size osize = clscnv->getSizeO();
00888   Size nsize = clscnv->getSizeN();
00889   Offset offset = clscnv->getOffsetN();
00890   Data start = in_idr + offset;
00891   Size nxsize = ClassConversion::computeSize(conv_ctx, osize);
00892 
00893   Size count;
00894   mcp(&count, start, sizeof(count));
00895   count = CLEAN_SIZE(count);
00896 
00897   if (!count)
00898     return Success;
00899 
00900   Size wpsize_s = osize * count * (-dim_s);
00901   Oid oid_s;
00902   mcp(&oid_s, start + sizeof(Size), sizeof(oid_s));
00903 
00904   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("convert_2 count=%d\n", count));
00905   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("convert_2 wpsize_s=%d\n", wpsize_s));
00906   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("convert_2 oid_s=%s\n", oid_s.toString()));
00907 
00908   unsigned char *pdata_s = new unsigned char[wpsize_s];
00909   eyedbsm::Status se_status;
00910   eyedbsm::DbHandle *sedbh = IDB_get_se_DbHandle(db);
00911   se_status = eyedbsm::objectRead(sedbh, 0, wpsize_s, pdata_s, eyedbsm::DefaultLock, 0, 0,
00912                             oid_s.getOid());
00913   if (se_status) {
00914     delete[] pdata_s;
00915     return Exception::make(IDB_ERROR, eyedbsm::statusGet(se_status));
00916   } 
00917 
00918   int ndim_d = count;
00919   unsigned char **pdata = new unsigned char*[ndim_d];
00920   Data start_s = pdata_s;
00921 
00922   Size asize = nxsize + IDB_OBJ_HEAD_SIZE;
00923   Size bsize = osize + IDB_OBJ_HEAD_SIZE;
00924 
00925   for (int i = 0; i < ndim_d; i++) {
00926     pdata[i] = new unsigned char[asize];
00927     memcpy(pdata[i] + IDB_OBJ_HEAD_SIZE, start_s , osize);
00928     Status s = ClassConversion::convert(db, conv_ctx, pdata[i], bsize);
00929     if (s) {
00930       for (int j = 0; j < i; j++)
00931         delete [] pdata[j];
00932       delete [] pdata;
00933       delete[] pdata_s;
00934       return s;
00935     }
00936     start_s += osize;
00937   }
00938 
00939   Size wpsize_d = nsize * count * (-dim_d);
00940   unsigned char *pdata_d = new unsigned char[wpsize_d];
00941 
00942   Data start_d = pdata_d;
00943   for (int i = 0; i < ndim_d; i++) {
00944     memcpy(start_d, pdata[i] + IDB_OBJ_HEAD_SIZE, nsize);
00945     start_d += nsize;
00946     delete [] pdata[i];
00947   }
00948 
00949   delete[] pdata_s;
00950   delete [] pdata;
00951 
00952   for (int i = dim_s; i < dim_d; i++) {
00953     memset(start_d, 0, nsize);
00954     start_d += nsize;
00955   }
00956 
00957   if (!db->writeBackConvertedObjects()) {
00958     delete[] pdata_d;
00959     return Exception::make(IDB_ERROR, wrerr);
00960   }
00961 
00962   se_status = eyedbsm::objectSizeModify(sedbh, wpsize_d, eyedbsm::True, oid_s.getOid());
00963   if (se_status) {
00964     delete[] pdata_d;
00965     return Exception::make(IDB_ERROR, eyedbsm::statusGet(se_status));
00966   }
00967 
00968   se_status = eyedbsm::objectWrite(sedbh, 0, wpsize_d, pdata_d, oid_s.getOid());
00969   delete[] pdata_d;
00970   if (se_status)
00971     return Exception::make(IDB_ERROR, eyedbsm::statusGet(se_status));
00972 
00973   return Success;
00974 }
00975 
00976 // fixed size source array and variable size destination array
00977 
00978 static Status
00979 CLASS_TO_CLASS_convert_3(Database *db, ClassConversion *clscnv,
00980                          ClassConversion::Context *conv_ctx,
00981                          int dim_s, int dim_d,
00982                          Data in_idr, Size &in_size)
00983 {
00984   Size osize = clscnv->getSizeO();
00985   Size nsize = clscnv->getSizeN();
00986   Offset offset = clscnv->getOffsetN();
00987   Data start = in_idr + offset;
00988   Size nxsize = ClassConversion::computeSize(conv_ctx, osize);
00989 
00990   unsigned char **pdata = new unsigned char*[dim_s];
00991   Data start_s = start;
00992 
00993   Size asize = nxsize + IDB_OBJ_HEAD_SIZE;
00994   Size bsize = osize + IDB_OBJ_HEAD_SIZE;
00995   Size wpsize_s = osize * dim_s;
00996 
00997   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("convert_3 offset=%d\n", offset));
00998   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("dim_s=%d\n", dim_s));
00999   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("dim_d=%d\n", dim_d));
01000   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("osize=%d\n", osize));
01001   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("nsize=%d\n", nsize));
01002   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("nxsize=%d\n", nxsize));
01003   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("asize=%d\n", asize));
01004   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("bsize=%d\n", bsize));
01005 
01006   for (int i = 0; i < dim_s; i++) {
01007     pdata[i] = new unsigned char[asize];
01008     memcpy(pdata[i] + IDB_OBJ_HEAD_SIZE, start_s, osize);
01009     Status s = ClassConversion::convert(db, conv_ctx, pdata[i], bsize);
01010     if (s) {
01011       for (int j = 0; j < i; j++)
01012         delete [] pdata[j];
01013       delete [] pdata;
01014       return s;
01015     }
01016     start_s += osize;
01017   }
01018 
01019   Size wpsize_d = nsize * dim_s;
01020   unsigned char *pdata_d = new unsigned char[wpsize_d];
01021   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("wpsize_d %d %d\n", wpsize_s, wpsize_d));
01022 
01023   Data start_d = pdata_d;
01024   for (int i = 0; i < dim_s; i++) {
01025     memcpy(start_d, pdata[i] + IDB_OBJ_HEAD_SIZE, nsize);
01026     start_d += nsize;
01027     delete [] pdata[i];
01028   }
01029 
01030   delete [] pdata;
01031 
01032   eyedbsm::Status se_status;
01033   eyedbsm::DbHandle *sedbh = IDB_get_se_DbHandle(db);
01034   Oid oid_d;
01035   se_status = eyedbsm::objectCreate(sedbh, pdata_d, wpsize_d, DSPID,
01036                               oid_d.getOid());
01037   delete[] pdata_d;
01038   if (se_status)
01039     return Exception::make(IDB_ERROR, eyedbsm::statusGet(se_status));
01040 
01041   memmove(start + sizeof(Size) + sizeof(Oid),
01042           start + wpsize_s,
01043           in_size - offset - wpsize_s);
01044 
01045   mcp(start, &dim_s, sizeof(Size));
01046   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("oid_d = %s\n", oid_d.toString()));
01047   mcp(start + sizeof(Size), oid_d.getOid(), sizeof(eyedbsm::Oid));
01048 
01049   in_size += sizeof(Size) + sizeof(Oid) - dim_s * osize;
01050   return Success;
01051 }
01052 
01053 static Status
01054 CLASS_TO_CLASS_convert(Database *db, ClassConversion *clscnv, Data in_idr, Size &in_size)
01055 {
01056   const Class *cls = 0;
01057   ClassConversion::Context *conv_ctx = 0;
01058   Status s = ClassConversion::getClass_(db, clscnv->getRoidO(), cls,
01059                                         conv_ctx, True);
01060   if (s) return s;
01061 
01062   IDB_LOG(IDB_LOG_SCHEMA_EVOLVE, ("CLASS_TO_CLASS = %s\n",
01063                                   (cls ? cls->getName() : "<unknown>")));
01064 
01065   if (!conv_ctx)
01066     return Exception::make(IDB_ERROR, "internal fatal error: cannot find "
01067                               "conversion method for class %s",
01068                               clscnv->getRoidO().toString());
01069 
01070   int dim_s = clscnv->getSrcDim();
01071   int dim_d = clscnv->getDestDim();
01072 
01073   if (dim_s > 0 && dim_d > 0)
01074     return CLASS_TO_CLASS_convert_1(db, clscnv, conv_ctx, dim_s, dim_d,
01075                                     in_idr, in_size);
01076 
01077   if (dim_s < 0 && dim_d < 0)
01078     return CLASS_TO_CLASS_convert_2(db, clscnv, conv_ctx, dim_s, dim_d,
01079                                     in_idr, in_size);
01080 
01081   if (dim_s > 0 && dim_d < 0)
01082     return CLASS_TO_CLASS_convert_3(db, clscnv, conv_ctx, dim_s, dim_d,
01083                                     in_idr, in_size);
01084 
01085   return Exception::make(IDB_ERROR, "CLASS_TO_CLASS conversion: "
01086                             "variable size to non variable size is not "
01087                             "supported");
01088 }
01089 
01090 static void
01091 CLASS_TO_CLASS_computeSize(ClassConversion *clscnv, Size &cur_size)
01092 {
01093   int dim_s = clscnv->getSrcDim();
01094   int dim_d = clscnv->getDestDim();
01095 
01096   if (dim_s > 0 && dim_d > 0)
01097     cur_size += dim_d * clscnv->getSizeN() - dim_s * clscnv->getSizeO();
01098   else if (dim_s < 0 && dim_d < 0)
01099     ;
01100   else if (dim_s > 0 && dim_d < 0)
01101     cur_size += sizeof(Size) + sizeof(Oid) - dim_s * clscnv->getSizeO();
01102 }
01103 
01104 // should be manual
01105 CNV_MAKE_NYI(USER_CNV, eyedblib::int16, eyedblib::int32)
01106 
01107 static Status
01108 NIL_CNV_convert(Database *db, ClassConversion *clscnv, Data in_idr,
01109                 Size &in_size)
01110 {
01111   return Success;
01112 }
01113 
01114 static void
01115 NIL_CNV_computeSize(ClassConversion *clscnv, Size &cur_size)
01116 {
01117 }
01118 
01119 //CNV_MAKE_NYI(NIL_CNV, eyedblib::int16, eyedblib::int32)
01120 
01121 void
01122 ClassConversion::init()
01123 {
01124   static Bool init = False;
01125 
01126   if (init) return;
01127 
01128   cnv_convert[INT16_TO_INT16] = INT16_TO_INT16_convert;
01129   cnv_convert[INT16_TO_INT32] = INT16_TO_INT32_convert;
01130   cnv_convert[INT16_TO_INT64] = INT16_TO_INT64_convert;
01131   cnv_convert[INT16_TO_FLOAT] = INT16_TO_FLOAT_convert;
01132   cnv_convert[INT16_TO_BYTE] = INT16_TO_BYTE_convert;
01133   cnv_convert[INT16_TO_CHAR] = INT16_TO_CHAR_convert;
01134   cnv_convert[INT16_TO_ENUM] = INT16_TO_ENUM_convert;
01135 
01136   cnv_convert[INT32_TO_INT32] = INT32_TO_INT32_convert;
01137   cnv_convert[INT32_TO_INT16] = INT32_TO_INT16_convert;
01138   cnv_convert[INT32_TO_INT64] = INT32_TO_INT64_convert;
01139   cnv_convert[INT32_TO_FLOAT] = INT32_TO_FLOAT_convert;
01140   cnv_convert[INT32_TO_BYTE] = INT32_TO_BYTE_convert;
01141   cnv_convert[INT32_TO_CHAR] = INT32_TO_CHAR_convert;
01142   cnv_convert[INT32_TO_ENUM] = INT32_TO_ENUM_convert;
01143 
01144   cnv_convert[INT64_TO_INT64] = INT64_TO_INT64_convert;
01145   cnv_convert[INT64_TO_INT16] = INT64_TO_INT16_convert;
01146   cnv_convert[INT64_TO_INT32] = INT64_TO_INT32_convert;
01147   cnv_convert[INT64_TO_FLOAT] = INT64_TO_FLOAT_convert;
01148   cnv_convert[INT64_TO_BYTE] = INT64_TO_BYTE_convert;
01149   cnv_convert[INT64_TO_CHAR] = INT64_TO_CHAR_convert;
01150   cnv_convert[INT64_TO_ENUM] = INT64_TO_ENUM_convert;
01151 
01152   cnv_convert[FLOAT_TO_FLOAT] = FLOAT_TO_FLOAT_convert;
01153   cnv_convert[FLOAT_TO_INT16] = FLOAT_TO_INT16_convert;
01154   cnv_convert[FLOAT_TO_INT32] = FLOAT_TO_INT32_convert;
01155   cnv_convert[FLOAT_TO_INT64] = FLOAT_TO_INT64_convert;
01156   cnv_convert[FLOAT_TO_BYTE] = FLOAT_TO_BYTE_convert;
01157   cnv_convert[FLOAT_TO_CHAR] = FLOAT_TO_CHAR_convert;
01158   cnv_convert[FLOAT_TO_ENUM] = FLOAT_TO_ENUM_convert;
01159 
01160   cnv_convert[CHAR_TO_CHAR] = CHAR_TO_CHAR_convert;
01161   cnv_convert[CHAR_TO_INT16] = CHAR_TO_INT16_convert;
01162   cnv_convert[CHAR_TO_INT32] = CHAR_TO_INT32_convert;
01163   cnv_convert[CHAR_TO_INT64] = CHAR_TO_INT64_convert;
01164   cnv_convert[CHAR_TO_FLOAT] = CHAR_TO_FLOAT_convert;
01165   cnv_convert[CHAR_TO_BYTE] = CHAR_TO_BYTE_convert;
01166   cnv_convert[CHAR_TO_ENUM] = CHAR_TO_ENUM_convert;
01167 
01168   cnv_convert[BYTE_TO_BYTE] = BYTE_TO_BYTE_convert;
01169   cnv_convert[BYTE_TO_INT16] = BYTE_TO_INT16_convert;
01170   cnv_convert[BYTE_TO_INT32] = BYTE_TO_INT32_convert;
01171   cnv_convert[BYTE_TO_INT64] = BYTE_TO_INT64_convert;
01172   cnv_convert[BYTE_TO_FLOAT] = BYTE_TO_FLOAT_convert;
01173   cnv_convert[BYTE_TO_CHAR] = BYTE_TO_CHAR_convert;
01174   cnv_convert[BYTE_TO_ENUM] = BYTE_TO_ENUM_convert;
01175 
01176   cnv_convert[ENUM_TO_ENUM] = ENUM_TO_ENUM_convert;
01177   cnv_convert[ENUM_TO_INT16] = ENUM_TO_INT16_convert;
01178   cnv_convert[ENUM_TO_INT32] = ENUM_TO_INT32_convert;
01179   cnv_convert[ENUM_TO_INT64] = ENUM_TO_INT64_convert;
01180   cnv_convert[ENUM_TO_FLOAT] = ENUM_TO_FLOAT_convert;
01181   cnv_convert[ENUM_TO_CHAR] = ENUM_TO_CHAR_convert;
01182   cnv_convert[ENUM_TO_BYTE] = ENUM_TO_BYTE_convert;
01183 
01184   cnv_convert[CHAR_TO_STRING] = CHAR_TO_STRING_convert;
01185   cnv_convert[INT16_TO_STRING] = INT16_TO_STRING_convert;
01186   cnv_convert[INT32_TO_STRING] = INT32_TO_STRING_convert;
01187   cnv_convert[INT64_TO_STRING] = INT64_TO_STRING_convert;
01188   cnv_convert[FLOAT_TO_STRING] = FLOAT_TO_STRING_convert;
01189   cnv_convert[BYTE_TO_STRING] = BYTE_TO_STRING_convert;
01190 
01191   cnv_convert[SET_TO_BAG] = SET_TO_BAG_convert;
01192   cnv_convert[SET_TO_ARRAY] = SET_TO_ARRAY_convert;
01193   cnv_convert[SET_TO_LIST] = SET_TO_LIST_convert;
01194   cnv_convert[BAG_TO_SET] = BAG_TO_SET_convert;
01195   cnv_convert[BAG_TO_ARRAY] = BAG_TO_ARRAY_convert;
01196   cnv_convert[BAG_TO_LIST] = BAG_TO_LIST_convert;
01197   cnv_convert[ARRAY_TO_BAG] = ARRAY_TO_BAG_convert;
01198   cnv_convert[ARRAY_TO_SET] = ARRAY_TO_SET_convert;
01199   cnv_convert[ARRAY_TO_LIST] = ARRAY_TO_LIST_convert;
01200   cnv_convert[LIST_TO_BAG] = LIST_TO_BAG_convert;
01201   cnv_convert[LIST_TO_ARRAY] = LIST_TO_ARRAY_convert;
01202   cnv_convert[LIST_TO_SET] = LIST_TO_SET_convert;
01203 
01204   cnv_convert[CLASS_TO_CLASS] = CLASS_TO_CLASS_convert;
01205 
01206   cnv_convert[USER_CNV] = USER_CNV_convert;
01207   cnv_convert[NIL_CNV] = NIL_CNV_convert;
01208 
01209   cnv_computeSize[INT16_TO_INT16] = INT16_TO_INT16_computeSize;
01210   cnv_computeSize[INT16_TO_INT32] = INT16_TO_INT32_computeSize;
01211   cnv_computeSize[INT16_TO_INT64] = INT16_TO_INT64_computeSize;
01212   cnv_computeSize[INT16_TO_FLOAT] = INT16_TO_FLOAT_computeSize;
01213   cnv_computeSize[INT16_TO_BYTE] = INT16_TO_BYTE_computeSize;
01214   cnv_computeSize[INT16_TO_CHAR] = INT16_TO_CHAR_computeSize;
01215   cnv_computeSize[INT16_TO_ENUM] = INT16_TO_ENUM_computeSize;
01216 
01217   cnv_computeSize[INT32_TO_INT32] = INT32_TO_INT32_computeSize;
01218   cnv_computeSize[INT32_TO_INT16] = INT32_TO_INT16_computeSize;
01219   cnv_computeSize[INT32_TO_INT64] = INT32_TO_INT64_computeSize;
01220   cnv_computeSize[INT32_TO_FLOAT] = INT32_TO_FLOAT_computeSize;
01221   cnv_computeSize[INT32_TO_BYTE] = INT32_TO_BYTE_computeSize;
01222   cnv_computeSize[INT32_TO_CHAR] = INT32_TO_CHAR_computeSize;
01223   cnv_computeSize[INT32_TO_ENUM] = INT32_TO_ENUM_computeSize;
01224 
01225   cnv_computeSize[INT64_TO_INT64] = INT64_TO_INT64_computeSize;
01226   cnv_computeSize[INT64_TO_INT16] = INT64_TO_INT16_computeSize;
01227   cnv_computeSize[INT64_TO_INT32] = INT64_TO_INT32_computeSize;
01228   cnv_computeSize[INT64_TO_FLOAT] = INT64_TO_FLOAT_computeSize;
01229   cnv_computeSize[INT64_TO_BYTE] = INT64_TO_BYTE_computeSize;
01230   cnv_computeSize[INT64_TO_CHAR] = INT64_TO_CHAR_computeSize;
01231   cnv_computeSize[INT64_TO_ENUM] = INT64_TO_ENUM_computeSize;
01232 
01233   cnv_computeSize[FLOAT_TO_FLOAT] = FLOAT_TO_FLOAT_computeSize;
01234   cnv_computeSize[FLOAT_TO_INT16] = FLOAT_TO_INT16_computeSize;
01235   cnv_computeSize[FLOAT_TO_INT32] = FLOAT_TO_INT32_computeSize;
01236   cnv_computeSize[FLOAT_TO_INT64] = FLOAT_TO_INT64_computeSize;
01237   cnv_computeSize[FLOAT_TO_BYTE] = FLOAT_TO_BYTE_computeSize;
01238   cnv_computeSize[FLOAT_TO_CHAR] = FLOAT_TO_CHAR_computeSize;
01239   cnv_computeSize[FLOAT_TO_ENUM] = FLOAT_TO_ENUM_computeSize;
01240 
01241   cnv_computeSize[CHAR_TO_CHAR] = CHAR_TO_CHAR_computeSize;
01242   cnv_computeSize[CHAR_TO_INT16] = CHAR_TO_INT16_computeSize;
01243   cnv_computeSize[CHAR_TO_INT32] = CHAR_TO_INT32_computeSize;
01244   cnv_computeSize[CHAR_TO_INT64] = CHAR_TO_INT64_computeSize;
01245   cnv_computeSize[CHAR_TO_FLOAT] = CHAR_TO_FLOAT_computeSize;
01246   cnv_computeSize[CHAR_TO_BYTE] = CHAR_TO_BYTE_computeSize;
01247   cnv_computeSize[CHAR_TO_ENUM] = CHAR_TO_ENUM_computeSize;
01248 
01249   cnv_computeSize[BYTE_TO_BYTE] = BYTE_TO_BYTE_computeSize;
01250   cnv_computeSize[BYTE_TO_INT16] = BYTE_TO_INT16_computeSize;
01251   cnv_computeSize[BYTE_TO_INT32] = BYTE_TO_INT32_computeSize;
01252   cnv_computeSize[BYTE_TO_INT64] = BYTE_TO_INT64_computeSize;
01253   cnv_computeSize[BYTE_TO_FLOAT] = BYTE_TO_FLOAT_computeSize;
01254   cnv_computeSize[BYTE_TO_CHAR] = BYTE_TO_CHAR_computeSize;
01255   cnv_computeSize[BYTE_TO_ENUM] = BYTE_TO_ENUM_computeSize;
01256 
01257   cnv_computeSize[ENUM_TO_ENUM] = ENUM_TO_ENUM_computeSize;
01258   cnv_computeSize[ENUM_TO_INT16] = ENUM_TO_INT16_computeSize;
01259   cnv_computeSize[ENUM_TO_INT32] = ENUM_TO_INT32_computeSize;
01260   cnv_computeSize[ENUM_TO_INT64] = ENUM_TO_INT64_computeSize;
01261   cnv_computeSize[ENUM_TO_FLOAT] = ENUM_TO_FLOAT_computeSize;
01262   cnv_computeSize[ENUM_TO_CHAR] = ENUM_TO_CHAR_computeSize;
01263   cnv_computeSize[ENUM_TO_BYTE] = ENUM_TO_BYTE_computeSize;
01264 
01265   cnv_computeSize[CHAR_TO_STRING] = CHAR_TO_STRING_computeSize;
01266   cnv_computeSize[INT16_TO_STRING] = INT16_TO_STRING_computeSize;
01267   cnv_computeSize[INT32_TO_STRING] = INT32_TO_STRING_computeSize;
01268   cnv_computeSize[INT64_TO_STRING] = INT64_TO_STRING_computeSize;
01269   cnv_computeSize[FLOAT_TO_STRING] = FLOAT_TO_STRING_computeSize;
01270   cnv_computeSize[BYTE_TO_STRING] = BYTE_TO_STRING_computeSize;
01271 
01272   cnv_computeSize[SET_TO_BAG] = SET_TO_BAG_computeSize;
01273   cnv_computeSize[SET_TO_ARRAY] = SET_TO_ARRAY_computeSize;
01274   cnv_computeSize[SET_TO_LIST] = SET_TO_LIST_computeSize;
01275   cnv_computeSize[BAG_TO_SET] = BAG_TO_SET_computeSize;
01276   cnv_computeSize[BAG_TO_ARRAY] = BAG_TO_ARRAY_computeSize;
01277   cnv_computeSize[BAG_TO_LIST] = BAG_TO_LIST_computeSize;
01278   cnv_computeSize[ARRAY_TO_BAG] = ARRAY_TO_BAG_computeSize;
01279   cnv_computeSize[ARRAY_TO_SET] = ARRAY_TO_SET_computeSize;
01280   cnv_computeSize[ARRAY_TO_LIST] = ARRAY_TO_LIST_computeSize;
01281   cnv_computeSize[LIST_TO_BAG] = LIST_TO_BAG_computeSize;
01282   cnv_computeSize[LIST_TO_ARRAY] = LIST_TO_ARRAY_computeSize;
01283   cnv_computeSize[LIST_TO_SET] = LIST_TO_SET_computeSize;
01284 
01285   cnv_computeSize[CLASS_TO_CLASS] = CLASS_TO_CLASS_computeSize;
01286 
01287   cnv_computeSize[USER_CNV] = USER_CNV_computeSize;
01288   cnv_computeSize[NIL_CNV] = NIL_CNV_computeSize;
01289 
01290   init = True;
01291 }
01292 
01293 void
01294 ClassConversion::_release()
01295 {
01296 }
01297 }

Generated on Mon Dec 22 18:15:51 2008 for eyedb by  doxygen 1.5.3