示例#1
0
文件: rdisk.c 项目: ashumeow/retrobsd
static inline struct buf *read_mbr(int root)
{
	if(root>MAXDEV) return NULL;

	int rv;
	int unit = disks[root].unit;

	struct buf *bp = getnewbuf();

	DEBUG8("rd%d: read mbr from device %d\n",root,unit);
	rv = disks[root].read(unit,0,bp->b_addr,512);
	if(rv==0)
	{
		DEBUG8("rd%d: mbr read FAIL\n",root);
		brelse(buf);
		return NULL;
	}
	DEBUG8("rd%d: mbr read OK\n",root);

	return bp;
}
示例#2
0
int
SMSTPDUContainer::decodeHexMessage(char* hexData)
{
   DEBUG1(cerr << "hexData = " << hexData << endl);
   int length = strlen(hexData);
   int size = 0;
   for(int i=0; i < length; i+=2 ) {
      // Put two of the hex characters in a string
      char hexChars[3] = { hexData[i], hexData[i+1], '\0'};
      DEBUG8(cerr << "hexChars=" << hexChars << endl);
      unsigned int value = 0;
      sscanf(hexChars, "%x", &value);
      *pnext++ = (uint8)value;
      size++;
   }
   reset();
   // Now it's time to decode the real message and set
   // the member variables accordingly.
   int position = 0;
   if ( 0 ) {
      // Skip SMSC-address
      if ( data[position] != 0 )
         position += data[position] + 1;
   }
   strcpy(m_serviceCenter, "");
   // Flags ( I think they are always == 4 )
   int flags = data[position++];
   int addressLength = data[position++];
   // Skip addresstype
   position++;
   char* senderAddress = new char[addressLength+1];
   unpackAddress(senderAddress, data, position, addressLength);
   strcpy(m_recipientPhone, senderAddress);
   delete [] senderAddress;
   // Skip the address (the length is given in nibbles) + PID + DCS + timestamp
   position += ((addressLength + 1) / 2) + 1 + 1 + 7;
   int dataLength = data[position++];
   m_payLoadSize = SMSUtil::getDecoded160x7(m_payLoad,
                                            &data[position],
                                            dataLength);
   if ( ( flags & 0x40 ) == 0x40 ) {
      DEBUG2(cout << "Skipping udh!!!!" << endl);
      // Header indication set.
      int udh_len = data[position++];
      // Remove udh from payload
      uint8 tempPay[256];
      memcpy(tempPay, m_payLoad, m_payLoadSize);
      int udh_offset = (( udh_len + 1 ) * 8) / 7 + 2;
      m_payLoadSize -= udh_offset;
      memcpy(m_payLoad, tempPay + udh_offset, m_payLoadSize);
   }
   return size;
}
示例#3
0
文件: rdisk.c 项目: ashumeow/retrobsd
static inline int init_device(int root,int flag)
{
	int i;
	int e;
	if(root>MAXDEV) return ENODEV;

	struct buf *bp;
	struct mbr *mbr;

	int unit = disks[root].unit;

	e = disks[root].init(unit,flag);

	if(e!=0)
		return e;

	DEBUG8("rd%d: about to read mbr\n",root);
	bp = read_mbr(root);
	if(!bp)
		return ENXIO;
	DEBUG8("rd%d: mbr read\n",root);

	mbr = (struct mbr *)bp->b_addr;

	DEBUG5("rd%d: partition types: %02X %02X %02X %02X\n",root,
		mbr->partitions[0].type,
		mbr->partitions[1].type,
		mbr->partitions[2].type,
		mbr->partitions[3].type
	);
	DEBUG8("rd%d: partition 1 start: %p length: %p\n",root,
		mbr->partitions[0].lbastart, mbr->partitions[0].lbalength
	);
	DEBUG8("rd%d: partition 2 start: %p length: %p\n",root,
		mbr->partitions[1].lbastart, mbr->partitions[1].lbalength
	);
	DEBUG8("rd%d: partition 3 start: %p length: %p\n",root,
		mbr->partitions[2].lbastart, mbr->partitions[2].lbalength
	);
	DEBUG8("rd%d: partition 4 start: %p length: %p\n",root,
		mbr->partitions[3].lbastart, mbr->partitions[3].lbalength
	);

	for(i=0; i<4; i++)
	{
		dflags[root].start[i] = mbr->partitions[i].lbastart>>1;
		dflags[root].len[i] = mbr->partitions[i].lbalength>>1;
	}
	dflags[root].blocks = disks[root].size(unit);
	brelse(bp);
	return 0;
}
GLOBAL void UMF_garbage_collection
(
    NumericType *Numeric,
    WorkType *Work,
    Int drnew,	    /* compact current front to drnew-by-dcnew */
    Int dcnew,
    Int do_Fcpos
)
{
    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

    Int size, e, n_row, n_col, nrows, ncols, nrowsleft, ncolsleft, prevsize,
	csize, size2, i2, j2, i, j, cdeg, rdeg, *E, row, col,
	*Rows, *Cols, *Rows2, *Cols2, nel, e2, *Row_tuples, *Col_tuples,
	*Row_degree, *Col_degree ;
    Entry *C, *C1, *C3, *C2 ;
    Unit *psrc, *pdest, *p, *pnext ;
    Element *epsrc, *epdest ;

#ifndef NDEBUG
    Int nmark ;
#endif

    /* ---------------------------------------------------------------------- */
    /* get parameters */
    /* ---------------------------------------------------------------------- */

    Col_degree = Numeric->Cperm ;	/* for NON_PIVOTAL_COL macro */
    Row_degree = Numeric->Rperm ;	/* for NON_PIVOTAL_ROW macro */
    Row_tuples = Numeric->Uip ;
    Col_tuples = Numeric->Lip ;
    E = Work->E ;
    n_row = Work->n_row ;
    n_col = Work->n_col ;

    /* note that the tuple lengths (Col_tlen and Row_tlen) are updated, but */
    /* the tuple lists themselves are stale and are about to be destroyed */
    /* and recreated.  Do not attempt to scan them until they are recreated. */

#ifndef NDEBUG
    DEBUGm1 (("::::GARBAGE COLLECTION::::\n")) ;
    UMF_dump_memory (Numeric) ;
#endif

    Numeric->ngarbage++ ;

    /* ---------------------------------------------------------------------- */
    /* delete the tuple lists by marking the blocks as free */
    /* ---------------------------------------------------------------------- */

    /* do not modify Row_tlen and Col_tlen */
    /* those are needed for UMF_build_tuples */

    for (row = 0 ; row < n_row ; row++)
    {
	if (NON_PIVOTAL_ROW (row) && Row_tuples [row])
	{
	    DEBUG2 (("row "ID" tuples "ID"\n", row, Row_tuples [row])) ;
	    p = Numeric->Memory + Row_tuples [row] - 1 ;
	    DEBUG2 (("Freeing tuple list row "ID", p-S "ID", size "ID"\n",
		row, (Int) (p-Numeric->Memory), p->header.size)) ;
	    ASSERT (p->header.size > 0) ;
	    ASSERT (p >= Numeric->Memory + Numeric->itail) ;
	    ASSERT (p < Numeric->Memory + Numeric->size) ;
	    p->header.size = -p->header.size ;
	    Row_tuples [row] = 0 ;
	}
    }

    for (col = 0 ; col < n_col ; col++)
    {
	if (NON_PIVOTAL_COL (col) && Col_tuples [col])
	{
	    DEBUG2 (("col "ID" tuples "ID"\n", col, Col_tuples [col])) ;
	    p = Numeric->Memory + Col_tuples [col] - 1 ;
	    DEBUG2 (("Freeing tuple list col "ID", p-S "ID", size "ID"\n",
		col, (Int) (p-Numeric->Memory), p->header.size)) ;
	    ASSERT (p->header.size > 0) ;
	    ASSERT (p >= Numeric->Memory + Numeric->itail) ;
	    ASSERT (p < Numeric->Memory + Numeric->size) ;
	    p->header.size = -p->header.size ;
	    Col_tuples [col] = 0 ;
	}
    }

    /* ---------------------------------------------------------------------- */
    /* mark the elements, and compress the name space */
    /* ---------------------------------------------------------------------- */

    nel = Work->nel ;
    ASSERT (nel < Work->elen) ;

#ifndef NDEBUG
    nmark = 0 ;
    UMF_dump_current_front (Numeric, Work, FALSE) ;
    DEBUGm1 (("E [0] "ID"  \n", E [0])) ;
    ASSERT (IMPLIES (E [0],
		Work->Flublock == (Entry *) (Numeric->Memory + E [0]))) ;
    ASSERT (IMPLIES (Work->Flublock,
		Work->Flublock == (Entry *) (Numeric->Memory + E [0]))) ;
    ASSERT ((E [0] != 0) == (Work->Flublock != (Entry *) NULL)) ;
#endif

    e2 = 0 ;

    for (e = 0 ; e <= nel ; e++) /* for all elements in order of creation */
    {
	if (E [e])
	{
	    psrc = Numeric->Memory + E [e] ;
	    psrc-- ;		/* get the header of this block */
	    if (e > 0)
	    {
		e2++ ;	/* do not renumber element zero */
	    }
	    ASSERT (psrc->header.size > 0) ;
	    psrc->header.size = e2  ;	/* store the new name in the header */
#ifndef NDEBUG
	    nmark++ ;
#endif
	    DEBUG7 ((ID":: Mark e "ID" at psrc-S "ID", new e "ID"\n",
		nmark, e, (Int) (psrc-Numeric->Memory), e2)) ;
	    E [e] = 0 ;
	    if (e == Work->prior_element)
	    {
		Work->prior_element = e2 ;
	    }
	}
    }

    /* all 1..e2 are now in use (element zero may or may not be in use) */
    Work->nel = e2 ;
    nel = Work->nel ;

#ifndef NDEBUG
    for (e = 0 ; e < Work->elen ; e++)
    {
	ASSERT (!E [e]) ;
    }
#endif

    /* ---------------------------------------------------------------------- */
    /* compress the elements */
    /* ---------------------------------------------------------------------- */

    /* point to tail marker block of size 1 + header */
    psrc = Numeric->Memory + Numeric->size - 2 ;
    pdest = psrc ;
    prevsize = psrc->header.prevsize ;
    DEBUG7 (("Starting the compression:\n")) ;

    while (prevsize > 0)
    {

	/* ------------------------------------------------------------------ */
	/* move up to the next element above the current header, and */
	/* get the element name and size */
	/* (if it is an element, the name will be positive) */
	/* ------------------------------------------------------------------ */

	size = prevsize ;
	psrc -= (size + 1) ;
	e = psrc->header.size ;
	prevsize = psrc->header.prevsize ;
	/* top block at tail has prevsize of 0 */

	/* a free block will have a negative size, so skip it */
	/* otherwise, if size >= 0, it holds the element name, not the size */

	DEBUG8 (("psrc-S: "ID" prevsize: "ID" size: "ID,
	    (Int) (psrc-Numeric->Memory), prevsize, size)) ;

	if (e == 0)
	{
	    /* -------------------------------------------------------------- */
	    /* this is the current frontal matrix */
	    /* -------------------------------------------------------------- */

	    Entry *F1, *F2, *Fsrc, *Fdst ;
	    Int c, r, k, dr, dc, gap, gap1, gap2, nb ;

	    /* shift the frontal matrix down */
	    F1 = (Entry *) (psrc + 1) ;

	    /* get the size of the current front.  r and c could be zero */
	    k = Work->fnpiv ;
	    dr = Work->fnr_curr ;
	    dc = Work->fnc_curr ;
	    r = Work->fnrows ;
	    c = Work->fncols ;
	    nb = Work->nb ;

	    ASSERT ((dr >= 0 && (dr % 2) == 1) || dr == 0) ;
	    ASSERT (drnew >= 0) ;
	    if (drnew % 2 == 0)
	    {
		/* make sure leading frontal matrix dimension is always odd */
		drnew++ ;
	    }
	    drnew = MIN (dr, drnew) ;
	    ASSERT ((drnew >= 0 && (drnew % 2) == 1) || drnew == 0) ;

	    pnext = pdest ;

#ifndef NDEBUG
	    DEBUGm2 (("move front: dr "ID" dc "ID" r "ID" drnew "ID" c "ID
		" dcnew " ID" k "ID"\n", dr, dc, r, drnew, c, dcnew, k)) ;
	    DEBUG7 (("\n")) ;
	    DEBUG7 ((ID":: Move current frontal matrix from: psrc-S: "ID" \n",
		nmark, (Int) (psrc-Numeric->Memory))) ;
	    nmark-- ;
	    ASSERT (E [e] == 0) ;
	    ASSERT (Work->Flublock == F1) ;
	    ASSERT (Work->Flblock  == Work->Flublock + nb*nb) ;
	    ASSERT (Work->Fublock  == Work->Flblock  + dr*nb) ;
	    ASSERT (Work->Fcblock  == Work->Fublock  + nb*dc) ;
	    DEBUG7 (("C  block: ")) ;
	    UMF_dump_dense (Work->Fcblock,  dr, r, c) ;
	    DEBUG7 (("L  block: ")) ;
	    UMF_dump_dense (Work->Flblock,  dr, r, k);
	    DEBUG7 (("U' block: ")) ;
	    UMF_dump_dense (Work->Fublock,  dc, c, k) ;
	    DEBUG7 (("LU block: ")) ;
	    UMF_dump_dense (Work->Flublock, nb, k, k) ;
	    ASSERT (r <= drnew && c <= dcnew && drnew <= dr && dcnew <= dc) ;
#endif

	    /* compact frontal matrix to drnew-by-dcnew before moving it */

	    /* do not compact the LU block (nb-by-nb) */

	    /* compact the columns of L (from dr-by-nb to drnew-by-nb) */
	    Fsrc = Work->Flblock ;
	    Fdst = Work->Flblock ;
	    ASSERT (Fdst == F1 + nb*nb) ;
	    gap1 = dr - r ;
	    gap2 = drnew - r ;
	    ASSERT (gap1 >= 0) ;
	    for (j = 0 ; j < k ; j++)
	    {
		for (i = 0 ; i < r ; i++)
		{
		    *Fdst++ = *Fsrc++ ;
		}
		Fsrc += gap1 ;
		Fdst += gap2 ;
	    }
	    ASSERT (Fdst == F1 + nb*nb + drnew*k) ;
	    Fdst += drnew * (nb - k) ;

	    /* compact the rows of U (U' from dc-by-nb to dcnew-by-nb) */
	    Fsrc = Work->Fublock ;
	    ASSERT (Fdst == F1 + nb*nb + drnew*nb) ;
	    gap1 = dc - c ;
	    gap2 = dcnew - c ;
	    for (i = 0 ; i < k ; i++)
	    {
		for (j = 0 ; j < c ; j++)
		{
		    *Fdst++ = *Fsrc++ ;
		}
		Fsrc += gap1 ;
		Fdst += gap2 ;
	    }
	    ASSERT (Fdst == F1 + nb*nb + drnew*nb + dcnew*k) ;
	    Fdst += dcnew * (nb - k) ;

	    /* compact the columns of C (from dr-by-dc to drnew-by-dcnew) */
	    Fsrc = Work->Fcblock ;
	    ASSERT (Fdst == F1 + nb*nb + drnew*nb + nb*dcnew) ;
	    gap1 = dr - r ;
	    gap2 = drnew - r ;
	    for (j = 0 ; j < c ; j++)
	    {
		for (i = 0 ; i < r ; i++)
		{
		    *Fdst++ = *Fsrc++ ;
		}
		Fsrc += gap1 ;
		Fdst += gap2 ;
	    }
	    ASSERT (Fdst == F1 + nb*nb + drnew*nb + nb*dcnew + drnew*c) ;

	    /* recompute Fcpos, if necessary */
	    if (do_Fcpos)
	    {
		Int *Fcols, *Fcpos ;
		Fcols = Work->Fcols ;
		Fcpos = Work->Fcpos ;
		for (j = 0 ; j < c ; j++)
		{
		    col = Fcols [j] ;
		    ASSERT (col >= 0 && col < Work->n_col) ;
		    ASSERT (Fcpos [col] == j * dr) ;
		    Fcpos [col] = j * drnew ;
		}
#ifndef NDEBUG
		{
		    Int cnt = 0 ;
		    for (j = 0 ; j < Work->n_col ; j++)
		    {
			if (Fcpos [j] != EMPTY) cnt++ ;
		    }
		    DEBUGm2 (("Recompute Fcpos cnt "ID" c "ID"\n", cnt, c)) ;
		    ASSERT (cnt == c) ;
		}
#endif
	    }

#ifndef NDEBUG
	    DEBUGm2 (("Compacted front, drnew "ID" dcnew "ID"\n", drnew, dcnew)) ;
	    DEBUG7 (("C  block: ")) ;
	    UMF_dump_dense (F1 + nb*nb + drnew*nb + nb*dcnew, drnew, r, c) ;
	    DEBUG7 (("L  block: ")) ;
	    UMF_dump_dense (F1 + nb*nb, drnew, r, k) ;
	    DEBUG7 (("U  block: ")) ;
	    UMF_dump_dense (F1 + nb*nb + drnew*nb, nb, k, c) ;
	    DEBUG7 (("LU block: ")) ;
	    UMF_dump_dense (F1, nb, k, k) ;
#endif

	    /* Compacted dimensions of the new frontal matrix. */
	    Work->fnr_curr = drnew ;
	    Work->fnc_curr = dcnew ;
	    Work->fcurr_size = (drnew + nb) * (dcnew + nb) ;
	    size = UNITS (Entry, Work->fcurr_size) ;

	    /* make sure the object doesn't evaporate.  The front can have
	     * zero size (Work->fcurr_size = 0), but the size of the memory
	     * block containing it cannot have zero size. */
	    size = MAX (1, size) ;

	    /* get the destination of frontal matrix */
	    pnext->header.prevsize = size ;
	    pdest -= (size + 1) ;
	    F2 = (Entry *) (pdest + 1) ;

	    ASSERT ((unsigned Int) psrc + 1 + size <= (unsigned Int) pnext) ;
	    ASSERT (psrc <= pdest) ;
	    ASSERT (F1 <= F2) ;

	    /* move the C block first */
	    Fsrc = F1 + nb*nb + drnew*nb + nb*dcnew + drnew*c ;
	    Fdst = F2 + nb*nb + drnew*nb + nb*dcnew + drnew*c ;
	    gap = drnew - r ;
	    for (j = c-1 ; j >= 0 ; j--)
	    {
		Fsrc -= gap ;
		Fdst -= gap ;
		/* move column j of C */
		for (i = r-1 ; i >= 0 ; i--)
		{
		    *--Fdst = *--Fsrc ;
		}
	    }
	    ASSERT (Fsrc == F1 + nb*nb + drnew*nb + nb*dcnew) ;
	    ASSERT (Fdst == F2 + nb*nb + drnew*nb + nb*dcnew) ;

	    /* move the U block */
	    Fsrc -= dcnew * (nb - k) ;
	    Fdst -= dcnew * (nb - k) ;
	    ASSERT (Fsrc == F1 + nb*nb + drnew*nb + dcnew*k) ;
	    ASSERT (Fdst == F2 + nb*nb + drnew*nb + dcnew*k) ;
	    gap = dcnew - c ;
	    for (i = k-1 ; i >= 0 ; i--)
	    {
		Fsrc -= gap ;
		Fdst -= gap ;
		for (j = c-1 ; j >= 0 ; j--)
		{
		    *--Fdst = *--Fsrc ;
		}
	    }
	    ASSERT (Fsrc == F1 + nb*nb + drnew*nb) ;
	    ASSERT (Fdst == F2 + nb*nb + drnew*nb) ;

	    /* move the L block */
	    Fsrc -= drnew * (nb - k) ;
	    Fdst -= drnew * (nb - k) ;
	    ASSERT (Fsrc == F1 + nb*nb + drnew*k) ;
	    ASSERT (Fdst == F2 + nb*nb + drnew*k) ;
	    gap = drnew - r ;
	    for (j = k-1 ; j >= 0 ; j--)
	    {
		Fsrc -= gap ;
		Fdst -= gap ;
		for (i = r-1 ; i >= 0 ; i--)
		{
		    *--Fdst = *--Fsrc ;
		}
	    }
	    ASSERT (Fsrc == F1 + nb*nb) ;
	    ASSERT (Fdst == F2 + nb*nb) ;

	    /* move the LU block */
	    Fsrc -= nb * (nb - k) ;
	    Fdst -= nb * (nb - k) ;
	    ASSERT (Fsrc == F1 + nb*k) ;
	    ASSERT (Fdst == F2 + nb*k) ;
	    gap = nb - k ;
	    for (j = k-1 ; j >= 0 ; j--)
	    {
		Fsrc -= gap ;
		Fdst -= gap ;
		for (i = k-1 ; i >= 0 ; i--)
		{
		    *--Fdst = *--Fsrc ;
		}
	    }
	    ASSERT (Fsrc == F1) ;
	    ASSERT (Fdst == F2) ;

	    E [0] = (pdest + 1) - Numeric->Memory ;

	    Work->Flublock = (Entry *) (Numeric->Memory + E [0]) ;
	    ASSERT (Work->Flublock == F2) ;
	    Work->Flblock  = Work->Flublock + nb * nb ;
	    Work->Fublock  = Work->Flblock  + drnew * nb ;
	    Work->Fcblock  = Work->Fublock  + nb * dcnew ;

	    pdest->header.prevsize = 0 ;
	    pdest->header.size = size ;

#ifndef NDEBUG
	    DEBUG7 (("After moving compressed current frontal matrix:\n")) ;
	    DEBUG7 (("C  block: ")) ;
	    UMF_dump_dense (Work->Fcblock,  drnew, r, c) ;
	    DEBUG7 (("L  block: ")) ;
	    UMF_dump_dense (Work->Flblock,  drnew, r, k);
	    DEBUG7 (("U' block: ")) ;
	    UMF_dump_dense (Work->Fublock,  dcnew, c, k) ;
	    DEBUG7 (("LU block: ")) ;
	    UMF_dump_dense (Work->Flublock, nb, k, k) ;
#endif

	}
	else if (e > 0)
	{

	    /* -------------------------------------------------------------- */
	    /* this is an element, compress and move from psrc down to pdest */
	    /* -------------------------------------------------------------- */

#ifndef NDEBUG
	    DEBUG7 (("\n")) ;
	    DEBUG7 ((ID":: Move element "ID": from: "ID" \n",
		nmark, e, (Int) (psrc-Numeric->Memory))) ;
	    nmark-- ;
	    ASSERT (e <= nel) ;
	    ASSERT (E [e] == 0) ;
#endif

	    /* -------------------------------------------------------------- */
	    /* get the element scalars, and pointers to C, Rows, and Cols: */
	    /* -------------------------------------------------------------- */

	    p = psrc + 1 ;
	    GET_ELEMENT (epsrc, p, Cols, Rows, ncols, nrows, C) ;
	    nrowsleft = epsrc->nrowsleft ;
	    ncolsleft = epsrc->ncolsleft ;
	    cdeg = epsrc->cdeg ;
	    rdeg = epsrc->rdeg ;

#ifndef NDEBUG
	    DEBUG7 ((" nrows "ID" nrowsleft "ID"\n", nrows, nrowsleft)) ;
	    DEBUG7 ((" ncols "ID" ncolsleft "ID"\n", ncols, ncolsleft)) ;
	    DEBUG8 ((" Rows:")) ;
	    for (i = 0 ; i < nrows ; i++) DEBUG8 ((" "ID, Rows [i])) ;
	    DEBUG8 (("\n Cols:")) ;
	    for (j = 0 ; j < ncols ; j++) DEBUG8 ((" "ID, Cols [j])) ;
	    DEBUG8 (("\n")) ;
#endif

	    /* -------------------------------------------------------------- */
	    /* determine the layout of the new element */
	    /* -------------------------------------------------------------- */

	    csize = nrowsleft * ncolsleft ;
	    size2 = UNITS (Element, 1)
		  + UNITS (Int, nrowsleft + ncolsleft)
		  + UNITS (Entry, csize) ;

	    DEBUG7 (("Old size "ID" New size "ID"\n", size, size2)) ;

	    pnext = pdest ;
	    pnext->header.prevsize = size2 ;
	    pdest -= (size2 + 1) ;

	    ASSERT (size2 <= size) ;
	    ASSERT ((unsigned Int) psrc + 1 + size <= (unsigned Int) pnext) ;
	    ASSERT (psrc <= pdest) ;

	    p = pdest + 1 ;
	    epdest = (Element *) p ;
	    p += UNITS (Element, 1) ;
	    Cols2 = (Int *) p ;
	    Rows2 = Cols2 + ncolsleft ;
	    p += UNITS (Int, nrowsleft + ncolsleft) ;
	    C2 = (Entry *) p ;

	    ASSERT (epdest >= epsrc) ;
	    ASSERT (Rows2 >= Rows) ;
	    ASSERT (Cols2 >= Cols) ;
	    ASSERT (C2 >= C) ;
	    ASSERT (p + UNITS (Entry, csize) == pnext) ;

	    /* -------------------------------------------------------------- */
	    /* move the contribution block */
	    /* -------------------------------------------------------------- */

	    /* overlap = psrc + size + 1 > pdest ; */

	    if (nrowsleft < nrows || ncolsleft < ncols)
	    {

		/* ---------------------------------------------------------- */
		/* compress contribution block in place prior to moving it */
		/* ---------------------------------------------------------- */

		DEBUG7 (("Compress C in place prior to move:\n"));
#ifndef NDEBUG
		UMF_dump_dense (C, nrows, nrows, ncols) ;
#endif
		C1 = C ;
		C3 = C ;
		for (j = 0 ; j < ncols ; j++)
		{
		    if (Cols [j] >= 0)
		    {
			for (i = 0 ; i < nrows ; i++)
			{
			    if (Rows [i] >= 0)
			    {
				*C3++ = C1 [i] ;
			    }
			}
		    }
		    C1 += nrows ;
		}
		ASSERT (C3-C == csize) ;
		DEBUG8 (("Newly compressed contrib. block (all in use):\n")) ;
#ifndef NDEBUG
		UMF_dump_dense (C, nrowsleft, nrowsleft, ncolsleft) ;
#endif
	    }

	    /* shift the contribution block down */
	    C += csize ;
	    C2 += csize ;
	    for (i = 0 ; i < csize ; i++)
	    {
		*--C2 = *--C ;
	    }

	    /* -------------------------------------------------------------- */
	    /* move the row indices */
	    /* -------------------------------------------------------------- */

	    i2 = nrowsleft ;
	    for (i = nrows - 1 ; i >= 0 ; i--)
	    {
		ASSERT (Rows2+i2 >= Rows+i) ;
		if (Rows [i] >= 0)
		{
		    Rows2 [--i2] = Rows [i] ;
		}
	    }
	    ASSERT (i2 == 0) ;

	    j2 = ncolsleft ;
	    for (j = ncols - 1 ; j >= 0 ; j--)
	    {
		ASSERT (Cols2+j2 >= Cols+j) ;
		if (Cols [j] >= 0)
		{
		    Cols2 [--j2] = Cols [j] ;
		}
	    }
	    ASSERT (j2 == 0) ;

	    /* -------------------------------------------------------------- */
	    /* construct the new header */
	    /* -------------------------------------------------------------- */

	    /* E [0...e] is now valid */
	    E [e] = (pdest + 1) - Numeric->Memory ;
	    epdest = (Element *) (pdest + 1) ;

	    epdest->next = EMPTY ;	/* destroys the son list */
	    epdest->ncols = ncolsleft ;
	    epdest->nrows = nrowsleft ;
	    epdest->ncolsleft = ncolsleft ;
	    epdest->nrowsleft = nrowsleft ;
	    epdest->rdeg = rdeg ;
	    epdest->cdeg = cdeg ;

	    ASSERT (size2 <= size) ;
	    pdest->header.prevsize = 0 ;
	    pdest->header.size = size2 ;

	    DEBUG7 (("After moving it:\n")) ;
#ifndef NDEBUG
	    UMF_dump_element (Numeric, Work, e, FALSE) ;
#endif
	}

#ifndef NDEBUG
	else
	{
	    DEBUG8 ((" free\n")) ;
	}
#endif
	DEBUG7 (("psrc "ID"  tail "ID"\n",
	(Int) (psrc-Numeric->Memory), Numeric->itail)) ;
    }

    ASSERT (psrc == Numeric->Memory + Numeric->itail) ;
    ASSERT (nmark == 0) ;

    /* ---------------------------------------------------------------------- */
    /* final tail pointer */
    /* ---------------------------------------------------------------------- */

    ASSERT (pdest >= Numeric->Memory + Numeric->itail) ;
    Numeric->itail = pdest - Numeric->Memory ;
    pdest->header.prevsize = 0 ;
    Numeric->ibig = EMPTY ;
    Numeric->tail_usage = Numeric->size - Numeric->itail ;

    /* ---------------------------------------------------------------------- */
    /* clear the unused E [nel+1 .. Work->elen - 1] */
    /* ---------------------------------------------------------------------- */

    for (e = nel+1 ; e < Work->elen ; e++)
    {
	E [e] = 0 ;
    }

#ifndef NDEBUG
    UMF_dump_packed_memory (Numeric, Work) ;
#endif

    DEBUG8 (("::::GARBAGE COLLECTION DONE::::\n")) ;
}
Packet*
RouteProcessor::handleRequestPacket( const RequestPacket& requestPacket,
                                     char* packetInfo )
{
   DEBUG1( cerr << "***" << endl);
   DEBUG4( cerr << "RouteProcessor::handleRequest" << endl );
   Packet* replyPacket = NULL;

   uint16 subType = requestPacket.getSubType();
      
   if ( m_packetFileName != NULL ) {
      // Use this code to write the packets to disk for later profiling
      FILE* packetFile = fopen("routePacks", "ab");
      uint32 packLen = ntohl(requestPacket.getLength());
      fwrite(&packLen, 4, 1, packetFile);
      fwrite(requestPacket.getBuf(),
             requestPacket.getLength(), 1, packetFile);
      fclose(packetFile);
   }
      
   switch (subType) {
   case Packet::PACKETTYPE_UPDATETRAFFICCOSTREQUEST : {
      DEBUG1(
             MC2INFO("RouteProcessor got UpdatetrafficCostRequestPacket"));
      const UpdateTrafficCostRequestPacket* updateTrafficCostPacket =
         static_cast<const UpdateTrafficCostRequestPacket*>(&requestPacket);
      replyPacket =
         processUpdateTrafficCostRequestPacket(updateTrafficCostPacket);
   }
      break;
         
   case Packet::PACKETTYPE_SUBROUTEREQUEST : {
      mc2dbg << "RouteProcessor got SubRouteRequestPacket - size = "
             << requestPacket.getLength() << endl;
      const RMSubRouteRequestPacket* subRoutePacket =
         static_cast<const RMSubRouteRequestPacket*>(&requestPacket);
      replyPacket = processSubRouteRequestPacket(subRoutePacket);
   }
      break;
         
   case Packet::PACKETTYPE_EDGENODESREQUEST: {
      mc2dbg << "RouteProcessor got EdgeNodesRequestPacket" << endl;
      const EdgeNodesRequestPacket* edgeNodesReq =
         static_cast<const EdgeNodesRequestPacket*>(&requestPacket);
      replyPacket = processEdgeNodesRequestPacket(edgeNodesReq);
   }
      break;
         
   case Packet::PACKETTYPE_IDTRANSLATIONREQUEST: {
      mc2dbg4 << "RouteProcessor got IDTranslationRequestPacket" << endl;
      const IDTranslationRequestPacket* levelReq =
         static_cast<const IDTranslationRequestPacket*>(&requestPacket);
      mc2dbg8 << "Incoming packet:" << endl;
      DEBUG8(
             HEXDUMP(mc2dbg8, levelReq->getBuf(), levelReq->getLength(),""));
      replyPacket = processIDTranslationRequestPacket(levelReq);
      mc2dbg8 << "Outgoing packet:" << endl;
      DEBUG8(HEXDUMP(mc2dbg8, replyPacket->getBuf(),
                     replyPacket->getLength(), ""));
   }
      break;
         
   case Packet::PACKETTYPE_DISTURBANCEPUSH: {
      mc2dbg << "RouteProcessor got DisturbancePushPacket " << endl;
      const DisturbancePushPacket* distPushReq =
         static_cast<const DisturbancePushPacket*>( &requestPacket );
      int nbrDist = processDisturbancePushPacket( distPushReq );
      replyPacket = NULL; // We cannot reply to this.
      // Add info about the number of disturbances.
      sprintf(packetInfo, "ndist = %d", nbrDist);
   }
      break;
   default : {
      mc2log << warn
             << "RouteProcessor received packet with unknown type = "
             << requestPacket.getSubTypeAsString()
             << " ip=" << requestPacket.getOriginIP()
             << ", port=" << requestPacket.getOriginPort() << endl;
      replyPacket = NULL;
   }
   }// end switch

   // If a mapload failed packets in the queue might lack the right map.
   // and need to be sent again
   if((dynamic_cast<ReplyPacket*>(replyPacket) != NULL) &&
      (static_cast<ReplyPacket*>(replyPacket)->getStatus() ==
       StringTable::MAPNOTFOUND)) {
      delete replyPacket;
      replyPacket = new AcknowledgeRequestReplyPacket(&requestPacket,
                                                      StringTable::OK,
                                                      ACKTIME_NOMAP);
   }      


   DEBUG1(cout << endl);
   
   return replyPacket;
} // handleRequest
inline UpdateTrafficCostReplyPacket*
RouteProcessor::processUpdateTrafficCostRequestPacket(
   const UpdateTrafficCostRequestPacket* updateCostsPacket)
{
   mc2dbg2 << "RouteProcessor::processUpdateTrafficCostRequestPacket"
           << endl;
   
   // Temporary trick
   UpdateTrafficCostReplyPacket* reply = 
         new UpdateTrafficCostReplyPacket( updateCostsPacket );
   reply->setStatus(StringTable::OK);
   return reply;
   
   UpdateTrafficCostReplyPacket* replyPacket = NULL;

   if (updateCostsPacket != NULL) {
      
      uint32 mapID = updateCostsPacket->getMapID();
      
      DEBUG8(updateCostsPacket->dump());         
      mc2dbg << "Updating map " << mapID << endl;

      // Get the CalcRoute for the map.
      CalcRoute* calcRoute = getCalcRoute(mapID);
      StringTable::stringCode status = StringTable::OK;
      
      if (calcRoute != NULL) {
         RoutingMap* mapToUpdate = calcRoute->getMap();
            
         uint32 nbrNodesToUpdate = updateCostsPacket->getNbrCosts();
         for (uint32 j = 0; j < nbrNodesToUpdate; j++) {
            
            uint32 nodeID = MAX_UINT32;
            uint32 cost   = MAX_UINT32;
            
            if (updateCostsPacket->getCost(nodeID, cost, j)) {
               
               RoutingNode* node =
                  mapToUpdate->getNodeFromTrueNodeNumber(nodeID);
               
               if (node != NULL) {
                  RoutingConnection* connection =
                     node->getFirstConnection();
                  
                  while (connection != NULL) {
                     RoutingConnectionData* connData =
                        connection->getData();
//                       RoutingNode* toNode =
//                          mapToUpdate->getNode(connection->getIndex());
                     RoutingNode* toNode = connection->getNode();
                     if ( toNode == NULL ) {
                        mc2dbg << "Coulnd't find connection from "
                               << hex << nodeID << " to node with index "
                               << connection << endl;
                        continue;
                     }
                     uint32 costC = connData->getCostB(0) + cost;
                     mapToUpdate->changeConnectionCosts(
                        node,
                        connection,
                        false,
                        connData->getCostA(0),
                        connData->getCostB(0),
                        costC,
                        connData->getVehicleRestriction(false));
                     connection = connection->getNext();
                  }
               }
               else {
                  MC2WARNING("Node not found");
                  cerr << "map " << mapID << "   nodeID: " << hex << nodeID
                       << dec << " (" << nodeID << ")" << endl;
                  status = StringTable::NOTFOUND;
               }
            }
            else {
               cerr << "Could not get cost " << j << endl;
            }
         }
      }
      else {
         handleMapNotFound(mapID, updateCostsPacket);
         status = StringTable::MAPNOTFOUND;
      }
 
      replyPacket = new UpdateTrafficCostReplyPacket(updateCostsPacket);
      replyPacket->setStatus(status);
   } // end if (calcRoute != NULL)
      
   return replyPacket;
} // updateTrafficCostRequestPacket
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
//
core_error_e core_operation_protected_setup_c::next_state()
    {
    DEBUG( "core_operation_protected_setup_c::next_state()" );
    switch( operation_state_m )
        {
        case core_state_init:
            {
            // This state is for initial actions.
            DEBUG( "- core_state_init" );
            DEBUG1S("User selected SSID: ", core_iap_data_m.ssid.length, core_iap_data_m.ssid.ssid);
            
            if ( core_iap_data_m.wpa_preshared_key.key_length == 0 )
                {
                DEBUG( "Using Pushbutton method" );
                is_pushbutton_method_used_m = true_t;
                }
            else
                {
                DEBUG( "Using Pincode method" );
                is_pushbutton_method_used_m = false_t;
                }

            scan_data_m = new ScanList;
            if( !scan_data_m )
                {
                DEBUG( "core_operation_protected_setup_c::next_state() - unable to create ScanList" );
                return core_error_no_memory;
                }
            
            core_callback_c* timer_callback = 
                new core_callback_c( &(core_operation_protected_setup_c::timer_expired), this );
            if( !timer_callback )
                {
                DEBUG( "core_operation_protected_setup_c::next_state() - unable to create callbacks" );
                return core_error_no_memory;
                }

            walktime_timer_m = core_timer_factory_c::create_timer( timer_callback );
            if( !walktime_timer_m )
                {
                DEBUG( "core_operation_protected_setup_c::next_state() - unable to create timer" );
                delete timer_callback;
                return core_error_no_memory;
                }


            if ( server_m->get_core_settings().is_connected() )
                {
                DEBUG( "core_operation_protected_setup_c::next_state() - already connected, completing request" );

                return core_error_connection_already_active;
                }

            // Override the security mode just in case.
            core_iap_data_m.security_mode = core_security_mode_protected_setup;
            
            if ( !server_m->create_eapol_instance( core_eapol_operating_mode_wfa ) )
                {
                DEBUG( "core_operation_protected_setup_c::next_state() - unable to instantiate EAPOL" );
                return core_error_no_memory;
                }

            walktime_timer_m->start( CORE_OPERATION_PROTECTED_SETUP_WALKTIME );
            
            return goto_state( core_state_prepare_scanning );
            }
        // This state is for actions what should be done at start or after core_operation_release_c.
        case core_state_prepare_scanning:
            {
            DEBUG( "- core_state_prepare_scanning" );
            core_error_e ret = server_m->init_connection_data(
                    core_iap_data_m,
                    server_m->get_device_settings() );
            if ( ret != core_error_ok )
                {
                DEBUG1( "core_operation_protected_setup_c::next_state() - unable to initialize connection data (%d)", ret );
                return ret;
                }

            if ( !server_m->get_connection_data()->iap_data().is_eap_used() )
                {
                DEBUG( "core_operation_protected_setup_c::next_state() - is_eap_used() == false, it should be true." );
                return core_error_illegal_argument;
                }

            server_m->get_core_settings().set_connection_state( core_connection_state_searching );
            
            return goto_state( core_state_start_scanning );
            }
            
        case core_state_start_scanning:
            {
            DEBUG( "- core_state_start_scanning" );
            operation_state_m = core_state_scan;
            
            // Clear scanlist 
            ASSERT( scan_data_m );
            scan_data_m->ClearAll();
            
            // add tag to help scanlist iteration
            server_m->get_scan_list().set_tag( tag_m );
            selected_ap_data_m = NULL;
            
            // Broadcast scan is used to detect session overlap.
            // Otherwise this could be direct scan.
            core_operation_base_c* operation = new core_operation_scan_c(
                request_id_m,
                server_m,
                drivers_m,
                adaptation_m,
                core_scan_mode_active,
                BROADCAST_SSID,
                all_valid_scan_channels_m,
                0,
                *scan_data_m,
                false_t,
                false_t );
                
            return run_sub_operation( operation );
            }
            
        case core_state_scan:
            {
            DEBUG( "- core_state_scan" );
            operation_state_m = core_state_MAX; // This is just to spot leak in following switch.
            ++wps_scan_count_m;
            
#ifdef SCANLIST_PARSING_AND_PRINTING

            core_scan_list_iterator_by_tag_c parsing_iter(
                server_m->get_scan_list(),
                tag_m);
            for ( core_ap_data_c* ap_data = parsing_iter.first(); ap_data; ap_data = parsing_iter.next() )
                {
                u8_t buffer[70];
                core_tools_c::fillz(buffer, sizeof(buffer) );
                
                for (u32_t i=0; i<ap_data->ssid().length; ++i)
                    {
                    buffer[2*i]   = ap_data->ssid().ssid[i];
                    buffer[2*i+1] = 0;
                    }
                
                DEBUG8("RADAR: SSID:%s BSSID:%02x.%02x.%02x.%02x.%02x.%02x RCPI:%u",
                    buffer,
                    //ap_data->ssid().ssid,
                    ap_data->bssid().addr[0],
                    ap_data->bssid().addr[1],
                    ap_data->bssid().addr[2],
                    ap_data->bssid().addr[3],
                    ap_data->bssid().addr[4],
                    ap_data->bssid().addr[5],
                    ap_data->rcpi()
                    );
                }
                
#endif // SCANLIST_PARSING_AND_PRINTING

            // Decide whether ap_data should be copied even when selected_registrar is not set.
            bool_t copy_ap_data( false_t );
            if( wps_scan_count_m == 1 ||
                ( wps_scan_count_m >= CORE_OPERATION_PROTECTED_SETUP_ROUNDTRIP_START &&
                  ( wps_scan_count_m % CORE_OPERATION_PROTECTED_SETUP_ROUNDTRIP_INTERVAL == 1 ) ) )
                {
                copy_ap_data = true_t;
                }
            DEBUG2( "core_operation_protected_setup_c::next_state() - wps_scan_count_m=%d, copy_ap_data=%d", wps_scan_count_m, copy_ap_data );
            
            abs_core_scan_list_iterator_c * iter;
            
            if ( is_pushbutton_method_used_m )
                {
                // Pushbutton: Check all APs from scanlist.
                iter = new core_scan_list_iterator_by_tag_c(
                        server_m->get_scan_list(),
                        tag_m);
                }
            else
                {
                // Pincode: Check only APs with given SSID from scanlist.
                iter = new core_scan_list_iterator_by_tag_and_ssid_c(
                        server_m->get_scan_list(),
                        tag_m,
                        core_iap_data_m.ssid);
                }

            u32_t selected_registrar_count( check_selected_registrars( iter, copy_ap_data ) );
            delete iter;
            iter = NULL;
            switch ( selected_registrar_count )
                {
                case 0: // No selected registrars yet. We should wait until some registrar appears
                    {
                    // Second round-trip should not start before selected_registrar is found.
                    if ( !selected_ap_data_m )
                        {
                        // Wait some time before new scan
                        return asynch_goto( core_state_start_scanning, CORE_OPERATION_PROTECTED_SETUP_DELAY_FOR_NEXT_SCAN );
                        }
                    }
                    /* 
                     * This will fall through in first round-trip if selected AP was found.
                     * It means that selected_registrar flag is not required until second round-trip.
                     */
                    //lint -fallthrough
                case 1: // Successfull case: one and only one selected registrar
                    {
                    // AP not found. It is coding error.
                    ASSERT( selected_ap_data_m );
                    
                    // Check that selected registrar is in SSID where it should be...
                    if ( core_iap_data_m.ssid != selected_ap_data_m->ssid() )
                        {
                        // If it is not, then wait some time before new scan
                        DEBUG( "core_operation_protected_setup_c::next_state() - selected registrar is not in wanted AP, ignoring" );
                        return asynch_goto( core_state_start_scanning, CORE_OPERATION_PROTECTED_SETUP_DELAY_FOR_NEXT_SCAN );
                        }
                    if ( selected_registrar_count > 0 )
                        {
                        // selected_registrar == true was found in correct AP.
                        is_selected_registrar_found_m = true_t;
                        }

                    return asynch_goto( core_state_connect_and_setup, CORE_OPERATION_PROTECTED_SETUP_START_DELAY );
                    }
                default: // More than one selected registrar: It means "multiple PBC sessions detected"
                    {
                    // But if we are using pincode method, then we just try connection with first AP.
                    // No need to check SSID, because it is already filtered.
                    if ( !is_pushbutton_method_used_m )
                        {
                        DEBUG1( "core_operation_protected_setup_c::next_state() - %i selected registrars found for the same SSID, trying pincode for first AP.", selected_registrar_count );
                        is_selected_registrar_found_m = true_t;
                        return asynch_goto( core_state_connect_and_setup, CORE_OPERATION_PROTECTED_SETUP_START_DELAY );
                        }
                    
                    protected_setup_status_m = core_protected_setup_status_multiple_PBC_sessions_detected;
                    walktime_timer_m->stop();

                    server_m->get_core_settings().set_connection_state( core_connection_state_notconnected );

                    return core_error_ok;
                    }
                }
            }

        case core_state_connect_and_setup:
            {
            DEBUG( "- core_state_connect_and_setup" );
            
            if ( is_selected_registrar_found_m )
                {
                /**
                 * Walk time timer can be stopped because user has pressed 
                 * Push-button or PIN-code from both phone and registrar.
                 * Do not stop timer, if selected registrar is not found.
                 */
                ASSERT( walktime_timer_m );
                walktime_timer_m->stop();
                }
            
            core_iap_data_c core_iap_data( core_iap_data_m );

            operation_state_m = core_state_setup_completed;
            
            // Add WSC IE to association request
            core_frame_wsc_ie_c* wsc_ie = core_frame_wsc_ie_c::instance(
                CORE_FRAME_WSC_IE_USED_VERSION, 
                CORE_FRAME_WSC_IE_REQUEST_TYPE_ENROLLEE );
            
            if ( wsc_ie == NULL )
                {
                server_m->get_core_settings().set_connection_state( core_connection_state_notconnected );
                return core_error_no_memory;
                }
            assoc_ie_list_m.append(
                wsc_ie,
                wsc_ie->element_id() );
            
            ASSERT( selected_ap_data_m != NULL );
            
            server_m->set_protected_setup_handler( this );
            
            server_m->get_core_settings().set_connection_state( core_connection_state_secureinfra );

            // WPA connect initiates connection and start authentication (in this case starts protected setup)
            core_operation_base_c* operation = new core_sub_operation_wpa_connect_c(
                request_id_m,
                server_m,
                drivers_m,
                adaptation_m,
                is_connected_m,
                management_status_m,
                core_iap_data_m.ssid,
                *selected_ap_data_m,
                is_reassociation_m,
                assoc_ie_list_m,
                NULL );

            return run_sub_operation( operation );
            }

        case core_state_setup_completed:
            {
            DEBUG( "- core_state_setup_completed" );

            protected_setup_status_m = core_protected_setup_status_ok;
            ASSERT( walktime_timer_m );
            walktime_timer_m->stop();

            DEBUG( "Wi-Fi Protected Setup done, starting disconnect." );

            operation_state_m = core_state_disconnect;
            
            core_operation_base_c* operation = new core_operation_release_c(
                request_id_m,
                server_m,
                drivers_m,
                adaptation_m,
                core_release_reason_other );

            return run_sub_operation( operation );
            }
            
        case core_state_disconnect:
            {
            DEBUG( "- core_state_disconnect" );
            server_m->get_core_settings().set_connection_state( core_connection_state_notconnected );
            return core_error_ok;
            }
            
        case core_state_user_cancel:
            {
            DEBUG( "- core_state_user_cancel" );
            
            operation_state_m = core_state_disconnect_on_cancel;
            
            // 
            ASSERT( walktime_timer_m );
            walktime_timer_m->stop();
            
            // We should cancel this timer, because asynch_goto could be ongoing.
            server_m->cancel_operation_timer();
            
            // This is not necessary? operation release will check this also...
            if( server_m->get_core_settings().connection_state() 
                == core_connection_state_secureinfra )
                {
                core_operation_base_c* operation = new core_operation_release_c(
                    request_id_m,
                    server_m,
                    drivers_m,
                    adaptation_m,
                    core_release_reason_external_request );

                return run_sub_operation( operation );
                }
            return next_state( );
            }
            
        case core_state_disconnect_on_cancel:
            {
            DEBUG( "- core_state_disconnect_on_cancel" );

            server_m->get_core_settings().set_connection_state( core_connection_state_notconnected );

            return core_error_cancel;
            }

        case core_state_setup_failed:
            {
            DEBUG( "- core_state_setup_failed" );

            operation_state_m = core_state_disconnect_on_error;
            ASSERT( walktime_timer_m );
            walktime_timer_m->stop();

            // Get EAPOL errorcode before releasing connection.
            wlan_eapol_if_eap_status_e eapol_status = static_cast<wlan_eapol_if_eap_status_e>( server_m->get_connection_data()->last_eap_error() );
            protected_setup_status_m = core_tools_c::convert_eapol_error_to_protected_setup_status( eapol_status );
            
            DEBUG2( "Protected Setup has failed, starting disconnect. (EAPOL status %i, protected setup status %i)",
                    eapol_status,
                    protected_setup_status_m );
            server_m->get_core_settings().set_connection_state( core_connection_state_secureinfra );

            core_operation_base_c* operation = new core_operation_release_c(
                request_id_m,
                server_m,
                drivers_m,
                adaptation_m,
                core_release_reason_other );

            return run_sub_operation( operation );
            }

        case core_state_disconnect_on_error:
            {
            DEBUG( "- core_state_disconnect_on_error" );

            server_m->get_core_settings().set_connection_state( core_connection_state_notconnected );

            DEBUG1( "core_operation_protected_setup_c::next_state() - failure_reason_m is %u",
                failure_reason_m );
            DEBUG1( "core_operation_protected_setup_c::next_state() - management_status_m is %u",
                management_status_m );

            core_error_e ret = protected_setup_status(
                failure_reason_m,
                management_status_m,
                protected_setup_status_m );
            DEBUG1( "core_operation_protected_setup_c::next_state() - returned error code is %u",
                ret );
            DEBUG1( "core_operation_protected_setup_c::next_state() - returned status is %u",
                protected_setup_status_m );

            return ret;
            }

        case core_state_disconnect_before_second_round_trip:
            {
            DEBUG( "- core_state_disconnect_before_second_round_trip" );

            operation_state_m = core_state_prepare_scanning;

            // Get EAPOL errorcode before releasing connection.
            wlan_eapol_if_eap_status_e eapol_status = static_cast<wlan_eapol_if_eap_status_e>( server_m->get_connection_data()->last_eap_error() );
            protected_setup_status_m = core_tools_c::convert_eapol_error_to_protected_setup_status( eapol_status );
            
            DEBUG2( "Protected Setup has failed (first round-trip), starting disconnect. (EAPOL status %i, protected setup status %i)",
                    eapol_status,
                    protected_setup_status_m );
            server_m->get_core_settings().set_connection_state( core_connection_state_secureinfra );

            core_operation_base_c* operation = new core_operation_release_c(
                request_id_m,
                server_m,
                drivers_m,
                adaptation_m,
                core_release_reason_other );

            return run_sub_operation( operation );
            }
        
        case core_state_walktime_expiration:
            {
            DEBUG( "- core_state_walktime_expiration" );

            server_m->get_core_settings().set_connection_state( core_connection_state_notconnected );

            // indicate unsuccessfully completed protected setup
            protected_setup_status_m = core_protected_setup_status_walktime_expired;

            return core_error_ok;
            }
            
        default:
            {
            ASSERT( false_t );
            }
        }
    return core_error_request_pending;
    }
void
GfxCountryMapGenerator::run()
{
   const int maxHandshake = 1024;
   char handshake[maxHandshake];
   
   TCPSocket* socket = waitForConnection(handshake, maxHandshake);

   if ( socket == NULL ) {
      mc2log << error << "No connection for GfxCountryMapGenerator" << endl;
      return;
   }
   
   DEBUG2(uint32 startTime = TimeUtility::getCurrentTime());

   // We've got an request for a map...
   mc2dbg4 << "GfxCountryMapGenerator, sending map with ID " 
           << mapIDs[0] << endl;
   CountryOverviewMap* theMap = 
      dynamic_cast<CountryOverviewMap*>(mapHandler->getMap(mapIDs[0]));
   DEBUG8(cerr << "MAPID " << mapIDs[0] << endl);
      
   // Check if the map is valid or not
   if (theMap != NULL) {
      // OK, map valid!

      uint32 nbrMaps = theMap->getNbrMaps();
      const GfxData* mapGfx = theMap->getGfxData();


      // Calculate the size of the filtered map when written to a buffer.
      uint32 filtMapsBufSize = 0;
      const uint32 nbrFiltLevels = 
         CountryOverviewMap::NBR_SIMPLIFIED_COUNTRY_GFX;
      for (uint32 i = 0; i < nbrFiltLevels; i++ ) {
         for (uint32 j = 0; j < mapGfx->getNbrPolygons(); j++ ) {
            const Stack* filtStack = theMap->getFilterStack(i,j);
            filtMapsBufSize += 4; // writes number of filt stack elements.
            for (uint32 k = 0; k < filtStack->getStackSize(); k++) {
               filtMapsBufSize += 4; // writes filt stack element.
            }
         }            
      }

      // Claculate size of buffer needed.
      uint32 bufSize = 4;     // nbrMaps
      bufSize += nbrMaps * 24; // nbrMaps * (mapId, creationTime, Bbox)
      bufSize += 4;           // polygons closed, nbrPolygons
      bufSize += mapGfx->getNbrPolygons() * 4; // nbr coordinates per polygon.
      bufSize += theMap->getGfxData()->getTotalNbrCoordinates() * 8; // coords.
      bufSize += 4; // nbrFiltLevels
      bufSize += filtMapsBufSize; // Size of the filter data.

      DataBuffer idsAndGfx(bufSize);

      // Note that we multiply the size of the coordinates with two in 
      // order to make space for the filtered versions of the country
      // GfxData as well.
//    DataBuffer idsAndGfx(nbrMaps * 24 + // ID + ver + Bbox
//                         theMap->getGfxData()->getTotalNbrCoordinates()*8*2 +
//                         102400);   // approx gfxdata
      
      idsAndGfx.writeNextLong(nbrMaps);
      for (uint32 i=0; i<nbrMaps; i++) {
         uint32 creationTime;
         int32 maxLat, minLat, maxLon, minLon;
         uint32 mapID = theMap->getMapData(i, creationTime,
                                           maxLat, minLon,
                                           minLat, maxLon);
         idsAndGfx.writeNextLong(mapID);
         idsAndGfx.writeNextLong(creationTime);
         idsAndGfx.writeNextLong(maxLat);
         idsAndGfx.writeNextLong(minLon);
         idsAndGfx.writeNextLong(minLat);
         idsAndGfx.writeNextLong(maxLon);
         mc2dbg1 << "   Wrote mapID=" << mapID << ", version=" 
                 << creationTime << ", bbox="
                 << maxLat << ", " << minLon << ", " << minLat << ", "
                 << maxLon << endl;
      }
      
      // Save the GfxData of the country
      

      //uint32 nbrPolygons = MIN(5, mapGfx->getNbrPolygons());
      uint32 nbrPolygons = 0;
      // The polygons being sorted on nbrCoordinates, we an accept 
      // to skip(send) 5 small polys with many coords, in order to 
      // send larger polygons with fewer coordinates.
      uint32 maxNbrSkipPolys = 5;
      uint32 skipPolys[maxNbrSkipPolys];
      for (uint32 i = 0; i < maxNbrSkipPolys;i++) {
         skipPolys[i] = MAX_UINT32;
      }
      bool cont = true;
      uint32 nbrSkip = 0;
      while (cont && (nbrPolygons < mapGfx->getNbrPolygons())) {
         mc2dbg8 << "poly " << nbrPolygons << " nbrC=" 
                 << mapGfx->getNbrCoordinates(nbrPolygons)
                 << " length=" << mapGfx->getLength(nbrPolygons);
         if (mapGfx->getLength(nbrPolygons) < 35000) {
            skipPolys[nbrSkip] = nbrPolygons;
            mc2dbg8 << "  - \"skipping\" ";
            nbrSkip++;
            if (nbrSkip >= maxNbrSkipPolys) {
               cont = false;
            }
         }
         mc2dbg8 << endl;
         nbrPolygons++;
      }
      // Don't send if any of the small polygons are the last ones..
      uint32 p = maxNbrSkipPolys;
      while ( (p > 0) && (skipPolys[p-1] >= nbrPolygons-1)) {
         if (skipPolys[p-1] == nbrPolygons-1) {
            mc2dbg8 << " skip poly in the end of nbrPolygons" << endl;
            nbrPolygons--;
         }
         p--;
      }

      nbrPolygons=MAX(1, nbrPolygons);
      
      mc2dbg << "Sending " << nbrPolygons << " polygons of "
             << mapGfx->getNbrPolygons() << endl;


      idsAndGfx.writeNextBool(true);        // polygons closed
      idsAndGfx.writeNextByte(0);           // PAD
      idsAndGfx.writeNextShort(nbrPolygons);// # polygons
      for (uint32 p=0; p<nbrPolygons;p++) {
         uint32 nbrCoordinates = mapGfx->getNbrCoordinates(p);
         idsAndGfx.writeNextLong(nbrCoordinates);
         for (uint32 i = 0; i < nbrCoordinates; i++) {
            idsAndGfx.writeNextLong(mapGfx->getLat(p, i));
            idsAndGfx.writeNextLong(mapGfx->getLon(p, i));
         }
      }
      
      // Send filtered gfxdata information.

      // Nbr filtering levels
      idsAndGfx.writeNextLong(nbrFiltLevels);      
      for (uint32 i = 0; i < nbrFiltLevels; i++ ) {
         // Nbr polygons already written before
         for (uint32 j = 0; j < nbrPolygons; j++ ) {
            const Stack* filtStack = theMap->getFilterStack(i,j);
            // Nbr indices in the filtering stack.
            idsAndGfx.writeNextLong(filtStack->getStackSize());
            for (uint32 k = 0; k < filtStack->getStackSize(); k++) {
               // Index
               idsAndGfx.writeNextLong(filtStack->getElementAt(k));
            }
         }            
      }
       
      
      // Create and fill a buffer with the string items in this country
      DataBuffer stringItems(theMap->getMaximunSizeOfStringItems()*2 +
                             40000000); // length of items
      
      if (!theMap->saveStringItems(&stringItems)) {
         mc2log << error <<"Error saving string items for country" << endl;
      }


      // Create and fill buffer with items.
      
      // Nbr items. To be filled in later.
      uint32 offset = stringItems.getCurrentOffset();
      stringItems.writeNextLong(0);
      uint32 maxCountryMapZoom = 3;
      uint32 nbrItems = 0;
      for (uint32 z = 0; z < maxCountryMapZoom; z++) {
         writeItemsInZoomLevel(theMap, &stringItems, z, nbrItems);
      }
      // Fill in nbr items
      stringItems.writeLong(nbrItems, offset);
      
      
      // Create and fill buffer with version and length
      DataBuffer versionAndLengthBuffer(8);
      versionAndLengthBuffer.writeNextLong(theMap->getCreationTime());
      uint32 length = idsAndGfx.getCurrentOffset() +
                      stringItems.getCurrentOffset();
      versionAndLengthBuffer.writeNextLong(length);

      // Send the buffers via TCP
      uint32 nbrBytes = 
         socket->writeAll( versionAndLengthBuffer.getBufferAddress(),
                           versionAndLengthBuffer.getCurrentOffset() );
      mc2dbg4 << "   Sent " << nbrBytes << " with version ("
              << theMap->getCreationTime() << ") and length (" 
              << length << ")" << endl;

      nbrBytes = socket->writeAll( idsAndGfx.getBufferAddress(),
                                   idsAndGfx.getCurrentOffset() );
      mc2dbg4 << "   Sent " << nbrBytes << " with map IDs and GfxData"
              << endl;

      nbrBytes = socket->writeAll( stringItems.getBufferAddress(),
                                   stringItems.getCurrentOffset() );
      mc2dbg4<< "   Sent " << nbrBytes << " with string items"
                  << endl;

      

      // Delete the socket
      delete socket;
   }
   DEBUG2(
   mc2dbg << "GfxCountryMapGenerator sent all data for map " 
               << mapIDs[0] << ", processing time " 
               << TimeUtility::getCurrentTime()-startTime << " ms" << endl;
   );
示例#9
0
GLOBAL Int UMF_create_element
(
    NumericType *Numeric,
    WorkType *Work,
    SymbolicType *Symbolic
)
{
    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

    Int j, col, row, *Fcols, *Frows, fnrows, fncols, *Cols, len, needunits, t1,
        t2, size, e, i, *E, *Fcpos, *Frpos, *Rows, eloc, fnr_curr, f,
        got_memory, *Row_tuples, *Row_degree, *Row_tlen, *Col_tuples, max_mark,
        *Col_degree, *Col_tlen, nn, n_row, n_col, r2, c2, do_Fcpos ;
    Entry *C, *Fcol ;
    Element *ep ;
    Unit *p, *Memory ;
    Tuple *tp, *tp1, *tp2, tuple, *tpend ;
#ifndef NDEBUG
    DEBUG2 (("FRONTAL WRAPUP\n")) ;
    UMF_dump_current_front (Numeric, Work, TRUE) ;
#endif

    /* ---------------------------------------------------------------------- */
    /* get parameters */
    /* ---------------------------------------------------------------------- */

    ASSERT (Work->fnpiv == 0) ;
    ASSERT (Work->fnzeros == 0) ;
    Row_degree = Numeric->Rperm ;
    Row_tuples = Numeric->Uip ;
    Row_tlen   = Numeric->Uilen ;
    Col_degree = Numeric->Cperm ;
    Col_tuples = Numeric->Lip ;
    Col_tlen   = Numeric->Lilen ;
    n_row = Work->n_row ;
    n_col = Work->n_col ;
    nn = MAX (n_row, n_col) ;
    Fcols = Work->Fcols ;
    Frows = Work->Frows ;
    Fcpos = Work->Fcpos ;
    Frpos = Work->Frpos ;
    Memory = Numeric->Memory ;
    fncols = Work->fncols ;
    fnrows = Work->fnrows ;

    tp = (Tuple *) NULL ;
    tp1 = (Tuple *) NULL ;
    tp2 = (Tuple *) NULL ;

    /* ---------------------------------------------------------------------- */
    /* add the current frontal matrix to the degrees of each column */
    /* ---------------------------------------------------------------------- */

    if (!Symbolic->fixQ)
    {
        /* but only if the column ordering is not fixed */
#pragma ivdep
        for (j = 0 ; j < fncols ; j++)
        {
            /* add the current frontal matrix to the degree */
            ASSERT (Fcols [j] >= 0 && Fcols [j] < n_col) ;
            Col_degree [Fcols [j]] += fnrows ;
        }
    }

    /* ---------------------------------------------------------------------- */
    /* add the current frontal matrix to the degrees of each row */
    /* ---------------------------------------------------------------------- */

#pragma ivdep
    for (i = 0 ; i < fnrows ; i++)
    {
        /* add the current frontal matrix to the degree */
        ASSERT (Frows [i] >= 0 && Frows [i] < n_row) ;
        Row_degree [Frows [i]] += fncols ;
    }

    /* ---------------------------------------------------------------------- */
    /* Reset the external degree counters */
    /* ---------------------------------------------------------------------- */

    E = Work->E ;
    max_mark = MAX_MARK (nn) ;

    if (!Work->pivcol_in_front)
    {
        /* clear the external column degrees. no more Usons of current front */
        Work->cdeg0 += (nn + 1) ;
        if (Work->cdeg0 >= max_mark)
        {
            /* guard against integer overflow.  This is very rare */
            DEBUG1 (("Integer overflow, cdeg\n")) ;
            Work->cdeg0 = 1 ;
#pragma ivdep
            for (e = 1 ; e <= Work->nel ; e++)
            {
                if (E [e])
                {
                    ep = (Element *) (Memory + E [e]) ;
                    ep->cdeg = 0 ;
                }
            }
        }
    }

    if (!Work->pivrow_in_front)
    {
        /* clear the external row degrees.  no more Lsons of current front */
        Work->rdeg0 += (nn + 1) ;
        if (Work->rdeg0 >= max_mark)
        {
            /* guard against integer overflow.  This is very rare */
            DEBUG1 (("Integer overflow, rdeg\n")) ;
            Work->rdeg0 = 1 ;
#pragma ivdep
            for (e = 1 ; e <= Work->nel ; e++)
            {
                if (E [e])
                {
                    ep = (Element *) (Memory + E [e]) ;
                    ep->rdeg = 0 ;
                }
            }
        }
    }

    /* ---------------------------------------------------------------------- */
    /* clear row/col offsets */
    /* ---------------------------------------------------------------------- */

    if (!Work->pivrow_in_front)
    {
#pragma ivdep
        for (j = 0 ; j < fncols ; j++)
        {
            Fcpos [Fcols [j]] = EMPTY ;
        }
    }

    if (!Work->pivcol_in_front)
    {
#pragma ivdep
        for (i = 0 ; i < fnrows ; i++)
        {
            Frpos [Frows [i]] = EMPTY ;
        }
    }

    if (fncols <= 0 || fnrows <= 0)
    {
        /* no element to create */
        DEBUG2 (("Element evaporation\n")) ;
        Work->prior_element = EMPTY ;
        return (TRUE) ;
    }

    /* ---------------------------------------------------------------------- */
    /* create element for later assembly */
    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG
    UMF_allocfail = FALSE ;
    if (UMF_gprob > 0)
    {
        double rrr = ((double) (rand ( ))) / (((double) RAND_MAX) + 1) ;
        DEBUG4 (("Check random %e %e\n", rrr, UMF_gprob)) ;
        UMF_allocfail = rrr < UMF_gprob ;
        if (UMF_allocfail) DEBUGm2 (("Random garbage collection (create)\n"));
    }
#endif

    needunits = 0 ;
    got_memory = FALSE ;
    eloc = UMF_mem_alloc_element (Numeric, fnrows, fncols, &Rows, &Cols, &C,
                                  &needunits, &ep) ;

    /* if UMF_get_memory needs to be called */
    if (Work->do_grow)
    {
        /* full compaction of current frontal matrix, since UMF_grow_front will
         * be called next anyway. */
        r2 = fnrows ;
        c2 = fncols ;
        do_Fcpos = FALSE ;
    }
    else
    {
        /* partial compaction. */
        r2 = MAX (fnrows, Work->fnrows_new + 1) ;
        c2 = MAX (fncols, Work->fncols_new + 1) ;
        /* recompute Fcpos if pivot row is in the front */
        do_Fcpos = Work->pivrow_in_front ;
    }

    if (!eloc)
    {
        /* Do garbage collection, realloc, and try again. */
        /* Compact the current front if it needs to grow anyway. */
        /* Note that there are no pivot rows or columns in the current front */
        DEBUGm3 (("get_memory from umf_create_element, 1\n")) ;
        if (!UMF_get_memory (Numeric, Work, needunits, r2, c2, do_Fcpos))
        {
            /* :: out of memory in umf_create_element (1) :: */
            DEBUGm4 (("out of memory: create element (1)\n")) ;
            return (FALSE) ;	/* out of memory */
        }
        got_memory = TRUE ;
        Memory = Numeric->Memory ;
        eloc = UMF_mem_alloc_element (Numeric, fnrows, fncols, &Rows, &Cols, &C,
                                      &needunits, &ep) ;
        ASSERT (eloc >= 0) ;
        if (!eloc)
        {
            /* :: out of memory in umf_create_element (2) :: */
            DEBUGm4 (("out of memory: create element (2)\n")) ;
            return (FALSE) ;	/* out of memory */
        }
    }

    e = ++(Work->nel) ;	/* get the name of this new frontal matrix */
    Work->prior_element = e ;
    DEBUG8 (("wrapup e "ID" nel "ID"\n", e, Work->nel)) ;

    ASSERT (e > 0 && e < Work->elen) ;
    ASSERT (E [e] == 0) ;
    E [e] = eloc ;

    if (Work->pivcol_in_front)
    {
        /* the new element is a Uson of the next frontal matrix */
        ep->cdeg = Work->cdeg0 ;
    }

    if (Work->pivrow_in_front)
    {
        /* the new element is an Lson of the next frontal matrix */
        ep->rdeg = Work->rdeg0 ;
    }

    /* ---------------------------------------------------------------------- */
    /* copy frontal matrix into the new element */
    /* ---------------------------------------------------------------------- */

#pragma ivdep
    for (i = 0 ; i < fnrows ; i++)
    {
        Rows [i] = Frows [i] ;
    }
#pragma ivdep
    for (i = 0 ; i < fncols ; i++)
    {
        Cols [i] = Fcols [i] ;
    }
    Fcol = Work->Fcblock ;
    DEBUG0 (("copy front "ID" by "ID"\n", fnrows, fncols)) ;
    fnr_curr = Work->fnr_curr ;
    ASSERT (fnr_curr >= 0 && fnr_curr % 2 == 1) ;
    for (j = 0 ; j < fncols ; j++)
    {
        copy_column (fnrows, Fcol, C) ;
        Fcol += fnr_curr ;
        C += fnrows ;
    }

    DEBUG8 (("element copied\n")) ;

    /* ---------------------------------------------------------------------- */
    /* add tuples for the new element */
    /* ---------------------------------------------------------------------- */

    tuple.e = e ;

    if (got_memory)
    {

        /* ------------------------------------------------------------------ */
        /* UMF_get_memory ensures enough space exists for each new tuple */
        /* ------------------------------------------------------------------ */

        /* place (e,f) in the element list of each column */
        for (tuple.f = 0 ; tuple.f < fncols ; tuple.f++)
        {
            col = Fcols [tuple.f] ;
            ASSERT (col >= 0 && col < n_col) ;
            ASSERT (NON_PIVOTAL_COL (col)) ;
            ASSERT (Col_tuples [col]) ;
            tp = ((Tuple *) (Memory + Col_tuples [col])) + Col_tlen [col]++ ;
            *tp = tuple ;
        }

        /* ------------------------------------------------------------------ */

        /* place (e,f) in the element list of each row */
        for (tuple.f = 0 ; tuple.f < fnrows ; tuple.f++)
        {
            row = Frows [tuple.f] ;
            ASSERT (row >= 0 && row < n_row) ;
            ASSERT (NON_PIVOTAL_ROW (row)) ;
            ASSERT (Row_tuples [row]) ;
            tp = ((Tuple *) (Memory + Row_tuples [row])) + Row_tlen [row]++ ;
            *tp = tuple ;
        }

    }
    else
    {

        /* ------------------------------------------------------------------ */
        /* place (e,f) in the element list of each column */
        /* ------------------------------------------------------------------ */

        /* might not have enough space for each tuple */

        for (tuple.f = 0 ; tuple.f < fncols ; tuple.f++)
        {
            col = Fcols [tuple.f] ;
            ASSERT (col >= 0 && col < n_col) ;
            ASSERT (NON_PIVOTAL_COL (col)) ;
            t1 = Col_tuples [col] ;
            DEBUG1 (("Placing on col:"ID" , tuples at "ID"\n",
                     col, Col_tuples [col])) ;

            size = 0 ;
            len = 0 ;

            if (t1)
            {
                p = Memory + t1 ;
                tp = (Tuple *) p ;
                size = GET_BLOCK_SIZE (p) ;
                len = Col_tlen [col] ;
                tp2 = tp + len ;
            }

            needunits = UNITS (Tuple, len + 1) ;
            DEBUG1 (("len: "ID" size: "ID" needunits: "ID"\n",
                     len, size, needunits));

            if (needunits > size && t1)
            {
                /* prune the tuples */
                tp1 = tp ;
                tp2 = tp ;
                tpend = tp + len ;
                for ( ; tp < tpend ; tp++)
                {
                    e = tp->e ;
                    ASSERT (e > 0 && e <= Work->nel) ;
                    if (!E [e]) continue ;   /* element already deallocated */
                    f = tp->f ;
                    p = Memory + E [e] ;
                    ep = (Element *) p ;
                    p += UNITS (Element, 1) ;
                    Cols = (Int *) p ;
                    ;
                    if (Cols [f] == EMPTY) continue ;	/* already assembled */
                    ASSERT (col == Cols [f]) ;
                    *tp2++ = *tp ;	/* leave the tuple in the list */
                }
                len = tp2 - tp1 ;
                Col_tlen [col] = len ;
                needunits = UNITS (Tuple, len + 1) ;
            }

            if (needunits > size)
            {
                /* no room exists - reallocate elsewhere */
                DEBUG1 (("REALLOCATE Col: "ID", size "ID" to "ID"\n",
                         col, size, 2*needunits)) ;

#ifndef NDEBUG
                UMF_allocfail = FALSE ;
                if (UMF_gprob > 0)  /* a double relop, but ignore NaN case */
                {
                    double rrr = ((double) (rand ( ))) /
                                 (((double) RAND_MAX) + 1) ;
                    DEBUG1 (("Check random %e %e\n", rrr, UMF_gprob)) ;
                    UMF_allocfail = rrr < UMF_gprob ;
                    if (UMF_allocfail) DEBUGm2 (("Random gar. (col tuple)\n")) ;
                }
#endif

                needunits = MIN (2*needunits, (Int) UNITS (Tuple, nn)) ;
                t2 = UMF_mem_alloc_tail_block (Numeric, needunits) ;
                if (!t2)
                {
                    /* :: get memory in umf_create_element (1) :: */
                    /* get memory, reconstruct all tuple lists, and return */
                    /* Compact the current front if it needs to grow anyway. */
                    /* Note: no pivot rows or columns in the current front */
                    DEBUGm4 (("get_memory from umf_create_element, 1\n")) ;
                    return (UMF_get_memory (Numeric, Work, 0, r2, c2,do_Fcpos));
                }
                Col_tuples [col] = t2 ;
                tp2 = (Tuple *) (Memory + t2) ;
                if (t1)
                {
                    for (i = 0 ; i < len ; i++)
                    {
                        *tp2++ = *tp1++ ;
                    }
                    UMF_mem_free_tail_block (Numeric, t1) ;
                }
            }

            /* place the new (e,f) tuple in the element list of the column */
            Col_tlen [col]++ ;
            *tp2 = tuple ;
        }

        /* ------------------------------------------------------------------ */
        /* place (e,f) in the element list of each row */
        /* ------------------------------------------------------------------ */

        for (tuple.f = 0 ; tuple.f < fnrows ; tuple.f++)
        {
            row = Frows [tuple.f] ;
            ASSERT (row >= 0 && row < n_row) ;
            ASSERT (NON_PIVOTAL_ROW (row)) ;
            t1 = Row_tuples [row] ;
            DEBUG1 (("Placing on row:"ID" , tuples at "ID"\n",
                     row, Row_tuples [row])) ;

            size = 0 ;
            len = 0 ;
            if (t1)
            {
                p = Memory + t1 ;
                tp = (Tuple *) p ;
                size = GET_BLOCK_SIZE (p) ;
                len = Row_tlen [row] ;
                tp2 = tp + len ;
            }

            needunits = UNITS (Tuple, len + 1) ;
            DEBUG1 (("len: "ID" size: "ID" needunits: "ID"\n",
                     len, size, needunits)) ;

            if (needunits > size && t1)
            {
                /* prune the tuples */
                tp1 = tp ;
                tp2 = tp ;
                tpend = tp + len ;
                for ( ; tp < tpend ; tp++)
                {
                    e = tp->e ;
                    ASSERT (e > 0 && e <= Work->nel) ;
                    if (!E [e])
                    {
                        continue ;	/* element already deallocated */
                    }
                    f = tp->f ;
                    p = Memory + E [e] ;
                    ep = (Element *) p ;
                    p += UNITS (Element, 1) ;
                    Cols = (Int *) p ;
                    Rows = Cols + (ep->ncols) ;
                    if (Rows [f] == EMPTY) continue ;	/* already assembled */
                    ASSERT (row == Rows [f]) ;
                    *tp2++ = *tp ;	/* leave the tuple in the list */
                }
                len = tp2 - tp1 ;
                Row_tlen [row] = len ;
                needunits = UNITS (Tuple, len + 1) ;
            }

            if (needunits > size)
            {
                /* no room exists - reallocate elsewhere */
                DEBUG1 (("REALLOCATE Row: "ID", size "ID" to "ID"\n",
                         row, size, 2*needunits)) ;

#ifndef NDEBUG
                UMF_allocfail = FALSE ;
                if (UMF_gprob > 0)  /* a double relop, but ignore NaN case */
                {
                    double rrr = ((double) (rand ( ))) /
                                 (((double) RAND_MAX) + 1) ;
                    DEBUG1 (("Check random %e %e\n", rrr, UMF_gprob)) ;
                    UMF_allocfail = rrr < UMF_gprob ;
                    if (UMF_allocfail) DEBUGm2 (("Random gar. (row tuple)\n")) ;
                }
#endif

                needunits = MIN (2*needunits, (Int) UNITS (Tuple, nn)) ;
                t2 = UMF_mem_alloc_tail_block (Numeric, needunits) ;
                if (!t2)
                {
                    /* :: get memory in umf_create_element (2) :: */
                    /* get memory, reconstruct all tuple lists, and return */
                    /* Compact the current front if it needs to grow anyway. */
                    /* Note: no pivot rows or columns in the current front */
                    DEBUGm4 (("get_memory from umf_create_element, 2\n")) ;
                    return (UMF_get_memory (Numeric, Work, 0, r2, c2,do_Fcpos));
                }
                Row_tuples [row] = t2 ;
                tp2 = (Tuple *) (Memory + t2) ;
                if (t1)
                {
                    for (i = 0 ; i < len ; i++)
                    {
                        *tp2++ = *tp1++ ;
                    }
                    UMF_mem_free_tail_block (Numeric, t1) ;
                }
            }

            /* place the new (e,f) tuple in the element list of the row */
            Row_tlen [row]++ ;
            *tp2 = tuple ;
        }

    }

    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG
    DEBUG1 (("Done extending\nFINAL: element row pattern: len="ID"\n", fncols));
    for (j = 0 ; j < fncols ; j++) DEBUG1 ((""ID"\n", Fcols [j])) ;
    DEBUG1 (("FINAL: element col pattern:  len="ID"\n", fnrows)) ;
    for (j = 0 ; j < fnrows ; j++) DEBUG1 ((""ID"\n", Frows [j])) ;
    for (j = 0 ; j < fncols ; j++)
    {
        col = Fcols [j] ;
        ASSERT (col >= 0 && col < n_col) ;
        UMF_dump_rowcol (1, Numeric, Work, col, !Symbolic->fixQ) ;
    }
    for (j = 0 ; j < fnrows ; j++)
    {
        row = Frows [j] ;
        ASSERT (row >= 0 && row < n_row) ;
        UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ;
    }
    if (n_row < 1000 && n_col < 1000)
    {
        UMF_dump_memory (Numeric) ;
    }
    DEBUG1 (("New element, after filling with stuff: "ID"\n", e)) ;
    UMF_dump_element (Numeric, Work, e, TRUE) ;
    if (nn < 1000)
    {
        DEBUG4 (("Matrix dump, after New element: "ID"\n", e)) ;
        UMF_dump_matrix (Numeric, Work, TRUE) ;
    }
    DEBUG3 (("FRONTAL WRAPUP DONE\n")) ;
#endif

    return (TRUE) ;
}