Commit d8258f10 authored by claes's avatar claes

Cast classes in class dependency, and class version dependent on attrobjects

parent face5d98
...@@ -17,6 +17,7 @@ This module contains functions to create database snapshot files. */ ...@@ -17,6 +17,7 @@ This module contains functions to create database snapshot files. */
#include "pwr_class.h" #include "pwr_class.h"
#include "co_cdh.h" #include "co_cdh.h"
#include "co_dcli.h" #include "co_dcli.h"
#include "co_time.h"
#include "co_tree.h" #include "co_tree.h"
#include "co_pdr.h" #include "co_pdr.h"
#include "co_dbs.h" #include "co_dbs.h"
...@@ -25,6 +26,8 @@ This module contains functions to create database snapshot files. */ ...@@ -25,6 +26,8 @@ This module contains functions to create database snapshot files. */
#include "wb_vrep.h" #include "wb_vrep.h"
#include "wb_mvrep.h" #include "wb_mvrep.h"
#include "wb_merep.h" #include "wb_merep.h"
#include "wb_volume.h"
#include "wb_attribute.h"
static int comp_dbs_name(tree_sTable *tp, tree_sNode *x, tree_sNode *y); static int comp_dbs_name(tree_sTable *tp, tree_sNode *x, tree_sNode *y);
...@@ -70,12 +73,12 @@ wb_dbs::~wb_dbs() ...@@ -70,12 +73,12 @@ wb_dbs::~wb_dbs()
{ {
pwr_tStatus sts; pwr_tStatus sts;
printf("-- m_nObjects: %d\n", m_nObjects); //printf("-- m_nObjects: %d\n", m_nObjects);
printf("-- m_nTreeObjects: %d\n", m_nTreeObjects); //printf("-- m_nTreeObjects: %d\n", m_nTreeObjects);
printf("-- m_nClassObjects: %d\n", m_nClassObjects); //printf("-- m_nClassObjects: %d\n", m_nClassObjects);
printf("-- m_nNameObjects: %d\n", m_nNameObjects); //printf("-- m_nNameObjects: %d\n", m_nNameObjects);
printf("-- m_nRbodyObjects: %d\n", m_nRbodyObjects); //printf("-- m_nRbodyObjects: %d\n", m_nRbodyObjects);
printf("-- m_nDbodyObjects: %d\n", m_nDbodyObjects); //printf("-- m_nDbodyObjects: %d\n", m_nDbodyObjects);
tree_DeleteTable(&sts, m_oid_th); tree_DeleteTable(&sts, m_oid_th);
tree_DeleteTable(&sts, m_name_th); tree_DeleteTable(&sts, m_name_th);
...@@ -293,6 +296,15 @@ bool wb_dbs::importHead(pwr_tOid oid, pwr_tCid cid, pwr_tOid poid, ...@@ -293,6 +296,15 @@ bool wb_dbs::importHead(pwr_tOid oid, pwr_tCid cid, pwr_tOid poid,
oep->dbody.size = dbs_dAlign(oep->o.dbody.size); oep->dbody.size = dbs_dAlign(oep->o.dbody.size);
} }
if ( cid == pwr_eClass_ClassDef) {
// Version is dependent of attribute objects
m_v->merep()->classVersion(&sts, cdh_ClassObjidToId(oid), &oep->o.time);
char buf[40];
time_AtoAscii( &oep->o.time, time_eFormat_DateAndTime, buf, sizeof(buf));
printf( "Class version: %s %s\n", name, buf);
}
return true; return true;
} }
...@@ -317,7 +329,7 @@ wb_dbs::createFile() ...@@ -317,7 +329,7 @@ wb_dbs::createFile()
pwr_tStatus sts; pwr_tStatus sts;
int size; int size;
printf("\n-- Working with load file volume '%s'...\n", m_v->name()); //printf("\n-- Working with load file volume '%s'...\n", m_v->name());
/*{ /*{
unsigned int i; unsigned int i;
...@@ -328,7 +340,7 @@ wb_dbs::createFile() ...@@ -328,7 +340,7 @@ wb_dbs::createFile()
} }
}*/ }*/
printf("-- Open file...\n"); //printf("-- Open file...\n");
sts = openFile(); sts = openFile();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
...@@ -341,78 +353,78 @@ wb_dbs::createFile() ...@@ -341,78 +353,78 @@ wb_dbs::createFile()
m_sect[dbs_eSect_volume].size = dbs_dAlign(sizeof(dbs_sVolume)); m_sect[dbs_eSect_volume].size = dbs_dAlign(sizeof(dbs_sVolume));
m_sect[dbs_eSect_volume].offset = size; m_sect[dbs_eSect_volume].offset = size;
printf("-- Writing volume section...\n"); //printf("-- Writing volume section...\n");
sts = writeSectVolume(); sts = writeSectVolume();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
size += m_sect[dbs_eSect_volume].size; size += m_sect[dbs_eSect_volume].size;
m_sect[dbs_eSect_volref].offset = size; m_sect[dbs_eSect_volref].offset = size;
printf("-- Preparing volref section...\n"); //printf("-- Preparing volref section...\n");
sts = prepareSectVolref(); sts = prepareSectVolref();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
size += m_sect[dbs_eSect_volref].size; size += m_sect[dbs_eSect_volref].size;
m_sect[dbs_eSect_oid].offset = size; m_sect[dbs_eSect_oid].offset = size;
printf("-- Writing oid section...\n"); //printf("-- Writing oid section...\n");
sts = writeSectOid(); sts = writeSectOid();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
size += m_sect[dbs_eSect_oid].size; size += m_sect[dbs_eSect_oid].size;
m_sect[dbs_eSect_rbody].offset = size; m_sect[dbs_eSect_rbody].offset = size;
printf("-- Writing rbody section...\n"); //printf("-- Writing rbody section...\n");
sts = writeSectRbody(); sts = writeSectRbody();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
size += m_sect[dbs_eSect_rbody].size; size += m_sect[dbs_eSect_rbody].size;
m_sect[dbs_eSect_dbody].offset = size; m_sect[dbs_eSect_dbody].offset = size;
printf("-- Writing dbody section...\n"); //printf("-- Writing dbody section...\n");
sts = writeSectDbody(); sts = writeSectDbody();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
size += m_sect[dbs_eSect_dbody].size; size += m_sect[dbs_eSect_dbody].size;
m_sect[dbs_eSect_object].offset = size; m_sect[dbs_eSect_object].offset = size;
printf("-- Writing object section...\n"); //printf("-- Writing object section...\n");
sts = writeSectObject(); sts = writeSectObject();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
size += m_sect[dbs_eSect_object].size; size += m_sect[dbs_eSect_object].size;
m_sect[dbs_eSect_name].offset = size; m_sect[dbs_eSect_name].offset = size;
printf("-- Writing name section...\n"); //printf("-- Writing name section...\n");
sts = writeSectName(); sts = writeSectName();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
size += m_sect[dbs_eSect_name].size; size += m_sect[dbs_eSect_name].size;
m_sect[dbs_eSect_class].offset = size; m_sect[dbs_eSect_class].offset = size;
printf("-- Writing class section...\n"); //printf("-- Writing class section...\n");
sts = writeSectClass(); sts = writeSectClass();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
size += m_sect[dbs_eSect_class].size; size += m_sect[dbs_eSect_class].size;
printf("-- Writing directory section...\n"); //printf("-- Writing directory section...\n");
sts = writeSectDirectory(); sts = writeSectDirectory();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
printf("-- Writing file section...\n"); //printf("-- Writing file section...\n");
sts = writeSectFile(size); sts = writeSectFile(size);
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
printf("-- Writing volref section...\n"); //printf("-- Writing volref section...\n");
sts = writeSectVolref(size); sts = writeSectVolref(size);
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
printf("-- Writing volref volumes...\n"); //printf("-- Writing volref volumes...\n");
sts = writeReferencedVolumes(); sts = writeReferencedVolumes();
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
printf("-- Close file...\n"); //printf("-- Close file...\n");
sts = closeFile(0); sts = closeFile(0);
if (EVEN(sts)) goto error_handler; if (EVEN(sts)) goto error_handler;
...@@ -447,8 +459,8 @@ wb_dbs::openFile() ...@@ -447,8 +459,8 @@ wb_dbs::openFile()
return LDH__FILEOPEN; return LDH__FILEOPEN;
} }
fn = dcli_fgetname(m_fp, m_fileName, m_fileName); fn = dcli_fgetname(m_fp, m_fileName, m_fileName);
if (fn != NULL) //if (fn != NULL)
printf("-- Opened load file: %s\n", m_fileName); // printf("-- Opened load file: %s\n", m_fileName);
if ((ret = stat(m_fileName, &sb)) != 0) { if ((ret = stat(m_fileName, &sb)) != 0) {
sts = errno_GetStatus(); sts = errno_GetStatus();
...@@ -456,9 +468,9 @@ wb_dbs::openFile() ...@@ -456,9 +468,9 @@ wb_dbs::openFile()
return sts; return sts;
} }
printf("st_atime...: %ld\n", sb.st_atime); //printf("st_atime...: %ld\n", sb.st_atime);
printf("st_mtime...: %ld\n", sb.st_mtime); //printf("st_mtime...: %ld\n", sb.st_mtime);
printf("st_ctime...: %ld\n", sb.st_ctime); //printf("st_ctime...: %ld\n", sb.st_ctime);
return LDH__SUCCESS; return LDH__SUCCESS;
} }
...@@ -483,17 +495,17 @@ wb_dbs::writeSectFile(size_t size) ...@@ -483,17 +495,17 @@ wb_dbs::writeSectFile(size_t size)
strcpy(fp->userName, ""); strcpy(fp->userName, "");
strcpy(fp->comment, ""); strcpy(fp->comment, "");
printf("format.......: %d\n", fp->format.m); //printf("format.......: %d\n", fp->format.m);
printf("cookie.......: %d\n", fp->cookie); //printf("cookie.......: %d\n", fp->cookie);
printf("size.........: %d\n", fp->size); //printf("size.........: %d\n", fp->size);
printf("offset.......: %d\n", fp->offset); //printf("offset.......: %d\n", fp->offset);
printf("formatVersion: %d\n", fp->formatVersion); //printf("formatVersion: %d\n", fp->formatVersion);
printf("version......: %d\n", fp->version); //printf("version......: %d\n", fp->version);
printf("sectVersion..: %d\n", fp->sectVersion); //printf("sectVersion..: %d\n", fp->sectVersion);
printf("pwrVersion...: %d\n", fp->pwrVersion); //printf("pwrVersion...: %d\n", fp->pwrVersion);
printf("time.........: %ld\n", fp->time.tv_sec); //printf("time.........: %ld\n", fp->time.tv_sec);
printf("fileType.....: %d\n", fp->fileType); //printf("fileType.....: %d\n", fp->fileType);
printf("userName.....: %s\n", fp->userName); //printf("userName.....: %s\n", fp->userName);
pdrmem_create(&pdrs, (char *) fp, sizeof(*fp), PDR_DECODE, fp->format, fp->format); pdrmem_create(&pdrs, (char *) fp, sizeof(*fp), PDR_DECODE, fp->format, fp->format);
if (!pdr_dbs_sFile(&pdrs, fp)) if (!pdr_dbs_sFile(&pdrs, fp))
...@@ -560,7 +572,7 @@ pwr_tStatus ...@@ -560,7 +572,7 @@ pwr_tStatus
wb_dbs::writeSectVolume() wb_dbs::writeSectVolume()
{ {
char v[dbs_dAlign(sizeof(dbs_sVolume))]; char v[dbs_dAlign(sizeof(dbs_sVolume))];
dbs_sVolume *vp = (dbs_sVolume *)v; //dbs_sVolume *vp = (dbs_sVolume *)v;
if (fseek(m_fp, m_sect[dbs_eSect_volume].offset, SEEK_SET) != 0) if (fseek(m_fp, m_sect[dbs_eSect_volume].offset, SEEK_SET) != 0)
...@@ -569,13 +581,13 @@ wb_dbs::writeSectVolume() ...@@ -569,13 +581,13 @@ wb_dbs::writeSectVolume()
memset(v, 0, sizeof(v)); memset(v, 0, sizeof(v));
memcpy(v, &m_volume, sizeof(m_volume)); memcpy(v, &m_volume, sizeof(m_volume));
printf("vid........: %d\n", vp->vid); //printf("vid........: %d\n", vp->vid);
printf("name.......: %s\n", vp->name); //printf("name.......: %s\n", vp->name);
printf("cid........: %d\n", vp->cid); //printf("cid........: %d\n", vp->cid);
printf("className..: %s\n", vp->className); //printf("className..: %s\n", vp->className);
printf("time.......: %ld\n", vp->time.tv_sec); //printf("time.......: %ld\n", vp->time.tv_sec);
printf("cardinality: %d\n", vp->cardinality); //printf("cardinality: %d\n", vp->cardinality);
printf("rbodysize..: %d\n", vp->rbodySize); //printf("rbodysize..: %d\n", vp->rbodySize);
if (fwrite(v, sizeof(v), 1, m_fp) < 1) if (fwrite(v, sizeof(v), 1, m_fp) < 1)
return LDH__FILEWRITE; return LDH__FILEWRITE;
...@@ -1135,22 +1147,44 @@ wb_dbs::buildSectClass() ...@@ -1135,22 +1147,44 @@ wb_dbs::buildSectClass()
} }
void void
wb_dbs::cidInsert(pwr_tStatus *sts, pwr_tCid cid, sCentry **cep) wb_dbs::cidInsert(pwr_tStatus *sts, pwr_tCid cid, pwr_sAttrRef *arp, sCentry **cep)
{ {
*cep = (sCentry*)tree_Insert(sts, m_class_th, &cid); *cep = (sCentry*)tree_Insert(sts, m_class_th, &cid);
if ( !arp)
return;
// if ( cdh_CidToVid(cid) == 1) // if ( cdh_CidToVid(cid) == 1)
// return; // return;
if (*sts == TREE__INSERTED) { if (*sts == TREE__INSERTED) {
// Insert depending classes // Insert depending classes
pwr_tCid *lst; pwr_tCid *lst;
pwr_sAttrRef *arlst;
sCentry *entry; sCentry *entry;
int cnt; int cnt;
pwr_tStatus lsts; pwr_tStatus lsts;
pwr_sAttrRef aref;
m_v->merep()->classDependency( &lsts, cid, &lst, &cnt); pwr_sAttrRef cast_aref;
for ( int i = 0; i < cnt; i++) pwr_tCid cast_cid;
cidInsert(&lsts, lst[i], &entry);
m_v->merep()->classDependency( &lsts, cid, &lst, &arlst, &cnt);
for ( int i = 0; i < cnt; i++) {
aref = cdh_ArefAdd( arp, &arlst[i]);
cidInsert(&lsts, lst[i], &aref, &entry);
if ( aref.Flags.b.CastAttr) {
cast_aref = cdh_ArefToCastAref( &aref);
wb_volume v(m_v);
wb_attribute a = v.attribute( &cast_aref);
if ( a) {
a.value( &cast_cid);
if ( cast_cid != pwr_cNCid)
cidInsert(&lsts, cast_cid, 0, &entry);
}
}
}
free(lst); free(lst);
free(arlst);
} }
} }
...@@ -1159,8 +1193,9 @@ wb_dbs::classInsert(sOentry *oep) ...@@ -1159,8 +1193,9 @@ wb_dbs::classInsert(sOentry *oep)
{ {
pwr_tStatus sts; pwr_tStatus sts;
sCentry *cep; sCentry *cep;
pwr_sAttrRef aref = cdh_ObjidToAref( oep->o.oid);
cidInsert(&sts, oep->o.cid, &cep); cidInsert(&sts, oep->o.cid, &aref, &cep);
if (sts == TREE__INSERTED) { if (sts == TREE__INSERTED) {
/* was inserted now */ /* was inserted now */
......
...@@ -125,7 +125,7 @@ public: ...@@ -125,7 +125,7 @@ public:
// ldhi_sObjHead *getAliasServer(sLCB *lcbp, ldhi_sObjHead *o, pwr_tOid *soid); // ldhi_sObjHead *getAliasServer(sLCB *lcbp, ldhi_sObjHead *o, pwr_tOid *soid);
// pwr_tStatus getMountServer(sLCB *lcbp, ldhi_sObjHead *o, pwr_tOid *soid); // pwr_tStatus getMountServer(sLCB *lcbp, ldhi_sObjHead *o, pwr_tOid *soid);
void cidInsert(pwr_tStatus *sts, pwr_tCid cid, sCentry **cep); void cidInsert(pwr_tStatus *sts, pwr_tCid cid, pwr_sAttrRef *arp, sCentry **cep);
void classInsert(sOentry *oep); void classInsert(sOentry *oep);
pwr_tStatus openFile(); pwr_tStatus openFile();
pwr_tStatus writeSectFile(size_t size); pwr_tStatus writeSectFile(size_t size);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "wb_tdrep.h" #include "wb_tdrep.h"
#include "wb_attrname.h" #include "wb_attrname.h"
#include "wb_ldh_msg.h" #include "wb_ldh_msg.h"
#include "co_time.h"
static int compCatt( tree_sTable *tp, tree_sNode *x, tree_sNode *y); static int compCatt( tree_sTable *tp, tree_sNode *x, tree_sNode *y);
...@@ -22,8 +23,10 @@ wb_merep::~wb_merep() ...@@ -22,8 +23,10 @@ wb_merep::~wb_merep()
{ {
pwr_tStatus sts; pwr_tStatus sts;
for ( mvrep_iterator it = m_mvrepdbs.begin(); it != m_mvrepdbs.end(); it++) for ( mvrep_iterator it = m_mvrepdbs.begin(); it != m_mvrepdbs.end(); it++) {
it->second->unref(); if ( it->second != m_vrep)
it->second->unref();
}
if ( m_catt_tt) if ( m_catt_tt)
tree_DeleteTable( &sts, m_catt_tt); tree_DeleteTable( &sts, m_catt_tt);
...@@ -93,7 +96,8 @@ void wb_merep::addDbs( pwr_tStatus *sts, wb_mvrep *mvrep) ...@@ -93,7 +96,8 @@ void wb_merep::addDbs( pwr_tStatus *sts, wb_mvrep *mvrep)
// Look for vrep in erep list... TODO // Look for vrep in erep list... TODO
m_mvrepdbs[mvrep->vid()] = mvrep; m_mvrepdbs[mvrep->vid()] = mvrep;
mvrep->ref(); if ( mvrep != m_vrep)
mvrep->ref();
*sts = LDH__SUCCESS; *sts = LDH__SUCCESS;
} }
else { else {
...@@ -110,7 +114,8 @@ void wb_merep::removeDbs(pwr_tStatus *sts, wb_mvrep *mvrep) ...@@ -110,7 +114,8 @@ void wb_merep::removeDbs(pwr_tStatus *sts, wb_mvrep *mvrep)
*sts = LDH__NOSUCHVOL; *sts = LDH__NOSUCHVOL;
return; return;
} }
it->second->unref(); if ( it->second != m_vrep)
it->second->unref();
m_mvrepdbs.erase( it); m_mvrepdbs.erase( it);
*sts = LDH__SUCCESS; *sts = LDH__SUCCESS;
} }
...@@ -294,11 +299,11 @@ int wb_merep::getAttrInfoRec( wb_attrname *attr, pwr_eBix bix, pwr_tCid cid, siz ...@@ -294,11 +299,11 @@ int wb_merep::getAttrInfoRec( wb_attrname *attr, pwr_eBix bix, pwr_tCid cid, siz
} }
void wb_merep::classDependency( pwr_tStatus *sts, pwr_tCid cid, void wb_merep::classDependency( pwr_tStatus *sts, pwr_tCid cid,
pwr_tCid **lst, int *cnt) pwr_tCid **lst, pwr_sAttrRef **arlst, int *cnt)
{ {
*lst = 0; *lst = 0;
*arlst = 0;
*cnt = 0; *cnt = 0;
*sts = LDH__SUCCESS;
wb_cdrep *cd = cdrep( sts, cid); wb_cdrep *cd = cdrep( sts, cid);
if ( !cd) return; if ( !cd) return;
...@@ -315,12 +320,14 @@ void wb_merep::classDependency( pwr_tStatus *sts, pwr_tCid cid, ...@@ -315,12 +320,14 @@ void wb_merep::classDependency( pwr_tStatus *sts, pwr_tCid cid,
} }
*lst = (pwr_tCid *) calloc( bd->nAttribute(), sizeof(pwr_tCid)); *lst = (pwr_tCid *) calloc( bd->nAttribute(), sizeof(pwr_tCid));
*arlst = (pwr_sAttrRef *) calloc( bd->nAttribute(), sizeof(pwr_sAttrRef));
*cnt = 0; *cnt = 0;
wb_adrep *ad, *oad; wb_adrep *ad, *oad;
for ( ad = bd->adrep( sts); ad;) { for ( ad = bd->adrep( sts); ad;) {
if ( cdh_tidIsCid( ad->tid())) { if ( cdh_tidIsCid( ad->tid())) {
(*lst)[*cnt] = ad->tid(); (*lst)[*cnt] = ad->tid();
(*arlst)[*cnt] = ad->aref();
(*cnt)++; (*cnt)++;
} }
oad = ad; oad = ad;
...@@ -329,6 +336,45 @@ void wb_merep::classDependency( pwr_tStatus *sts, pwr_tCid cid, ...@@ -329,6 +336,45 @@ void wb_merep::classDependency( pwr_tStatus *sts, pwr_tCid cid,
} }
delete cd; delete cd;
delete bd; delete bd;
*sts = LDH__SUCCESS;
}
void wb_merep::classVersion( pwr_tStatus *sts, pwr_tCid cid, pwr_tTime *time)
{
wb_cdrep *cd = cdrep( sts, cid);
if ( !cd) return;
wb_bdrep *bd = cd->bdrep( sts, pwr_eBix_rt);
if ( !bd) {
delete cd;
return;
}
if ( bd->nAttribute() == 0) {
delete cd;
delete bd;
return;
}
*time = cd->ohTime();
wb_adrep *ad, *oad;
for ( ad = bd->adrep( sts); ad;) {
if ( cdh_tidIsCid( ad->tid())) {
pwr_tTime t;
classVersion( sts, ad->tid(), &t);
if ( EVEN(*sts)) return;
if ( time_Acomp( time, &t) == -1)
*time = t;
}
oad = ad;
ad = ad->next( sts);
delete oad;
}
delete cd;
delete bd;
*sts = LDH__SUCCESS;
} }
void wb_merep::insertCattObject( pwr_tStatus *sts, pwr_tCid cid, void wb_merep::insertCattObject( pwr_tStatus *sts, pwr_tCid cid,
......
...@@ -65,7 +65,8 @@ public: ...@@ -65,7 +65,8 @@ public:
pwr_eType *type, int *flags, int level); pwr_eType *type, int *flags, int level);
void classDependency( pwr_tStatus *sts, pwr_tCid cid, void classDependency( pwr_tStatus *sts, pwr_tCid cid,
pwr_tCid **lst, int *cnt); pwr_tCid **lst, pwr_sAttrRef **arlst, int *cnt);
void classVersion( pwr_tStatus *sts, pwr_tCid cid, pwr_tTime *time);
tree_sTable *buildCatt( pwr_tStatus *sts); tree_sTable *buildCatt( pwr_tStatus *sts);
void insertCattObject( pwr_tStatus *sts, pwr_tCid cid, void insertCattObject( pwr_tStatus *sts, pwr_tCid cid,
wb_adrep *adp, int offset); wb_adrep *adp, int offset);
...@@ -74,3 +75,4 @@ public: ...@@ -74,3 +75,4 @@ public:
}; };
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment