<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zorbaerrors/Assert.h"
#include "system/globalenv.h"

#include "store/minimal/string_pool.h"
#include "store/minimal/qname_pool.h"
#include "store/minimal/min_atomic_items.h"
#include "store/minimal/min_store.h"
#include "store/minimal/min_store_defs.h"
#include "store/minimal/min_node_items.h"
#include "store/api/collection.h"
#include "zorbatypes/datetime.h"


namespace zorba { namespace storeminimal {

/*******************************************************************************

********************************************************************************/
QNamePool::QNamePool(ulong size, StringPool* nspool) 
  :
  theCache(new QNameItemImpl[size]),
  theCacheSize(size),
  theFirstFree(1),
  theNumFree(size - 1),
  theHashSet(2 * size),
  theNamespacePool(nspool)
{
  // Put all the preallocated slots in the free list of the cahce.
  QNameItemImpl* qn = &theCache[1];
  QNameItemImpl* last = qn + size - 1;

  for (uint16_t i = 1; qn < last; qn++, i++)
  {
    qn->theNextFree = i + 1;
    qn->thePrevFree = i - 1;
    qn->thePosition = i;
  }
  (--qn)->theNextFree = 0;
}


/*******************************************************************************

********************************************************************************/
QNamePool::~QNamePool() 
{
  ulong n = theHashSet.theHashTab.size();
  for (ulong i = 0; i < n; i++)
  {
    if (theHashSet.theHashTab[i].theItem != NULL)
    {
      QNameItemImpl* qn = theHashSet.theHashTab[i].theItem;

      if (!qn->isNormalized())
        qn->theLocal.setNull();

      if (theHashSet.theHashTab[i].theItem->isOverflow())
        delete theHashSet.theHashTab[i].theItem;
    }
  }

  if (theCache != NULL)
  {
    delete [] theCache;
    theCache = NULL;
  }
}


/*******************************************************************************

********************************************************************************/
void QNamePool::remove(QNameItemImpl* qn)
{
  SYNC_CODE(AutoMutex lock(&theHashSet.theMutex);)

  if (qn->getRefCount() > 0)
    return;

  if (qn->isInCache())
  {
    qn->theNextFree = (uint16_t)theFirstFree;
    theCache[theFirstFree].thePrevFree = qn->thePosition;
    theFirstFree = qn->thePosition;
    theNumFree++;

    //+
    theHashSet.remove(qn);
    if (!qn->isNormalized())
    {
      // Save the pointer to the associated normalized qname and then set
      // that pointer to null. This way (a) we can decerement the ref
      // counter of the normalized qname after releasing theHashSet.theMutex
      // (otherwise, we would run into a self-deadlock if the normalized
      // qname needs to be freed),and (b) removeReference is not called
      // when we overwite the pointer with the new local name.
      qn->detachNormalized();
    }
    else
    {
      // Set qn->theLocal so that the assertion in setNormalized() (which is
      // invoked later by the caller of this method) will not trigger.
      qn->theLocal = NULL;
    }
  }
  else
  {
    // If all the pointers to QNameItems were smart pointers, we could leave
    // qn in the pool, and let the pool garbage-collect it later (if it still
    // unused). If however QNameItems may be referenced by regular pointers as
    // well, then qn must be removed from the pool and really deleted
    theHashSet.remove(qn);
    delete qn;
  }
}


/*******************************************************************************
  If the pool does not already contain a qname with the given namespace, prefix,
  and local name, then create such a qname, insert it in the pool and return an
  rchandle to it. Otherwise, return an rchandle to the existing qname. 

  Note: The given namespace, prefix, and local name pointers may point to heap 
  or stack allocated strings. If a qname is inserted, then the strings are 
  copied internally into xqpStringStore objects. So, it's always the caller
  who is resposnible for freeing the given strings.
********************************************************************************/
store::Item_t QNamePool::insert(
    const char* ns,
    const char* pre,
    const char* ln,
    bool        sync)
{
  QNameItemImpl* qn;<commit_msg>Experiments with minimal store on dashboard.<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zorbaerrors/Assert.h"
#include "system/globalenv.h"

#include "store/minimal/string_pool.h"
#include "store/minimal/qname_pool.h"
#include "store/minimal/min_atomic_items.h"
#include "store/minimal/min_store.h"
#include "store/minimal/min_store_defs.h"
#include "store/minimal/min_node_items.h"
#include "store/api/collection.h"
#include "zorbatypes/datetime.h"


namespace zorba { namespace storeminimal {

/*******************************************************************************

********************************************************************************/
QNamePool::QNamePool(ulong size, StringPool* nspool) 
  :
  theCache(new QNameItemImpl[size]),
  theCacheSize(size),
  theFirstFree(1),
  theNumFree(size - 1),
  theHashSet(2 * size),
  theNamespacePool(nspool)
{
  // Put all the preallocated slots in the free list of the cahce.
  QNameItemImpl* qn = &theCache[1];
  QNameItemImpl* last = qn + size - 1;

  for (uint16_t i = 1; qn < last; qn++, i++)
  {
    qn->theNextFree = i + 1;
    qn->thePrevFree = i - 1;
    qn->thePosition = i;
  }
  (--qn)->theNextFree = 0;
}


/*******************************************************************************

********************************************************************************/
QNamePool::~QNamePool() 
{
  ulong n = theHashSet.theHashTab.size();
  for (ulong i = 0; i < n; i++)
  {
    if (theHashSet.theHashTab[i].theItem != NULL)
    {
      QNameItemImpl* qn = theHashSet.theHashTab[i].theItem;

      if (!qn->isNormalized())
        qn->theLocal.setNull();

      if (theHashSet.theHashTab[i].theItem->isOverflow())
        delete theHashSet.theHashTab[i].theItem;
    }
  }

  if (theCache != NULL)
  {
    delete [] theCache;
    theCache = NULL;
  }
}


/*******************************************************************************

********************************************************************************/
void QNamePool::remove(QNameItemImpl* qn)
{
  SYNC_CODE(AutoMutex lock(&theHashSet.theMutex);)

  if (qn->getRefCount() > 0)
    return;

  if (qn->isInCache())
  {
    qn->theNextFree = (uint16_t)theFirstFree;
    theCache[theFirstFree].thePrevFree = qn->thePosition;
    theFirstFree = qn->thePosition;
    theNumFree++;

    //+
    theHashSet.remove(qn);
    if (!qn->isNormalized())
    {
      // Save the pointer to the associated normalized qname and then set
      // that pointer to null. This way (a) we can decerement the ref
      // counter of the normalized qname after releasing theHashSet.theMutex
      // (otherwise, we would run into a self-deadlock if the normalized
      // qname needs to be freed),and (b) removeReference is not called
      // when we overwite the pointer with the new local name.
      qn->detachNormalized();
    }
    else
    {
      // Set qn->theLocal so that the assertion in setNormalized() (which is
      // invoked later by the caller of this method) will not trigger.
      qn->theLocal = NULL;
    }
  }
  else
  {
    // If all the pointers to QNameItems were smart pointers, we could leave
    // qn in the pool, and let the pool garbage-collect it later (if it still
    // unused). If however QNameItems may be referenced by regular pointers as
    // well, then qn must be removed from the pool and really deleted
    theHashSet.remove(qn);
    delete qn;
  }
}


/*******************************************************************************
  If the pool does not already contain a qname with the given namespace, prefix,
  and local name, then create such a qname, insert it in the pool and return an
  rchandle to it. Otherwise, return an rchandle to the existing qname. 

  Note: The given namespace, prefix, and local name pointers may point to heap 
  or stack allocated strings. If a qname is inserted, then the strings are 
  copied internally into xqpStringStore objects. So, it's always the caller
  who is resposnible for freeing the given strings.
********************************************************************************/
store::Item_t QNamePool::insert(
    const char* ns,
    const char* pre,
    const char* ln,
    bool        sync)
{
  ZORBA_FATAL(false, "")

  QNameItemImpl* qn;
{'fraction_non_alphanumeric': 0.22272868538278257, 'fraction_numerical': 0.005594115818916399, 'mean_word_length': 3.755665024630542, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3607179', 'n_tokens_mistral': 2916, 'n_tokens_neox': 2728, 'n_words': 905}