/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


#define DBTUP_C
#include "Dbtup.hpp"
#include <RefConvert.hpp>
#include <ndb_limits.h>
#include <pc.hpp>
#include <signaldata/FsConf.hpp>
#include <signaldata/FsRemoveReq.hpp>
#include <signaldata/DropTab.hpp>
#include <signaldata/AlterTab.hpp>
#include <AttributeDescriptor.hpp>
#include "AttributeOffset.hpp"

#define ljam() { jamLine(20000 + __LINE__); }
#define ljamEntry() { jamEntryLine(20000 + __LINE__); }

/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
/* --------------- ADD/DROP FRAGMENT TABLE MODULE ----------------- */
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
void Dbtup::execTUPFRAGREQ(Signal* signal)
{
  FragoperrecPtr fragOperPtr;
  FragrecordPtr regFragPtr;
  TablerecPtr regTabPtr;

  ljamEntry();
  Uint32 userptr = signal->theData[0];
  Uint32 userblockref = signal->theData[1];
  Uint32 reqinfo = signal->theData[2];
  regTabPtr.i = signal->theData[3];
  Uint32 noOfAttributes = signal->theData[4];
  Uint32 fragId = signal->theData[5];
  Uint32 noOfNullAttr = signal->theData[7];
  /*  Uint32 schemaVersion = signal->theData[8];*/
  Uint32 noOfKeyAttr = signal->theData[9];

  Uint32 noOfNewAttr = signal->theData[10];
  Uint32 checksumIndicator = signal->theData[11];
  Uint32 noOfAttributeGroups = signal->theData[12];
  Uint32 globalCheckpointIdIndicator = signal->theData[13];

  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
  if (cfirstfreeFragopr == RNIL) {
    ljam();
    signal->theData[0] = userptr;
    signal->theData[1] = ZNOFREE_FRAGOP_ERROR;
    sendSignal(userblockref, GSN_TUPFRAGREF, signal, 2, JBB);
    return;
  }//if
  seizeFragoperrec(fragOperPtr);

  fragOperPtr.p->nextFragoprec = RNIL;
  fragOperPtr.p->lqhBlockrefFrag = userblockref;
  fragOperPtr.p->lqhPtrFrag = userptr;
  fragOperPtr.p->fragidFrag = fragId;
  fragOperPtr.p->tableidFrag = regTabPtr.i;
  fragOperPtr.p->attributeCount = noOfAttributes;
  fragOperPtr.p->freeNullBit = noOfNullAttr;
  fragOperPtr.p->noOfNewAttrCount = noOfNewAttr;

  ndbrequire(reqinfo == ZADDFRAG);

  getFragmentrec(regFragPtr, fragId, regTabPtr.p);
  if (regFragPtr.i != RNIL) {
    ljam();
    terrorCode = ZEXIST_FRAG_ERROR;	/* THE FRAGMENT ALREADY EXIST */
    fragrefuse1Lab(signal, fragOperPtr);
    return;
  }//if
  if (cfirstfreefrag != RNIL) {
    ljam();
    seizeFragrecord(regFragPtr);
  } else {
    ljam();
    terrorCode = ZFULL_FRAGRECORD_ERROR;
    fragrefuse1Lab(signal, fragOperPtr);
    return;
  }//if
  initFragRange(regFragPtr.p);
  if (!addfragtotab(regTabPtr.p, fragId, regFragPtr.i)) {
    ljam();
    terrorCode = ZNO_FREE_TAB_ENTRY_ERROR;
    fragrefuse2Lab(signal, fragOperPtr, regFragPtr);
    return;
  }//if
  if (cfirstfreerange == RNIL) {
    ljam();
    terrorCode = ZNO_FREE_PAGE_RANGE_ERROR;
    fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
    return;
  }//if

  regFragPtr.p->emptyPrimPage = RNIL;
  regFragPtr.p->thFreeFirst = RNIL;
  regFragPtr.p->thFreeCopyFirst = RNIL;
  regFragPtr.p->noCopyPagesAlloc = 0;
  regFragPtr.p->fragTableId = regTabPtr.i;
  regFragPtr.p->fragmentId = fragId;
  regFragPtr.p->checkpointVersion = RNIL;

  Uint32 noAllocatedPages = 2;
  noAllocatedPages = allocFragPages(regFragPtr.p, noAllocatedPages);

  if (noAllocatedPages == 0) {
    ljam();
    terrorCode = ZNO_PAGES_ALLOCATED_ERROR;
    fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
    return;
  }//if

  if (regTabPtr.p->tableStatus == NOT_DEFINED) {
    ljam();
//-------------------------------------------------------------------------------------
// We are setting up references to the header of the tuple.
// Active operation  This word contains a reference to the operation active on the tuple
//                   at the moment. RNIL means no one active at all.  Not optional.
// Tuple version     Uses only low 16 bits.  Not optional.
// Checksum          The third header word is optional and contains a checksum of the
//                   tuple header.
// Null-bits         A number of words to contain null bits for all non-dynamic attributes.
//                   Each word contains upto 32 null bits. Each time a new word is needed
//                   we allocate the complete word. Zero nullable attributes means that
//                   there is no word at all
// Global Checkpoint id
//                   This word is optional. When used it is stored as a 32-bit unsigned
//                   attribute with attribute identity 0. Thus the kernel assumes that
//                   this is the first word after the header.
//-------------------------------------------------------------------------------------
    fragOperPtr.p->definingFragment = true;
    regTabPtr.p->tableStatus = DEFINING;
    regTabPtr.p->checksumIndicator = (checksumIndicator != 0 ? true : false);
    regTabPtr.p->GCPIndicator = (globalCheckpointIdIndicator != 0 ? true : false);

    regTabPtr.p->tupChecksumIndex = 2;
    regTabPtr.p->tupNullIndex = 2 + (checksumIndicator != 0 ? 1 : 0);
    regTabPtr.p->tupNullWords = (noOfNullAttr + 31) >> 5;
    regTabPtr.p->tupGCPIndex = regTabPtr.p->tupNullIndex + regTabPtr.p->tupNullWords;
    regTabPtr.p->tupheadsize = regTabPtr.p->tupGCPIndex;

    regTabPtr.p->noOfKeyAttr = noOfKeyAttr;
    regTabPtr.p->noOfAttr = noOfAttributes;
    regTabPtr.p->noOfNewAttr = noOfNewAttr;
    regTabPtr.p->noOfNullAttr = noOfNullAttr;
    regTabPtr.p->noOfAttributeGroups = noOfAttributeGroups;

    regTabPtr.p->notNullAttributeMask.clear();

    Uint32 tableDescriptorRef = allocTabDescr(noOfAttributes, noOfKeyAttr, noOfAttributeGroups);
    if (tableDescriptorRef == RNIL) {
      ljam();
      fragrefuse4Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
      return;
    }//if
    setUpDescriptorReferences(tableDescriptorRef, regTabPtr.p);
  } else {
    ljam();
    fragOperPtr.p->definingFragment = false;
  }//if
  signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
  signal->theData[1] = fragOperPtr.i;
  signal->theData[2] = regFragPtr.i;
  signal->theData[3] = fragId;
  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUPFRAGCONF, signal, 4, JBB);
  return;
}//Dbtup::execTUPFRAGREQ()

/* -------------------------------------------------------------------- */
/* ------------------------- ADDFRAGTOTAB ----------------------------- */
/* PUTS A FRAGMENT POINTER AND FID IN THE TABLE ARRAY OF THE TID RECORD */
/* -------------------------------------------------------------------- */
bool Dbtup::addfragtotab(Tablerec* const regTabPtr, Uint32 fragId, Uint32 fragIndex) 
{
  for (Uint32 i = 0; i < (2 * NO_OF_FRAG_PER_NODE); i++) {
    ljam();
    if (regTabPtr->fragid[i] == RNIL) {
      ljam();
      regTabPtr->fragid[i] = fragId;
      regTabPtr->fragrec[i] = fragIndex;
      return true;
    }//if
  }//for
  return false;
}//Dbtup::addfragtotab()

void Dbtup::getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* const regTabPtr) 
{
  for (Uint32 i = 0; i < (2 * NO_OF_FRAG_PER_NODE); i++) {
    ljam();
    if (regTabPtr->fragid[i] == fragId) {
      ljam();
/* ---------------------------------------------------------------- */
/* A FRAGMENT  RECORD HAVE BEEN FOUND FOR THIS OPERATION.           */
/* ---------------------------------------------------------------- */
      regFragPtr.i = regTabPtr->fragrec[i];
      ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
      return;
    }//if
  }//for
  regFragPtr.i = RNIL;
  ptrNull(regFragPtr);
}//Dbtup::getFragmentrec()

void Dbtup::seizeFragrecord(FragrecordPtr& regFragPtr) 
{
  regFragPtr.i = cfirstfreefrag;
  ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
  cfirstfreefrag = regFragPtr.p->nextfreefrag;
  regFragPtr.p->nextfreefrag = RNIL;
}//Dbtup::seizeFragrecord()

/* ---------------------------------------------------------------- */
/* SEIZE A FRAGMENT OPERATION RECORD                                */
/* ---------------------------------------------------------------- */
void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr) 
{
  fragOperPtr.i = cfirstfreeFragopr;
  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
  cfirstfreeFragopr = fragOperPtr.p->nextFragoprec;
  fragOperPtr.p->nextFragoprec = RNIL;
}//Dbtup::seizeFragoperrec()

/* **************************************************************** */
/* **************          TUP_ADD_ATTRREQ       ****************** */
/* **************************************************************** */
void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
{
  FragrecordPtr regFragPtr;
  FragoperrecPtr fragOperPtr;
  TablerecPtr regTabPtr;

  ljamEntry();
  fragOperPtr.i = signal->theData[0];
  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
  Uint32 attrId = signal->theData[2];
  Uint32 attrDescriptor = signal->theData[3];

  regTabPtr.i = fragOperPtr.p->tableidFrag;
  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);

  Uint32 fragId = fragOperPtr.p->fragidFrag;

  getFragmentrec(regFragPtr, fragId, regTabPtr.p);
  ndbrequire(regFragPtr.i != RNIL);

  ndbrequire(fragOperPtr.p->attributeCount > 0);
  fragOperPtr.p->attributeCount--;

  if ((regTabPtr.p->tableStatus == DEFINING) &&
      (fragOperPtr.p->definingFragment)) {
    ljam();
    Uint32 firstTabDesIndex = regTabPtr.p->tabDescriptor + (attrId * ZAD_SIZE);
    setTabDescrWord(firstTabDesIndex, attrDescriptor);
    Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
    Uint32 nullBitPos = 0;                  /* Default pos for NOT NULL attributes */
    if (AttributeDescriptor::getNullable(attrDescriptor)) {
      if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
        ljam();                                                      /* NULL ATTR */
        fragOperPtr.p->freeNullBit--;	                           /* STORE NULL BIT POSTITION */
        nullBitPos = fragOperPtr.p->freeNullBit;
        ndbrequire(fragOperPtr.p->freeNullBit < ZNIL);               /* Check not below zero */
      }//if
    } else {
      ljam();
      regTabPtr.p->notNullAttributeMask.set(attrId);
    }//if

    Uint32 attrDes2 = 0;
    if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
      ljam();
      Uint32 attributePos = regTabPtr.p->tupheadsize;
      switch (AttributeDescriptor::getArrayType(attrDescriptor)) {
      case 1:
      case 2:
      {
        ljam();
        Uint32 bitsUsed = AttributeDescriptor::getArraySize(attrDescriptor) * (1 << attrLen);
        regTabPtr.p->tupheadsize += ((bitsUsed + 31) >> 5);
        break;
      }
      default:
        ndbrequire(false);
        break;
      }//switch
      AttributeOffset::setOffset(attrDes2, attributePos);
      AttributeOffset::setNullFlagPos(attrDes2, nullBitPos);
    } else {
      ndbrequire(false);
    }//if
    setTabDescrWord(firstTabDesIndex + 1, attrDes2);

    if (regTabPtr.p->tupheadsize > MAX_TUPLE_SIZE_IN_WORDS) {
      ljam();
      terrorCode = ZTOO_LARGE_TUPLE_ERROR;
      addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
      return;
    }//if
    if ((fragOperPtr.p->attributeCount == 0) &&
        (fragOperPtr.p->freeNullBit != 0)) {
      ljam();
      terrorCode = ZINCONSISTENT_NULL_ATTRIBUTE_COUNT;
      addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
      return;
    }//if
  }//if
/* **************************************************************** */
/* **************          TUP_ADD_ATTCONF       ****************** */
/* **************************************************************** */
  signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, signal, 1, JBB);
  if (fragOperPtr.p->attributeCount > 0) {
    ljam();
    return;	/* EXIT AND WAIT FOR MORE */
  }//if
  regFragPtr.p->fragStatus = ACTIVE;
  if (regTabPtr.p->tableStatus == DEFINING) {
    ljam();
    setUpQueryRoutines(regTabPtr.p);
    setUpKeyArray(regTabPtr.p);
    regTabPtr.p->tableStatus = DEFINED;
  }//if
  releaseFragoperrec(fragOperPtr);
  return;
}//Dbtup::execTUP_ADD_ATTRREQ()

void Dbtup::setUpDescriptorReferences(Uint32 descriptorReference,
                                      Tablerec* const regTabPtr)
{
  Uint32 noOfAttributes = regTabPtr->noOfAttr;
  descriptorReference += ZTD_SIZE;
  ReadFunction * tmp = (ReadFunction*)&tableDescriptor[descriptorReference].tabDescr;
  regTabPtr->readFunctionArray = tmp;
  regTabPtr->updateFunctionArray = (UpdateFunction*)(tmp + noOfAttributes);

  TableDescriptor * start = &tableDescriptor[descriptorReference];
  TableDescriptor * end = (TableDescriptor*)(tmp + 2 * noOfAttributes);
  regTabPtr->readKeyArray = descriptorReference + (end - start);
  regTabPtr->attributeGroupDescriptor = regTabPtr->readKeyArray + regTabPtr->noOfKeyAttr;
  regTabPtr->tabDescriptor = regTabPtr->attributeGroupDescriptor + regTabPtr->noOfAttributeGroups;
}//Dbtup::setUpDescriptorReferences()

Uint32
Dbtup::sizeOfReadFunction()
{
  ReadFunction* tmp = (ReadFunction*)&tableDescriptor[0];
  TableDescriptor* start = &tableDescriptor[0];
  TableDescriptor * end = (TableDescriptor*)(tmp + 1);
  return (Uint32)(end - start);
}//Dbtup::sizeOfReadFunction()

void Dbtup::setUpKeyArray(Tablerec* const regTabPtr)
{
  ndbrequire((regTabPtr->readKeyArray + regTabPtr->noOfKeyAttr) < cnoOfTabDescrRec);
  Uint32* keyArray = &tableDescriptor[regTabPtr->readKeyArray].tabDescr;
  Uint32 countKeyAttr = 0;
  for (Uint32 i = 0; i < regTabPtr->noOfAttr; i++) {
    ljam();
    Uint32 refAttr = regTabPtr->tabDescriptor + (i * ZAD_SIZE);
    Uint32 attrDescriptor = getTabDescrWord(refAttr);
    if (AttributeDescriptor::getPrimaryKey(attrDescriptor)) {
      ljam();
      AttributeHeader::init(&keyArray[countKeyAttr], i, 0);
      countKeyAttr++;
    }//if
  }//for
  ndbrequire(countKeyAttr == regTabPtr->noOfKeyAttr);
}//Dbtup::setUpKeyArray()

void Dbtup::addattrrefuseLab(Signal* signal,
                             FragrecordPtr regFragPtr,
                             FragoperrecPtr fragOperPtr,
                             Tablerec* const regTabPtr,
                             Uint32 fragId) 
{
  releaseFragPages(regFragPtr.p);
  deleteFragTab(regTabPtr, fragId);
  releaseFragrec(regFragPtr);
  releaseTabDescr(regTabPtr);
  initTab(regTabPtr);

  signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
  signal->theData[1] = terrorCode;
  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTRREF, signal, 2, JBB);
  releaseFragoperrec(fragOperPtr);
  return;
}//Dbtup::addattrrefuseLab()

void Dbtup::fragrefuse4Lab(Signal* signal,
                           FragoperrecPtr fragOperPtr,
                           FragrecordPtr regFragPtr,
                           Tablerec* const regTabPtr,
                           Uint32 fragId) 
{
  releaseFragPages(regFragPtr.p);
  fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr, fragId);
  initTab(regTabPtr);
  return;
}//Dbtup::fragrefuse4Lab()

void Dbtup::fragrefuse3Lab(Signal* signal,
                           FragoperrecPtr fragOperPtr,
                           FragrecordPtr regFragPtr,
                           Tablerec* const regTabPtr,
                           Uint32 fragId) 
{
  fragrefuse2Lab(signal, fragOperPtr, regFragPtr);
  deleteFragTab(regTabPtr, fragId);
  return;
}//Dbtup::fragrefuse3Lab()

void Dbtup::fragrefuse2Lab(Signal* signal, FragoperrecPtr fragOperPtr, FragrecordPtr regFragPtr) 
{
  fragrefuse1Lab(signal, fragOperPtr);
  releaseFragrec(regFragPtr);
  return;
}//Dbtup::fragrefuse2Lab()

void Dbtup::fragrefuse1Lab(Signal* signal, FragoperrecPtr fragOperPtr) 
{
  fragrefuseLab(signal, fragOperPtr);
  releaseFragoperrec(fragOperPtr);
  return;
}//Dbtup::fragrefuse1Lab()

void Dbtup::fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr) 
{
  signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
  signal->theData[1] = terrorCode;
  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUPFRAGREF, signal, 2, JBB);
  return;
}//Dbtup::fragrefuseLab()

void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr) 
{
  fragOperPtr.p->nextFragoprec = cfirstfreeFragopr;
  cfirstfreeFragopr = fragOperPtr.i;
}//Dbtup::releaseFragoperrec()


void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId) 
{
  for (Uint32 i = 0; i < (2 * NO_OF_FRAG_PER_NODE); i++) {
    ljam();
    if (regTabPtr->fragid[i] == fragId) {
      ljam();
      regTabPtr->fragid[i] = RNIL;
      regTabPtr->fragrec[i] = RNIL;
      return;
    }//if
  }//for
  ndbrequire(false);
}//Dbtup::deleteFragTab()

void
Dbtup::execDROP_TAB_REQ(Signal* signal)
{
  ljamEntry();
  DropTabReq* req = (DropTabReq*)signal->getDataPtr();
  
  TablerecPtr tabPtr;
  tabPtr.i = req->tableId;
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
  
  tabPtr.p->m_dropTable.tabUserRef = req->senderRef;
  tabPtr.p->m_dropTable.tabUserPtr = req->senderData;

  signal->theData[0] = ZREL_FRAG;
  signal->theData[1] = tabPtr.i;
  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
}//Dbtup::execDROP_TAB_REQ()

void Dbtup::releaseTabDescr(Tablerec* const regTabPtr) 
{
  Uint32 descriptor = regTabPtr->readKeyArray;
  if (descriptor != RNIL) {
    ljam();
    regTabPtr->tabDescriptor = RNIL;
    regTabPtr->readKeyArray = RNIL;
    regTabPtr->readFunctionArray = NULL;
    regTabPtr->updateFunctionArray = NULL;
    regTabPtr->attributeGroupDescriptor= RNIL;

    Uint32 sizeFunctionArrays = 2 * (regTabPtr->noOfAttr * sizeOfReadFunction());
    descriptor -= (sizeFunctionArrays + ZTD_SIZE);
    Uint32 retNo = getTabDescrWord(descriptor + ZTD_DATASIZE);
    ndbrequire(getTabDescrWord(descriptor + ZTD_HEADER) == ZTD_TYPE_NORMAL);
    ndbrequire(retNo == getTabDescrWord((descriptor + retNo) - ZTD_TR_SIZE));
    ndbrequire(ZTD_TYPE_NORMAL == getTabDescrWord((descriptor + retNo) - ZTD_TR_TYPE));
    freeTabDescr(descriptor, retNo);
  }//if
}//Dbtup::releaseTabDescr()

void Dbtup::releaseFragment(Signal* signal, Uint32 tableId)
{
  TablerecPtr tabPtr;
  tabPtr.i = tableId;
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
  Uint32 fragIndex = RNIL;
  Uint32 fragId = RNIL;
  Uint32 i = 0;
  for (i = 0; i < (2 * NO_OF_FRAG_PER_NODE); i++) {
    ljam();
    if (tabPtr.p->fragid[i] != RNIL) {
      ljam();
      fragIndex = tabPtr.p->fragrec[i];
      fragId = tabPtr.p->fragid[i];
      break;
    }//if
  }//for
  if (fragIndex != RNIL) {
    ljam();
    
    FragrecordPtr regFragPtr;
    regFragPtr.i = fragIndex;
    ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
    releaseFragPages(regFragPtr.p);

    tabPtr.p->fragid[i] = RNIL;
    tabPtr.p->fragrec[i] = RNIL;
    releaseFragrec(regFragPtr);

    signal->theData[0] = ZREL_FRAG;
    signal->theData[1] = tableId;
    sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);  
    return;
  }//if
  
  /**
   * Finished...
   */
  sendFSREMOVEREQ(signal, tabPtr);
}//Dbtup::releaseFragment()

void Dbtup::sendFSREMOVEREQ(Signal* signal, TablerecPtr tabPtr)
{
  FsRemoveReq * const fsReq = (FsRemoveReq *)signal->getDataPtrSend();
  fsReq->userReference = cownref;
  fsReq->userPointer = tabPtr.i;
  fsReq->fileNumber[0] = tabPtr.i;
  fsReq->fileNumber[1] = (Uint32)-1; // Remove all fragments
  fsReq->fileNumber[2] = (Uint32)-1; // Remove all data files within fragment
  fsReq->fileNumber[3] = 255 |       // No P-value used here
    (5 <<  8) |  // Data-files in D5
    (0 << 16) | // Data-files
    (1 << 24);  // Version 1 of fileNumber
  
  fsReq->directory = 1;
  fsReq->ownDirectory = 1;
  sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal, 
	     FsRemoveReq::SignalLength, JBA);  
}//Dbtup::sendFSREMOVEREQ()
 
void Dbtup::execFSREMOVECONF(Signal* signal)
{
  ljamEntry();
  
  FsConf * const fsConf = (FsConf *)signal->getDataPtrSend();
  TablerecPtr tabPtr;
  tabPtr.i = fsConf->userPointer;
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);

  
  DropTabConf * const dropConf = (DropTabConf *)signal->getDataPtrSend();
  dropConf->senderRef = reference();
  dropConf->senderData = tabPtr.p->m_dropTable.tabUserPtr;
  dropConf->tableId = tabPtr.i;
  sendSignal(tabPtr.p->m_dropTable.tabUserRef, GSN_DROP_TAB_CONF,
             signal, DropTabConf::SignalLength, JBB);
  
  releaseTabDescr(tabPtr.p);
  initTab(tabPtr.p);
}//Dbtup::execFSREMOVECONF()

void Dbtup::execFSREMOVEREF(Signal* signal)
{
  ljamEntry();
  ndbrequire(false);
}//Dbtup::execFSREMOVEREF()