double Nonleaf::ClosestDiffTwo(Stat *Stats, int &i, int &j) const 
{
Entry tmpent;
tmpent.Init(Stats->Dimension);
int i1,j1,imin,jmin;
double d, dmin;

if (actsize<2) 
	print_error("Nonleaf::ClosestDiffTwo","Less than 2 entries");

if (actsize==2) {
	d=distance(Stats->GDtype,entry[0],entry[1]);
	if (d==0) 
	print_error("Nonleaf::ClosestDiffTwo",
		    "Same 2 entries in a nonleaf: should not happen");
	}

dmin=HUGE_DOUBLE;
imin=0;
jmin=1;
for (i1=0;i1<actsize-1;i1++)
   for (j1=i1+1;j1<actsize;j1++) {
		d = distance(Stats->GDtype,entry[i1],entry[j1]);
		if (d>0 && d<dmin) { 
			imin = i1; 
			jmin = j1; 
			dmin = d;}
	}
i=imin; 
j=jmin;
tmpent.Add(entry[i],entry[j]);
return tmpent.Fitness(Stats->Ftype);
}
	static status_t Create(Entry* parent, const char* name, bool implicit,
		Entry*& _entry)
	{
		char* clonedName = strdup(name);
		if (clonedName == NULL)
			return B_NO_MEMORY;

		Entry* entry = new(std::nothrow) Entry(parent, clonedName, implicit);
		if (entry == NULL) {
			free(clonedName);
			return B_NO_MEMORY;
		}

		status_t error = entry->Init();
		if (error != B_OK) {
			delete entry;
			return error;
		}

		if (parent != NULL)
			parent->fChildren.Insert(entry);

		_entry = entry;
		return B_OK;
	}
Node* Nonleaf::AdjustTree(Stat *Stats, const Entry &ent)
{
int EntryI;
int i,j;
double d;

Node *ResNode, *NewNode;
Entry ResEnt;
ResEnt.Init(Stats->Dimension);

EntryI=ClosestOne(Stats,ent);
ResNode=child[EntryI]->AdjustTree(Stats,ent);

if (ResNode!=NULL) { // Split Propagate
	child[EntryI]->CF(entry[EntryI]);
	ResNode->CF(ResEnt);
	NewNode=InsertMightSplit(Stats,ResEnt,ResNode); 
	if (NewNode==NULL) { // Split Propagate Stops
	   if (actsize>2) {
		d=ClosestTwo(Stats, i, j);
		if (!(i==EntryI&&j==actsize-1))
	       		MergeMightResplit(Stats, i, j);
		}
	  return NULL;
	  }
	 else { if (this!=Stats->OldRoot) 
			return NewNode;
	        else { // Create New Root
	  		Stats->CreateNewRoot(this,NewNode);
	  		return NULL;
	        	}
              }
	}
else { // No Split Coming Up
	entry[EntryI]+=ent; 
	return NULL;
	}
}
void Node::Print_Summary(Stat *Stats, std::ofstream &fo) const 
{
Entry tmpent;
tmpent.Init(entry[0].sx.dim);
CF(tmpent);
fo<<"Root CF\t"<<tmpent<<std::endl;
fo<<"FootPrint\t"<<sqrt(tmpent.Radius())<<std::endl;

#ifdef RECTANGLE
Rectangle tmprect;
tmprect.Init(entry[0].sx.dim);
Rect(tmprect);
fo<<"Root Rectangle\t"<<tmprect<<std::endl;
#endif RECTANGLE

fo<<"Leaf Nodes\t"<<LeafNum()<<std::endl;
fo<<"Nonleaf Nodes\t"<<NonleafNum()<<std::endl;
fo<<"Tree Size\t"<<Size()<<std::endl;
fo<<"Tree Depth\t"<<Depth()<<std::endl;

fo<<"Leaf Entries\t"<<NumLeafEntry()<<std::endl;
fo<<"Nonleaf Entries\t"<<NumNonleafEntry()<<std::endl;
fo<<"Occupancy\t"<<Occupancy(Stats)<<std::endl;
}
Esempio n. 5
0
Result
OCSPCache::Put(const CertID& aCertID, Result aResult,
               Time aThisUpdate, Time aValidThrough)
{
  MutexAutoLock lock(mMutex);

  size_t index;
  if (FindInternal(aCertID, index, lock)) {
    // Never replace an entry indicating a revoked certificate.
    if (mEntries[index]->mResult == Result::ERROR_REVOKED_CERTIFICATE) {
      LogWithCertID("OCSPCache::Put(%p) already in cache as revoked - "
                    "not replacing", aCertID);
      MakeMostRecentlyUsed(index, lock);
      return Success;
    }

    // Never replace a newer entry with an older one unless the older entry
    // indicates a revoked certificate, which we want to remember.
    if (mEntries[index]->mThisUpdate > aThisUpdate &&
        aResult != Result::ERROR_REVOKED_CERTIFICATE) {
      LogWithCertID("OCSPCache::Put(%p) already in cache with more recent "
                    "validity - not replacing", aCertID);
      MakeMostRecentlyUsed(index, lock);
      return Success;
    }

    // Only known good responses or responses indicating an unknown
    // or revoked certificate should replace previously known responses.
    if (aResult != Success &&
        aResult != Result::ERROR_OCSP_UNKNOWN_CERT &&
        aResult != Result::ERROR_REVOKED_CERTIFICATE) {
      LogWithCertID("OCSPCache::Put(%p) already in cache - not replacing "
                    "with less important status", aCertID);
      MakeMostRecentlyUsed(index, lock);
      return Success;
    }

    LogWithCertID("OCSPCache::Put(%p) already in cache - replacing", aCertID);
    mEntries[index]->mResult = aResult;
    mEntries[index]->mThisUpdate = aThisUpdate;
    mEntries[index]->mValidThrough = aValidThrough;
    MakeMostRecentlyUsed(index, lock);
    return Success;
  }

  if (mEntries.length() == MaxEntries) {
    LogWithCertID("OCSPCache::Put(%p) too full - evicting an entry", aCertID);
    for (Entry** toEvict = mEntries.begin(); toEvict != mEntries.end();
         toEvict++) {
      // Never evict an entry that indicates a revoked or unknokwn certificate,
      // because revoked responses are more security-critical to remember.
      if ((*toEvict)->mResult != Result::ERROR_REVOKED_CERTIFICATE &&
          (*toEvict)->mResult != Result::ERROR_OCSP_UNKNOWN_CERT) {
        delete *toEvict;
        mEntries.erase(toEvict);
        break;
      }
    }
    // Well, we tried, but apparently everything is revoked or unknown.
    // We don't want to remove a cached revoked or unknown response. If we're
    // trying to insert a good response, we can just return "successfully"
    // without doing so. This means we'll lose some speed, but it's not a
    // security issue. If we're trying to insert a revoked or unknown response,
    // we can't. We should return with an error that causes the current
    // verification to fail.
    if (mEntries.length() == MaxEntries) {
      return aResult;
    }
  }

  Entry* newEntry = new (std::nothrow) Entry(aResult, aThisUpdate,
                                             aValidThrough);
  // Normally we don't have to do this in Gecko, because OOM is fatal.
  // However, if we want to embed this in another project, OOM might not
  // be fatal, so handle this case.
  if (!newEntry) {
    return Result::FATAL_ERROR_NO_MEMORY;
  }
  Result rv = newEntry->Init(aCertID);
  if (rv != Success) {
    delete newEntry;
    return rv;
  }
  if (!mEntries.append(newEntry)) {
    delete newEntry;
    return Result::FATAL_ERROR_NO_MEMORY;
  }
  LogWithCertID("OCSPCache::Put(%p) added to cache", aCertID);
  return Success;
}
double Node::Fitness(short ftype) const {
	Entry tmpent;
	tmpent.Init(entry[0].sx.dim);
	this->CF(tmpent);
	return tmpent.Fitness(ftype);
	}
double Node::Diameter() const {
	Entry tmpent;
	tmpent.Init(entry[0].sx.dim);
	this->CF(tmpent);
	return tmpent.Diameter();
	}
double Node::Radius() const {
	Entry tmpent;
	tmpent.Init(entry[0].sx.dim);
	this->CF(tmpent);
	return tmpent.Radius();
	}
void Hierarchy0(int &n, 	 // final number of clusters
		const int K,     // final number of clusters
		Entry **entries,
		short GDtype,
		short Ftype,
		double Ft)
{

if (n<=1) return;

int 	i, j, imin, jmin, done;
short  	*checked = new short[n];
memset(checked,0,n*sizeof(short));
	// 0: unchecked;
	// -1: exceeds the given threshold if merged with nearest neighbor;
	// -2: nonexistant after merging.

double 	*dist = new double[n*(n-1)/2];
double 	d, dmin;
Entry 	tmpent;
tmpent.Init((*entries)[0].sx.dim);

dmin = HUGE;	// compute all initial distances and closest pair
for (i=0; i<n-1; i++)
  for (j=i+1; j<n; j++) {
	d = distance(GDtype,(*entries)[i],(*entries)[j]);
	dist[i*n-i*(i+1)/2+j-i-1] = d;
	if (d<dmin) {
		dmin = d;
		imin = i;
		jmin = j;
		}
	}

if (K==0) {// ****** case 1 ****** cluster by threshold ft
done = FALSE;
while (done==FALSE) {
	tmpent.Add((*entries)[imin],(*entries)[jmin]);
	if (tmpent.Fitness(Ftype) < Ft) { 
	// within the threshold
		(*entries)[imin] += (*entries)[jmin];
		checked[jmin] = -2;
		for (i=0; i<imin; i++) {
		   if (checked[i]==0) {
		   dist[i*n-i*(i+1)/2+imin-i-1] = 
			distance(GDtype,(*entries)[i],(*entries)[imin]);
		   }}
		for (j=imin+1; j<n; j++) {
		   if (checked[j]==0) {
		   dist[imin*n-imin*(imin+1)/2+j-imin-1] =
			distance(GDtype,(*entries)[imin],(*entries)[j]);
		   }}
		}
	else { 
	// exceeds the threshold
		checked[imin] = -1;
		checked[jmin] = -1;
		}

	done = TRUE;
	dmin = HUGE;
	for (i=0; i<n-1; i++) {
	  if (checked[i]==0) {
	  for (j=i+1; j<n; j++) {
		if (checked[j]==0) {
			d = dist[i*n-i*(i+1)/2+j-i-1];
			if (d<dmin) {
				done = FALSE;
				dmin = d;
				imin = i;
				jmin = j;
	}}}}} 
	} // end of while
} // end of if
else { // ***** case 2 ***** cluster by number k	
done = n;
while (done > K) {
	(*entries)[imin] += (*entries)[jmin];
	checked[jmin] = -2;
	done--;
	for (i=0; i<imin; i++) {
	   if (checked[i]==0) {
	   dist[i*n-i*(i+1)/2+imin-i-1] = 
		distance(GDtype,(*entries)[i],(*entries)[imin]);
	   }}
	for (j=imin+1; j<n; j++) {
	   if (checked[j]==0) {
	   dist[imin*n-imin*(imin+1)/2+j-imin-1] =
		distance(GDtype,(*entries)[imin],(*entries)[j]);
	   }}

	dmin = HUGE;
	for (i=0; i<n-1; i++) {
	  if (checked[i]==0) {
	  for (j=i+1; j<n; j++) {
		if (checked[j]==0) {
		d = dist[i*n-i*(i+1)/2+j-i-1];	
		if (d<dmin) {
			dmin = d;
			imin = i;
			jmin = j;
	}}}}}
	} // end of while
} // end of else

j = 0;
for (i=0; i<n; i++)
   if (checked[i]!=-2) {
	(*entries)[j]=(*entries)[i];
	j++;
	}
n=j;

delete [] checked;
delete [] dist;
}