Beispiel #1
0
/*
 * process_class - process a class
 * HEAP_CACHE_ATTRINFO structure
 *    return: error status
 *    class_oid(in): the class OID
 *    hfid(in): the class HFID 
 *    max_space_to_process(in): maximum space to process
 *    instance_lock_timeout(in): the lock timeout for instances
 *    space_to_process(in, out): space to process
 *    last_processed_oid(in, out): last processed oid
 *    total_objects(in, out): count the processed class objects
 *    failed_objects(in, out): count the failed class objects
 *    modified_objects(in, out): count the modified class objects
 *    big_objects(in, out): count the big class objects
 */
static int
process_class (THREAD_ENTRY * thread_p, OID * class_oid, HFID * hfid,
	       int max_space_to_process, int *instance_lock_timeout,
	       int *space_to_process, OID * last_processed_oid,
	       int *total_objects, int *failed_objects,
	       int *modified_objects, int *big_objects)
{
  int nobjects, nfetched, i, j;
  OID last_oid, prev_oid;
  LOCK null_lock = NULL_LOCK;
  LOCK oid_lock = X_LOCK;
  LC_COPYAREA *fetch_area = NULL;	/* Area where objects are received */
  struct lc_copyarea_manyobjs *mobjs;	/* Describe multiple objects in area */
  struct lc_copyarea_oneobj *obj;	/* Describe on object in area        */
  RECDES recdes;
  HEAP_CACHE_ATTRINFO attr_info;
  HEAP_SCANCACHE upd_scancache;
  int ret = NO_ERROR, object_processed;

  int nfailed_instances = 0;

  if (class_oid == NULL || hfid == NULL || space_to_process == NULL ||
      *space_to_process <= 0 || *space_to_process > max_space_to_process ||
      last_processed_oid == NULL || total_objects == NULL ||
      failed_objects == NULL || modified_objects == NULL ||
      big_objects == NULL || *total_objects < 0 || *failed_objects < 0)
    {
      return ER_FAILED;
    }

  nobjects = 0;
  nfetched = -1;

  ret =
    heap_scancache_start_modify (thread_p, &upd_scancache, hfid, class_oid,
				 SINGLE_ROW_UPDATE);
  if (ret != NO_ERROR)
    {
      return ER_FAILED;
    }

  ret = heap_attrinfo_start (thread_p, class_oid, -1, NULL, &attr_info);
  if (ret != NO_ERROR)
    {
      heap_scancache_end_modify (thread_p, &upd_scancache);
      return ER_FAILED;
    }

  COPY_OID (&last_oid, last_processed_oid);
  COPY_OID (&prev_oid, last_processed_oid);

  while (nobjects != nfetched)
    {
      ret = xlocator_lock_and_fetch_all (thread_p, hfid, &oid_lock,
					 instance_lock_timeout, class_oid,
					 &null_lock, &nobjects, &nfetched,
					 &nfailed_instances, &last_oid,
					 &fetch_area);

      if (ret == NO_ERROR)
	{
	  (*total_objects) += nfailed_instances;
	  (*failed_objects) += nfailed_instances;

	  if (fetch_area != NULL)
	    {
	      mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (fetch_area);
	      obj = LC_START_ONEOBJ_PTR_IN_COPYAREA (mobjs);

	      for (i = 0; i < mobjs->num_objs; i++)
		{
		  if (obj->length > *space_to_process)
		    {
		      if (*space_to_process == max_space_to_process)
			{
			  (*total_objects)++;
			  (*big_objects)++;
			  lock_unlock_object (thread_p, &obj->oid, class_oid,
					      oid_lock, true);
			}
		      else
			{
			  *space_to_process = 0;
			  COPY_OID (last_processed_oid, &prev_oid);

			  for (j = i; j < mobjs->num_objs; j++)
			    {
			      lock_unlock_object (thread_p, &obj->oid,
						  class_oid, oid_lock, true);
			      obj = LC_NEXT_ONEOBJ_PTR_IN_COPYAREA (obj);
			    }

			  if (fetch_area)
			    {
			      locator_free_copy_area (fetch_area);
			    }
			  goto end;
			}
		    }
		  else
		    {
		      *space_to_process -= obj->length;

		      (*total_objects)++;
		      LC_RECDES_TO_GET_ONEOBJ (fetch_area, obj, &recdes);

		      if (desc_disk_to_attr_info
			  (thread_p, &obj->oid, &recdes,
			   &attr_info) == NO_ERROR)
			{
			  object_processed = process_object
			    (thread_p, &upd_scancache, &attr_info, &obj->oid);

			  if (object_processed != 1)
			    {
			      lock_unlock_object (thread_p, &obj->oid,
						  class_oid, oid_lock, true);

			      if (object_processed == -1)
				{
				  (*failed_objects)++;
				}
			    }
			  else
			    {
			      (*modified_objects)++;
			    }
			}
		      else
			{
			  (*failed_objects)++;
			}
		    }

		  COPY_OID (&prev_oid, &obj->oid);
		  obj = LC_NEXT_ONEOBJ_PTR_IN_COPYAREA (obj);
		}

	      if (fetch_area)
		{
		  locator_free_copy_area (fetch_area);
		}
	    }
	  else
	    {
	      /* No more objects */
	      break;
	    }
	}
      else
	{
	  ret = ER_FAILED;
	  break;
	}
    }

  COPY_OID (last_processed_oid, &last_oid);

end:

  heap_attrinfo_end (thread_p, &attr_info);
  heap_scancache_end_modify (thread_p, &upd_scancache);

  return ret;
}
Beispiel #2
0
/*
 * xstats_update_class_statistics () -  Updates the statistics for the objects
 *                                    of a given class
 *   return:
 *   class_id(in): Identifier of the class
 *
 * Note: It first retrieves the whole catalog information about this class,
 *       including all possible forms of disk representations for the instance
 *       objects. Then, it performs a complete pass on the heap file of the
 *       class, reading in all of the instance objects one by one and
 *       calculating the ranges of numeric attribute values (ie. min. & max.
 *       values for each numeric attribute).
 *
 *       During this pass on the heap file, these values are maintained
 *       separately for objects with the same representation. Each minimum and
 *       maximum value is initialized when the first instance of the class
 *       with the corresponding representation is encountered. These values are
 *       continually updated as attribute values exceeding the known range are
 *       encountered. At the end of this pass, these individual ranges for
 *       each representation are uniformed in the last (the current)
 *       representation, building the global range values for the attributes
 *       of the class. Then, the btree statistical information is obtained for
 *       each attribute that is indexed and stored in this final representation
 *       structure. Finally, a new timestamp is obtained for these class
 *       statistics and they are stored to disk within the catalog structure
 *       for the last class representation.
 */
int
xstats_update_class_statistics (THREAD_ENTRY * thread_p, OID * class_id_p)
{
  CLS_INFO *cls_info_p = NULL;
  REPR_ID repr_id;
  DISK_REPR *disk_repr_p = NULL;
  DISK_ATTR *disk_attr_p = NULL;
  BTREE_STATS *btree_stats_p = NULL;
  HEAP_SCANCACHE hf_scan_cache, *hf_scan_cache_p = NULL;
  HEAP_CACHE_ATTRINFO hf_cache_attr_info, *hf_cache_attr_info_p = NULL;
  RECDES recdes;
  OID oid;
  SCAN_CODE scan_rc;
  DB_VALUE *db_value_p;
  DB_DATA *db_data_p;
  int i, j;

  cls_info_p = catalog_get_class_info (thread_p, class_id_p);
  if (cls_info_p == NULL)
    {
      goto error;
    }

  /* if class information was not obtained */
  if (cls_info_p->hfid.vfid.fileid < 0 || cls_info_p->hfid.vfid.volid < 0)
    {
      /* The class does not have a heap file (i.e. it has no instances);
         so no statistics can be obtained for this class; just set
         'tot_objects' field to 0 and return. */

      cls_info_p->tot_objects = 0;

      if (catalog_add_class_info (thread_p, class_id_p, cls_info_p) !=
	  NO_ERROR)
	{
	  goto error;
	}

      catalog_free_class_info (cls_info_p);
      return NO_ERROR;
    }

  if (catalog_get_last_representation_id (thread_p, class_id_p, &repr_id) !=
      NO_ERROR)
    {
      goto error;
    }

  disk_repr_p = catalog_get_representation (thread_p, class_id_p, repr_id);
  if (disk_repr_p == NULL)
    {
      goto error;
    }

  cls_info_p->tot_pages = file_get_numpages (thread_p,
					     &cls_info_p->hfid.vfid);
  cls_info_p->tot_objects = 0;
  disk_repr_p->num_objects = 0;

  /* scan whole object of the class and update the statistics */

  if (heap_scancache_start (thread_p, &hf_scan_cache, &(cls_info_p->hfid),
			    class_id_p, true, false,
			    LOCKHINT_NONE) != NO_ERROR)
    {
      goto error;
    }

  hf_scan_cache_p = &hf_scan_cache;

  if (heap_attrinfo_start (thread_p, class_id_p, -1, NULL,
			   &hf_cache_attr_info) != NO_ERROR)
    {
      goto error;
    }
  hf_cache_attr_info_p = &hf_cache_attr_info;

  /* Obtain minimum and maximum value of the instances for each attribute of
     the class and count the number of objects by scanning heap file */

  recdes.area_size = -1;
  scan_rc = heap_first (thread_p, &(cls_info_p->hfid), class_id_p, &oid,
			&recdes, hf_scan_cache_p, PEEK);

  while (scan_rc == S_SUCCESS)
    {
      if (heap_attrinfo_read_dbvalues (thread_p, &oid, &recdes,
				       hf_cache_attr_info_p) != NO_ERROR)
	{
	  scan_rc = S_ERROR;
	  break;
	}

      /* Consider attributes only whose type are fixed because min/max value
         statistics are useful only for those type when calculating the cost
         of query plan by query optimizer. Variable type attributes, for
         example VARCHAR(STRING), take constant number of selectivity. */

      for (i = 0; i < disk_repr_p->n_fixed; i++)
	{
	  disk_attr_p = &(disk_repr_p->fixed[i]);

	  db_value_p = heap_attrinfo_access (disk_attr_p->id,
					     hf_cache_attr_info_p);
	  if (db_value_p != NULL && db_value_is_null (db_value_p) != true)
	    {
	      db_data_p = db_value_get_db_data (db_value_p);

	      if (disk_repr_p->num_objects == 0)
		{
		  /* first object */
		  disk_attr_p->min_value = *db_data_p;
		  disk_attr_p->max_value = *db_data_p;
		}
	      else
		{
		  /* compare with previous values */
		  if (stats_compare_data (db_data_p, &disk_attr_p->min_value,
					  disk_attr_p->type) < 0)
		    {
		      disk_attr_p->min_value = *db_data_p;
		    }

		  if (stats_compare_data (db_data_p, &disk_attr_p->max_value,
					  disk_attr_p->type) > 0)
		    {
		      disk_attr_p->max_value = *db_data_p;
		    }
		}
	    }
	}

      cls_info_p->tot_objects++;
      disk_repr_p->num_objects++;

      scan_rc = heap_next (thread_p, &(cls_info_p->hfid), class_id_p, &oid,
			   &recdes, hf_scan_cache_p, PEEK);
    }

  if (scan_rc == S_ERROR)
    {
      goto error;
    }

  heap_attrinfo_end (thread_p, hf_cache_attr_info_p);
  if (heap_scancache_end (thread_p, hf_scan_cache_p) != NO_ERROR)
    {
      goto error;
    }

  /* update the index statistics for each attribute */

  for (i = 0; i < disk_repr_p->n_fixed + disk_repr_p->n_variable; i++)
    {
      if (i < disk_repr_p->n_fixed)
	{
	  disk_attr_p = disk_repr_p->fixed + i;
	}
      else
	{
	  disk_attr_p = disk_repr_p->variable + (i - disk_repr_p->n_fixed);
	}

      for (j = 0, btree_stats_p = disk_attr_p->bt_stats;
	   j < disk_attr_p->n_btstats; j++, btree_stats_p++)
	{
	  if (btree_get_stats (thread_p, &btree_stats_p->btid, btree_stats_p,
			       true) != NO_ERROR)
	    {
	      goto error;
	    }
	}
    }

  /* replace the current disk representation structure/information in the
     catalog with the newly computed statistics */

  if (catalog_add_representation (thread_p, class_id_p, repr_id, disk_repr_p)
      != NO_ERROR)
    {
      goto error;
    }

  cls_info_p->time_stamp = stats_get_time_stamp ();

  if (catalog_add_class_info (thread_p, class_id_p, cls_info_p) != NO_ERROR)
    {
      goto error;
    }

  if (disk_repr_p)
    {
      catalog_free_representation (disk_repr_p);
    }

  if (cls_info_p)
    {
      catalog_free_class_info (cls_info_p);
    }

  return NO_ERROR;

error:
  if (hf_cache_attr_info_p)
    {
      heap_attrinfo_end (thread_p, hf_cache_attr_info_p);
    }

  if (hf_scan_cache_p)
    {
      (void) heap_scancache_end (thread_p, hf_scan_cache_p);
    }

  if (disk_repr_p)
    {
      catalog_free_representation (disk_repr_p);
    }

  if (cls_info_p)
    {
      catalog_free_class_info (cls_info_p);
    }

  return er_errid ();
}