1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #include "dbCCSeg.h"
34 
35 #include "db.h"
36 #include "dbBlock.h"
37 #include "dbCapNode.h"
38 #include "dbDatabase.h"
39 #include "dbJournal.h"
40 #include "dbNet.h"
41 #include "dbTable.h"
42 #include "dbTable.hpp"
43 #include "utl/Logger.h"
44 
45 namespace odb {
46 
47 template class dbTable<_dbCCSeg>;
48 
operator ==(const _dbCCSeg & rhs) const49 bool _dbCCSeg::operator==(const _dbCCSeg& rhs) const
50 {
51   if (_flags._spef_mark_1 != rhs._flags._spef_mark_1)
52     return false;
53 
54   if (_flags._mark != rhs._flags._mark)
55     return false;
56 
57   if (_flags._inFileCnt != rhs._flags._inFileCnt)
58     return false;
59 
60   if (_cap_node[0] != rhs._cap_node[0])
61     return false;
62 
63   if (_cap_node[1] != rhs._cap_node[1])
64     return false;
65 
66   if (_next[0] != rhs._next[0])
67     return false;
68 
69   if (_next[1] != rhs._next[1])
70     return false;
71 
72   return true;
73 }
74 
differences(dbDiff & diff,const char * field,const _dbCCSeg & rhs) const75 void _dbCCSeg::differences(dbDiff& diff,
76                            const char* field,
77                            const _dbCCSeg& rhs) const
78 {
79   DIFF_BEGIN
80   DIFF_FIELD(_flags._spef_mark_1);
81   DIFF_FIELD(_flags._mark);
82   DIFF_FIELD(_flags._inFileCnt);
83   DIFF_FIELD(_cap_node[0]);
84   DIFF_FIELD(_cap_node[1]);
85   DIFF_FIELD(_next[0]);
86   DIFF_FIELD(_next[1]);
87   DIFF_END
88 }
89 
out(dbDiff & diff,char side,const char * field) const90 void _dbCCSeg::out(dbDiff& diff, char side, const char* field) const
91 {
92   DIFF_OUT_BEGIN
93   DIFF_OUT_FIELD(_flags._spef_mark_1);
94   DIFF_OUT_FIELD(_flags._mark);
95   DIFF_OUT_FIELD(_flags._inFileCnt);
96   DIFF_OUT_FIELD(_cap_node[0]);
97   DIFF_OUT_FIELD(_cap_node[1]);
98   DIFF_OUT_FIELD(_next[0]);
99   DIFF_OUT_FIELD(_next[1]);
100   DIFF_END
101 }
102 
103 ////////////////////////////////////////////////////////////////////
104 //
105 // dbCCSeg - Methods
106 //
107 ////////////////////////////////////////////////////////////////////
108 
adjustCapacitance(float factor,int corner)109 void dbCCSeg::adjustCapacitance(float factor, int corner)
110 {
111   _dbCCSeg* seg = (_dbCCSeg*) this;
112   _dbBlock* block = (_dbBlock*) seg->getOwner();
113 
114   float& value
115       = (*block->_cc_val_tbl)[(seg->getOID() - 1) * block->_corners_per_block
116                               + 1 + corner];
117   float prev_value = value;
118   value *= factor;
119 
120   if (block->_journal) {
121     debugPrint(getImpl()->getLogger(),
122                utl::ODB,
123                "DB_ECO",
124                1,
125                "ECO: dbCCSeg {}, adjustCapacitance {}, corner {}",
126                seg->getId(),
127                factor,
128                corner);
129     block->_journal->beginAction(dbJournal::UPDATE_FIELD);
130     block->_journal->pushParam(dbCCSegObj);
131     block->_journal->pushParam(seg->getId());
132     block->_journal->pushParam(_dbCCSeg::CAPACITANCE);
133     block->_journal->pushParam(prev_value);
134     block->_journal->pushParam(value);
135     block->_journal->pushParam(0);
136     block->_journal->endAction();
137   }
138 }
139 
adjustCapacitance(float factor)140 void dbCCSeg::adjustCapacitance(float factor)
141 {
142   _dbBlock* block = (_dbBlock*) getImpl()->getOwner();
143   uint corner;
144   for (corner = 0; corner < block->_corners_per_block; corner++)
145     adjustCapacitance(factor, corner);
146 }
147 
getCapacitance(int corner)148 double dbCCSeg::getCapacitance(int corner)
149 {
150   _dbCCSeg* seg = (_dbCCSeg*) this;
151   _dbBlock* block = (_dbBlock*) seg->getOwner();
152   uint cornerCnt = block->_corners_per_block;
153   ZASSERT((corner >= 0) && ((uint) corner < cornerCnt));
154   return (*block->_cc_val_tbl)[(seg->getOID() - 1) * cornerCnt + 1 + corner];
155 }
156 
accAllCcCap(double * ttcap,double MillerMult)157 void dbCCSeg::accAllCcCap(double* ttcap, double MillerMult)
158 {
159   _dbCCSeg* seg = (_dbCCSeg*) this;
160   _dbBlock* block = (_dbBlock*) seg->getOwner();
161   uint cornerCnt = block->_corners_per_block;
162   for (uint ii = 0; ii < cornerCnt; ii++) {
163     ttcap[ii]
164         += ((*block->_cc_val_tbl)[(seg->getOID() - 1) * cornerCnt + 1 + ii])
165            * MillerMult;
166   }
167 }
168 
getAllCcCap(double * ttcap)169 void dbCCSeg::getAllCcCap(double* ttcap)
170 {
171   _dbCCSeg* seg = (_dbCCSeg*) this;
172   _dbBlock* block = (_dbBlock*) seg->getOwner();
173   uint cornerCnt = block->_corners_per_block;
174   for (uint ii = 0; ii < cornerCnt; ii++) {
175     ttcap[ii] = (*block->_cc_val_tbl)[(seg->getOID() - 1) * cornerCnt + 1 + ii];
176   }
177 }
178 
setAllCcCap(double * ttcap)179 void dbCCSeg::setAllCcCap(double* ttcap)
180 {
181   _dbCCSeg* seg = (_dbCCSeg*) this;
182   _dbBlock* block = (_dbBlock*) seg->getOwner();
183   uint cornerCnt = block->_corners_per_block;
184   for (uint ii = 0; ii < cornerCnt; ii++) {
185     (*block->_cc_val_tbl)[(seg->getOID() - 1) * cornerCnt + 1 + ii] = ttcap[ii];
186   }
187   if (block->_journal) {
188     char ccCaps[400];
189     int pos = 0;
190     ccCaps[0] = '\0';
191     for (uint ii = 0; ii < cornerCnt; ii++)
192       pos += sprintf(&ccCaps[pos], "%f ", ttcap[ii]);
193     debugPrint(getImpl()->getLogger(),
194                utl::ODB,
195                "DB_ECO",
196                1,
197                "ECO: dbCCSeg::setAllCcCap, ccseg: {}, caps: {}",
198                seg->getId(),
199                ttcap[0]);
200     block->_journal->beginAction(dbJournal::UPDATE_FIELD);
201     block->_journal->pushParam(dbCCSegObj);
202     block->_journal->pushParam(getId());
203     block->_journal->pushParam(_dbCCSeg::SETALLCCCAP);
204     for (uint ii = 0; ii < cornerCnt; ii++)
205       block->_journal->pushParam(ttcap[ii]);
206     block->_journal->endAction();
207   }
208 }
209 
setCapacitance(double cap,int corner)210 void dbCCSeg::setCapacitance(double cap, int corner)
211 {
212   _dbCCSeg* seg = (_dbCCSeg*) this;
213   _dbBlock* block = (_dbBlock*) seg->getOwner();
214   uint cornerCnt = block->_corners_per_block;
215   ZASSERT((corner >= 0) && ((uint) corner < cornerCnt));
216 
217   float& value
218       = (*block->_cc_val_tbl)[(seg->getOID() - 1) * cornerCnt + 1 + corner];
219   float prev_value = value;
220   value = (float) cap;
221 
222   if (block->_journal) {
223     debugPrint(getImpl()->getLogger(),
224                utl::ODB,
225                "DB_ECO",
226                1,
227                "ECO: dbCCSeg {}, setCapacitance {}, corner {}",
228                seg->getId(),
229                value,
230                corner);
231     block->_journal->beginAction(dbJournal::UPDATE_FIELD);
232     block->_journal->pushParam(dbCCSegObj);
233     block->_journal->pushParam(seg->getId());
234     block->_journal->pushParam(_dbCCSeg::CAPACITANCE);
235     block->_journal->pushParam(prev_value);
236     block->_journal->pushParam(value);
237     block->_journal->pushParam(corner);
238     block->_journal->endAction();
239   }
240 }
241 
addCapacitance(double cap,int corner)242 void dbCCSeg::addCapacitance(double cap, int corner)
243 {
244   _dbCCSeg* seg = (_dbCCSeg*) this;
245   _dbBlock* block = (_dbBlock*) seg->getOwner();
246   uint cornerCnt = block->_corners_per_block;
247   ZASSERT((corner >= 0) && ((uint) corner < cornerCnt));
248 
249   float& value
250       = (*block->_cc_val_tbl)[(seg->getOID() - 1) * cornerCnt + 1 + corner];
251   float prev_value = value;
252   value += (float) cap;
253 
254   if (block->_journal) {
255     debugPrint(getImpl()->getLogger(),
256                utl::ODB,
257                "DB_ECO",
258                1,
259                "ECO: dbCCSeg {}, addCapacitance {}, corner {}",
260                seg->getId(),
261                value,
262                corner);
263     block->_journal->beginAction(dbJournal::UPDATE_FIELD);
264     block->_journal->pushParam(dbCCSegObj);
265     block->_journal->pushParam(seg->getId());
266     block->_journal->pushParam(_dbCCSeg::CAPACITANCE);
267     block->_journal->pushParam(prev_value);
268     block->_journal->pushParam(value);
269     block->_journal->pushParam(corner);
270     block->_journal->endAction();
271   }
272 }
273 
addCcCapacitance(dbCCSeg * other)274 void dbCCSeg::addCcCapacitance(dbCCSeg* other)
275 {
276   _dbCCSeg* seg = (_dbCCSeg*) this;
277   _dbBlock* block = (_dbBlock*) seg->getOwner();
278   _dbCCSeg* oseg = (_dbCCSeg*) other;
279   uint cornerCnt = block->_corners_per_block;
280 
281   for (uint ii = 0; ii < cornerCnt; ii++) {
282     float& value
283         = (*block->_cc_val_tbl)[(seg->getOID() - 1) * cornerCnt + 1 + ii];
284     float& ovalue
285         = (*block->_cc_val_tbl)[(oseg->getOID() - 1) * cornerCnt + 1 + ii];
286     value += ovalue;
287   }
288 
289   if (block->_journal) {
290     debugPrint(getImpl()->getLogger(),
291                utl::ODB,
292                "DB_ECO",
293                1,
294                "ECO: dbCCSeg {}, other dbCCSeg {}, addCcCapacitance",
295                seg->getOID(),
296                oseg->getOID());
297     block->_journal->beginAction(dbJournal::UPDATE_FIELD);
298     block->_journal->pushParam(dbCCSegObj);
299     block->_journal->pushParam(seg->getId());
300     block->_journal->pushParam(_dbCCSeg::ADDCCCAPACITANCE);
301     block->_journal->pushParam(oseg->getId());
302     block->_journal->endAction();
303   }
304 }
305 
getSourceCapNode()306 dbCapNode* dbCCSeg::getSourceCapNode()
307 {
308   _dbCCSeg* seg = (_dbCCSeg*) this;
309   _dbBlock* block = (_dbBlock*) seg->getOwner();
310   _dbCapNode* n = block->_cap_node_tbl->getPtr(seg->_cap_node[0]);
311   return (dbCapNode*) n;
312 }
313 
getTargetCapNode()314 dbCapNode* dbCCSeg::getTargetCapNode()
315 {
316   _dbCCSeg* seg = (_dbCCSeg*) this;
317   _dbBlock* block = (_dbBlock*) seg->getOwner();
318   _dbCapNode* n = block->_cap_node_tbl->getPtr(seg->_cap_node[1]);
319   return (dbCapNode*) n;
320 }
321 
getSourceNodeNum()322 uint dbCCSeg::getSourceNodeNum()
323 {
324   dbCapNode* n = getSourceCapNode();
325   return n->getNode();
326 }
327 
328 /*
329 void
330 dbCCSeg::setSourceNode( uint source_node )
331 {
332     _dbCCSeg * seg = (_dbCCSeg *) this;
333     seg->_source_cap_node = source_node;
334 }
335 */
336 
getTargetNodeNum()337 uint dbCCSeg::getTargetNodeNum()
338 {
339   dbCapNode* n = getTargetCapNode();
340   return n->getNode();
341 }
342 
343 /*
344 void
345 dbCCSeg::setTargetNode( uint target_node )
346 {
347     _dbCCSeg * seg = (_dbCCSeg *) this;
348     seg->_target_cap_node = target_node;
349 }
350 */
351 
getSourceNet()352 dbNet* dbCCSeg::getSourceNet()
353 {
354   dbCapNode* node = getSourceCapNode();
355   return node->getNet();
356 }
357 
getTargetNet()358 dbNet* dbCCSeg::getTargetNet()
359 {
360   dbCapNode* node = getTargetCapNode();
361   return node->getNet();
362 }
363 
getInfileCnt()364 uint dbCCSeg::getInfileCnt()
365 {
366   _dbCCSeg* seg = (_dbCCSeg*) this;
367   return (seg->_flags._inFileCnt);
368 }
369 
incrInfileCnt()370 void dbCCSeg::incrInfileCnt()
371 {
372   _dbCCSeg* seg = (_dbCCSeg*) this;
373   seg->_flags._inFileCnt++;
374 }
375 
isMarked()376 bool dbCCSeg::isMarked()
377 {
378   _dbCCSeg* seg = (_dbCCSeg*) this;
379   return seg->_flags._mark == 1;
380 }
381 
setMark(bool value)382 void dbCCSeg::setMark(bool value)
383 {
384   _dbCCSeg* seg = (_dbCCSeg*) this;
385   seg->_flags._mark = (value == true) ? 1 : 0;
386 }
387 
printCapnCC(uint capn)388 void dbCCSeg::printCapnCC(uint capn)
389 {
390   _dbCCSeg* seg = (_dbCCSeg*) this;
391   uint sidx;
392   if (capn == seg->_cap_node[0])
393     sidx = 0;
394   else if (capn == seg->_cap_node[1])
395     sidx = 1;
396   else {
397     debugPrint(getImpl()->getLogger(),
398                utl::ODB,
399                "DB_ECO",
400                1,
401                "ccSeg {} has capnd {} {}, not {} !",
402                getId(),
403                (uint) seg->_cap_node[0],
404                (uint) seg->_cap_node[1],
405                capn);
406     return;
407   }
408   getImpl()->getLogger()->info(
409       utl::ODB,
410       21,
411       "    ccSeg={} capn0={} next0={} capn1={} next1={}",
412       getId(),
413       (uint) seg->_cap_node[0],
414       (uint) seg->_next[0],
415       (uint) seg->_cap_node[1],
416       (uint) seg->_next[1]);
417   if (seg->_next[sidx] == 0) {
418     return;
419   }
420   dbBlock* block = (dbBlock*) seg->getOwner();
421   dbCCSeg* nseg = getCCSeg(block, seg->_next[sidx]);
422   nseg->printCapnCC(capn);
423 }
424 
checkCapnCC(uint capn)425 bool dbCCSeg::checkCapnCC(uint capn)
426 {
427   _dbCCSeg* seg = (_dbCCSeg*) this;
428   uint sidx;
429   if (capn == seg->_cap_node[0])
430     sidx = 0;
431   else if (capn == seg->_cap_node[1])
432     sidx = 1;
433   else {
434     getImpl()->getLogger()->info(utl::ODB,
435                                  22,
436                                  "ccSeg {} has capnd {} {}, not {} !",
437                                  getId(),
438                                  (uint) seg->_cap_node[0],
439                                  (uint) seg->_cap_node[1],
440                                  capn);
441     return false;
442   }
443   if (seg->_next[sidx] == 0) {
444     return true;
445   }
446   dbBlock* block = (dbBlock*) seg->getOwner();
447   dbCCSeg* nseg = getCCSeg(block, seg->_next[sidx]);
448   bool rc = nseg->checkCapnCC(capn);
449   return rc;
450 }
451 
452 /*
453  * TODO: ????
454 dbCCSeg *
455 dbCCSeg::relinkTgtCC (dbNet *net_, dbCCSeg *pseg_, uint src_cap_node, uint
456 tgt_cap_node)
457 {
458     _dbNet *tnet = (_dbNet *)net_;
459     _dbCCSeg *pseg = (_dbCCSeg *)pseg_;
460     if (pseg && src_cap_node==0 && tgt_cap_node==0)
461     {
462         tnet->_cc_tgt_segs = pseg->getOID();
463         return NULL;
464     }
465     dbTable<_dbCCSeg> *cct = ((_dbBlock *)tnet->getOwner())->_cc_seg_tbl;
466     _dbCCSeg *seg;
467     uint psid = 0;
468     uint tsid;
469     for (tsid = tnet->_cc_tgt_segs; tsid; tsid = seg->_next_target)
470     {
471         seg = cct->getPtr(tsid);
472         if (seg->_source_cap_node == src_cap_node &&
473             seg->_target_cap_node == tgt_cap_node)
474             break;
475         psid = tsid;
476     }
477     if (!tsid)
478         return NULL;
479     if (psid)
480         cct->getPtr(psid)->_next_target = seg->_next_target;
481     else
482         tnet->_cc_tgt_segs = seg->_next_target;
483     seg->_next_target = 0;
484     if (pseg)
485         ((_dbCCSeg *)pseg)->_next_target = tsid;
486     return (dbCCSeg *) seg;
487 }
488 */
489 
findParallelCCSeg(_dbBlock * block,_dbCapNode * src,_dbCapNode * tgt,bool reInsert)490 static _dbCCSeg* findParallelCCSeg(_dbBlock* block,
491                                    _dbCapNode* src,
492                                    _dbCapNode* tgt,
493                                    bool reInsert)
494 {
495   uint src_id = src->getOID();
496   uint tgt_id = tgt->getOID();
497   _dbCCSeg* pccs = NULL;
498   _dbCCSeg* ccs = NULL;
499   uint seg;
500 
501   for (seg = tgt->_cc_segs; seg;) {
502     ccs = block->_cc_seg_tbl->getPtr(seg);
503 
504     if (ccs->_cap_node[0] == tgt_id && ccs->_cap_node[1] == src_id)
505       break;
506 
507     if (ccs->_cap_node[1] == tgt_id && ccs->_cap_node[0] == src_id)
508       break;
509 
510     pccs = ccs;
511     seg = ccs->next(tgt_id);
512   }
513   if (!seg)
514     return NULL;
515   if (!pccs || !reInsert)
516     return ccs;
517   pccs->_next[pccs->idx(tgt_id)] = ccs->next(tgt_id);
518   ccs->_next[ccs->idx(tgt_id)] = tgt->_cc_segs;
519   tgt->_cc_segs = ccs->getOID();
520   return ccs;
521 }
522 
findCC(dbCapNode * nodeA,dbCapNode * nodeB)523 dbCCSeg* dbCCSeg::findCC(dbCapNode* nodeA, dbCapNode* nodeB)
524 {
525   _dbBlock* block = (_dbBlock*) nodeA->getImpl()->getOwner();
526   _dbCCSeg* seg = findParallelCCSeg(
527       block, (_dbCapNode*) nodeA, (_dbCapNode*) nodeB, false);
528   return (dbCCSeg*) seg;
529 }
530 
create(dbCapNode * src_,dbCapNode * tgt_,bool mergeParallel)531 dbCCSeg* dbCCSeg::create(dbCapNode* src_, dbCapNode* tgt_, bool mergeParallel)
532 {
533   _dbBlock* block = (_dbBlock*) src_->getImpl()->getOwner();
534 
535   uint srcNetId = src_->getNet()->getImpl()->getOID();
536   uint tgtNetId = tgt_->getNet()->getImpl()->getOID();
537 
538   _dbCapNode* src = (_dbCapNode*) src_;
539   _dbCapNode* tgt = (_dbCapNode*) tgt_;
540   if (srcNetId > tgtNetId) {
541     src = (_dbCapNode*) tgt_;
542     tgt = (_dbCapNode*) src_;
543   }
544 
545   if (block->_journal) {
546     debugPrint(block->getImpl()->getLogger(),
547                utl::ODB,
548                "DB_ECO",
549                1,
550                "ECO: dbCCSeg::create, nodeA = {}, nodeB = {}, merge = {}",
551                src->getOID(),
552                tgt->getOID(),
553                mergeParallel);
554 
555     block->_journal->beginAction(dbJournal::CREATE_OBJECT);
556     block->_journal->pushParam(dbCCSegObj);
557     block->_journal->pushParam(src->getOID());
558     block->_journal->pushParam(tgt->getOID());
559     block->_journal->pushParam(mergeParallel);
560     block->_journal->endAction();
561   }
562 
563   _dbCCSeg* seg;
564   if (mergeParallel && (seg = findParallelCCSeg(block, src, tgt, true)))
565     return (dbCCSeg*) seg;
566 
567   seg = block->_cc_seg_tbl->create();
568   // seg->_flags._cnt = block->_num_corners;
569 
570   // set corner values
571   uint cornerCnt = block->_corners_per_block;
572   if (block->_maxCCSegId >= seg->getOID()) {
573     for (uint ii = 0; ii < cornerCnt; ii++)
574       (*block->_cc_val_tbl)[(seg->getOID() - 1) * cornerCnt + 1 + ii] = 0.0;
575   } else {
576     block->_maxCCSegId = seg->getOID();
577     uint ccCapIdx = block->_cc_val_tbl->getIdx(cornerCnt, (float) 0.0);
578     ZASSERT((seg->getOID() - 1) * cornerCnt + 1 == ccCapIdx);
579   }
580 
581   seg->_cap_node[0] = src->getOID();
582   seg->_next[0] = src->_cc_segs;
583   src->_cc_segs = seg->getOID();
584 
585   seg->_cap_node[1] = tgt->getOID();
586   seg->_next[1] = tgt->_cc_segs;
587   tgt->_cc_segs = seg->getOID();
588   return (dbCCSeg*) seg;
589 }
590 
unlink_cc_seg(_dbBlock * block,_dbCapNode * node,_dbCCSeg * s)591 static void unlink_cc_seg(_dbBlock* block, _dbCapNode* node, _dbCCSeg* s)
592 {
593   dbId<_dbCapNode> cid = node->getOID();
594   uint prev = 0;
595   uint next = node->_cc_segs;
596   uint seg = s->getOID();
597 
598   while (next) {
599     if (next == seg) {
600       if (prev == 0)
601         node->_cc_segs = s->next(cid);
602       else {
603         _dbCCSeg* p = block->_cc_seg_tbl->getPtr(prev);
604         p->next(cid) = s->next(cid);
605       }
606 
607       break;
608     }
609 
610     _dbCCSeg* ncc = block->_cc_seg_tbl->getPtr(next);
611     prev = next;
612     next = ncc->next(cid);
613   }
614 }
615 
unLink_cc_seg(dbCapNode * capn)616 void dbCCSeg::unLink_cc_seg(dbCapNode* capn)
617 {
618   _dbBlock* block = (_dbBlock*) getImpl()->getOwner();
619   unlink_cc_seg(block, (_dbCapNode*) capn, (_dbCCSeg*) this);
620   if (block->_journal) {
621     debugPrint(getImpl()->getLogger(),
622                utl::ODB,
623                "DB_ECO",
624                1,
625                "ECO: dbCCSeg::unLink, ccseg: {}, capNode: {}",
626                getId(),
627                capn->getId());
628     block->_journal->beginAction(dbJournal::UPDATE_FIELD);
629     block->_journal->pushParam(dbCCSegObj);
630     block->_journal->pushParam(getId());
631     block->_journal->pushParam(_dbCCSeg::UNLINKCCSEG);
632     block->_journal->pushParam(capn->getId());
633     block->_journal->endAction();
634   }
635 }
636 
Link_cc_seg(dbCapNode * capn,uint cseq)637 void dbCCSeg::Link_cc_seg(dbCapNode* capn, uint cseq)
638 {
639   _dbBlock* block = (_dbBlock*) getImpl()->getOwner();
640   _dbCapNode* tgt = (_dbCapNode*) capn;
641   ((_dbCCSeg*) this)->_next[cseq] = tgt->_cc_segs;
642   tgt->_cc_segs = getId();
643 
644   if (block->_journal) {
645     debugPrint(getImpl()->getLogger(),
646                utl::ODB,
647                "DB_ECO",
648                1,
649                "ECO: dbCCSeg::Link, ccseg: {}, capNode: {}, cseq: {}",
650                getId(),
651                capn->getId(),
652                cseq);
653     block->_journal->beginAction(dbJournal::UPDATE_FIELD);
654     block->_journal->pushParam(dbCCSegObj);
655     block->_journal->pushParam(getId());
656     block->_journal->pushParam(_dbCCSeg::LINKCCSEG);
657     block->_journal->pushParam(capn->getId());
658     block->_journal->pushParam(cseq);
659     block->_journal->endAction();
660   }
661 }
662 
disconnect(dbCCSeg * tcc_)663 void dbCCSeg::disconnect(dbCCSeg* tcc_)
664 {
665   _dbCCSeg* tcc = (_dbCCSeg*) tcc_;
666   dbBlock* block = (dbBlock*) tcc->getOwner();
667 
668   dbCapNode* src = dbCapNode::getCapNode(block, tcc->_cap_node[0]);
669   dbCapNode* tgt = dbCapNode::getCapNode(block, tcc->_cap_node[1]);
670   tcc_->unLink_cc_seg(src);
671   tcc_->unLink_cc_seg(tgt);
672 }
673 
connect(dbCCSeg * tcc_)674 void dbCCSeg::connect(dbCCSeg* tcc_)
675 {
676   _dbCCSeg* tcc = (_dbCCSeg*) tcc_;
677   dbBlock* block = (dbBlock*) tcc->getOwner();
678 
679   dbCapNode* src = dbCapNode::getCapNode(block, tcc->_cap_node[0]);
680   dbCapNode* tgt = dbCapNode::getCapNode(block, tcc->_cap_node[1]);
681   tcc_->Link_cc_seg(src, 0);
682   tcc_->Link_cc_seg(tgt, 1);
683 }
destroy(dbCCSeg * seg_)684 void dbCCSeg::destroy(dbCCSeg* seg_)
685 {
686   _dbCCSeg* seg = (_dbCCSeg*) seg_;
687   _dbBlock* block = (_dbBlock*) seg->getOwner();
688 
689   if (block->_journal) {
690     debugPrint(block->getImpl()->getLogger(),
691                utl::ODB,
692                "DB_ECO",
693                1,
694                "ECO: dbCCSeg::destroy, seg id: {}",
695                seg->getId());
696     block->_journal->beginAction(dbJournal::DELETE_OBJECT);
697     block->_journal->pushParam(dbCCSegObj);
698     block->_journal->pushParam(seg->getId());
699     block->_journal->pushParam((uint) 1);  //  regular destroy
700     block->_journal->endAction();
701   }
702 
703   _dbCapNode* src = block->_cap_node_tbl->getPtr(seg->_cap_node[0]);
704   _dbCapNode* tgt = block->_cap_node_tbl->getPtr(seg->_cap_node[1]);
705   unlink_cc_seg(block, src, seg);
706   unlink_cc_seg(block, tgt, seg);
707   dbProperty::destroyProperties(seg);
708   block->_cc_seg_tbl->destroy(seg);
709 }
destroyS(dbCCSeg * seg_)710 void dbCCSeg::destroyS(dbCCSeg* seg_)
711 {
712   _dbCCSeg* seg = (_dbCCSeg*) seg_;
713   _dbBlock* block = (_dbBlock*) seg->getOwner();
714 
715   if (block->_journal) {
716     debugPrint(block->getImpl()->getLogger(),
717                utl::ODB,
718                "DB_ECO",
719                1,
720                "ECO: dbCCSeg::destroy, seg id: {}",
721                seg->getId());
722     block->_journal->beginAction(dbJournal::DELETE_OBJECT);
723     block->_journal->pushParam(dbCCSegObj);
724     block->_journal->pushParam(seg->getId());
725     block->_journal->pushParam((uint) 0);  //  simple destroy
726     block->_journal->endAction();
727   }
728 
729   dbProperty::destroyProperties(seg);
730   block->_cc_seg_tbl->destroy(seg);
731 }
732 
destroy(dbSet<dbCCSeg>::iterator & itr)733 dbSet<dbCCSeg>::iterator dbCCSeg::destroy(dbSet<dbCCSeg>::iterator& itr)
734 {
735   dbCCSeg* bt = *itr;
736   dbSet<dbCCSeg>::iterator next = ++itr;
737   destroy(bt);
738   return next;
739 }
740 
swapCapnode(dbCapNode * orig_,dbCapNode * new_)741 void dbCCSeg::swapCapnode(dbCapNode* orig_, dbCapNode* new_)
742 {
743   _dbCCSeg* seg = (_dbCCSeg*) this;
744   _dbBlock* block = (_dbBlock*) seg->getOwner();
745   _dbCapNode* orig = (_dbCapNode*) orig_;
746   _dbCapNode* newn = (_dbCapNode*) new_;
747   uint oid = orig->getOID();
748   uint nid = newn->getOID();
749   uint sidx;
750   if (oid == seg->_cap_node[0]) {
751     sidx = 0;
752   } else if (oid == seg->_cap_node[1]) {
753     sidx = 1;
754   } else {
755     getImpl()->getLogger()->error(
756         utl::ODB,
757         23,
758         "CCSeg {} does not have orig capNode {}. Can not swap.",
759         seg->getOID(),
760         oid);
761   }
762   unlink_cc_seg(block, orig, seg);
763   seg->_cap_node[sidx] = nid;
764   seg->_next[sidx] = newn->_cc_segs;
765   newn->_cc_segs = seg->getOID();
766   if (block->_journal) {
767     debugPrint(getImpl()->getLogger(),
768                utl::ODB,
769                "DB_ECO",
770                1,
771                "ECO: dbCCSeg {}, origCapNode {}, newCapNode {}, swapCapnode",
772                seg->getOID(),
773                oid,
774                nid);
775     block->_journal->beginAction(dbJournal::UPDATE_FIELD);
776     block->_journal->pushParam(dbCCSegObj);
777     block->_journal->pushParam(seg->getId());
778     block->_journal->pushParam(_dbCCSeg::SWAPCAPNODE);
779     block->_journal->pushParam(oid);
780     block->_journal->pushParam(nid);
781     block->_journal->endAction();
782   }
783 }
784 
getTheOtherCapn(dbCapNode * oneCap,uint & cid)785 dbCapNode* dbCCSeg::getTheOtherCapn(dbCapNode* oneCap, uint& cid)
786 {
787   _dbCCSeg* seg = (_dbCCSeg*) this;
788   _dbBlock* block = (_dbBlock*) seg->getOwner();
789   cid = ((_dbCapNode*) oneCap)->getOID() == seg->_cap_node[1] ? 0 : 1;
790   _dbCapNode* n = block->_cap_node_tbl->getPtr(seg->_cap_node[cid]);
791   return (dbCapNode*) n;
792 }
793 
getCCSeg(dbBlock * block_,uint dbid_)794 dbCCSeg* dbCCSeg::getCCSeg(dbBlock* block_, uint dbid_)
795 {
796   _dbBlock* block = (_dbBlock*) block_;
797   return (dbCCSeg*) block->_cc_seg_tbl->getPtr(dbid_);
798 }
799 
800 }  // namespace odb
801