00001 /** @file webnode.cc */ 00002 /* 00003 * Copyright (C) 2002 Laird Breyer 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 * 00019 * Author: Laird Breyer (laird@lbreyer.com) 00020 */ 00021 00022 #include "webnode.h" 00023 00024 // WebNode objects, which are of type MemoryPooled<WebNodeStruct>, 00025 // are allocated by their own memory manager, part of which is declared here 00026 const int MemoryPooled<WebNodeStruct>::BLOCK_SIZE=WEBNODE_MEMPOOL_DELTA; 00027 MemoryPooled<WebNodeStruct> *MemoryPooled<WebNodeStruct>::freelist = NULL; 00028 00029 // Link objects, which are of type MemPool<LinkStruct>, 00030 // are allocated by their own memory manager 00031 MemPool<LinkStruct> WebNode::global_link_pool; 00032 00033 // the global_link_pool contains a few static data members 00034 const int MemPool<LinkStruct>::BLOCK_SIZE = LINK_MEMPOOL_DELTA; 00035 MemPoolObject<LinkStruct>* MemPool<LinkStruct>::mempool1 = NULL; 00036 MemPoolObject<LinkStruct>* MemPool<LinkStruct>::mempool2 = NULL; 00037 00038 00039 WebNode :: WebNode(uint32 idno) { 00040 data.id = idno; 00041 data.date = 0; 00042 data.num_valid_tolinks = 0; 00043 data.num_leaflinks = 0; 00044 data.num_tolinks = 0; 00045 data.num_fromlinks = 0; 00046 data.tolinks = NULL; 00047 data.fromlinks = NULL; 00048 } 00049 00050 /// Sets the earliest known date of the WebNode 00051 /** 00052 * This function is designed to be called several times. 00053 * The earliest nonzero date is retained. 00054 */ 00055 void WebNode :: SetDate(uint16 adate) { 00056 if( adate > 0 ) { 00057 if( data.date > 0 ) { 00058 data.date = min(data.date,adate); 00059 } else { 00060 data.date = adate; 00061 } 00062 } 00063 } 00064 00065 /// Inserts a set of tolinks into the WebNode. 00066 /** 00067 * Inserts (or merges) the raw (character ptr) links 00068 * into the webnode's tolinks array. 00069 */ 00070 void WebNode :: InsertRawLinks(RawLinkSet *s) { 00071 assert(data.num_valid_tolinks == 0); 00072 assert(data.num_leaflinks == 0); 00073 if(data.num_tolinks > 0) { 00074 for(int j = 0; j < data.num_tolinks; j++) { 00075 s->insert(data.tolinks[j].data.pointer_diff); 00076 } 00077 WebNode::global_link_pool.Deallocate(data.tolinks,data.num_tolinks); 00078 data.num_tolinks = 0; 00079 } 00080 00081 data.num_tolinks = s->size(); 00082 if( data.num_tolinks > 0 ) { 00083 data.tolinks = WebNode::global_link_pool.Allocate(data.num_tolinks); 00084 int k = 0; 00085 for(RawLinkSet::iterator i = s->begin(); i != s->end(); i++) { 00086 data.tolinks[k++].data.pointer_diff = (*i); 00087 } 00088 assert(k == data.num_tolinks); 00089 00090 } else { 00091 00092 data.tolinks = NULL; 00093 00094 } 00095 } 00096 00097 00098 /// This appends a webnode to the fromlinks list. 00099 void WebNode :: AppendFromLink(WebNodePtr anothernode) throw (overflow_error) { 00100 00101 assert(anothernode); 00102 if( data.num_fromlinks <= 0 ) { 00103 cerr << "error: trying to append to empty fromlink" << endl; 00104 throw overflow_error(""); 00105 } 00106 00107 if( data.fromlinks == NULL ) { 00108 data.fromlinks = WebNode::global_link_pool.Allocate(data.num_fromlinks); 00109 assert(data.fromlinks != NULL); 00110 for(int k = 0; k < data.num_fromlinks; k++) { 00111 data.fromlinks[k].data.webnode_ptr = NULL; 00112 } 00113 } 00114 00115 00116 // insert anothernode in the first free nonempty slot. 00117 for(int k = 0; k < data.num_fromlinks; k++) { 00118 if(data.fromlinks[k].data.webnode_ptr == NULL) { 00119 data.fromlinks[k].data.webnode_ptr = anothernode; 00120 return; 00121 } 00122 } 00123 // if we get to here, there's a problem 00124 cerr << "error: fromlink overflow" << endl; 00125 throw overflow_error(""); 00126 } 00127 00128 /// Sorts all valid links into the first part of the tolinks array. 00129 /** 00130 * While sorting, it also 00131 * converts the pointer_differences into webnode_ptrs. 00132 * Dangling links are left in the upper half of the array. 00133 * 00134 * Note second argument should really be a data member of first 00135 * (more elegant) but then we'd have to create a derived simplehashtable... 00136 */ 00137 void WebNode :: NormalizeRawLinks(SimpleHashTable<WebNodePtr> *h) { 00138 int i, j; 00139 for(i = 0; i < data.num_tolinks; i++) { 00140 WebNodePtr w = h->Find(data.tolinks[i].data.pointer_diff); 00141 if( w ) { 00142 data.tolinks[i].data.webnode_ptr = w; 00143 } else { // its dangling link 00144 // see if another valid link exists 00145 for(j = i + 1; j < data.num_tolinks; j++) { 00146 WebNodePtr v = h->Find(data.tolinks[j].data.pointer_diff); 00147 if( v ) { // found one, swap 00148 data.tolinks[j].data.pointer_diff = data.tolinks[i].data.pointer_diff; 00149 data.tolinks[i].data.webnode_ptr = v; 00150 break; 00151 } 00152 } 00153 if( j == data.num_tolinks ) { // all other links were dangling 00154 // so all elements i, i+1, i+2,... are dangling links 00155 break; 00156 } 00157 } 00158 } 00159 00160 data.num_valid_tolinks = i; 00161 00162 #ifndef NDEBUG 00163 // consistency check/validation 00164 for(int k = 0; k < NumberOfValidToLinks(); k++) { 00165 assert(ValidToLink(k)); 00166 assert(ValidToLink(k)->OccupationCount() == 0); 00167 } 00168 for(int k = NumberOfValidToLinks(); k < data.num_tolinks; k++) { 00169 assert(!h->Find(data.tolinks[k].data.pointer_diff)); 00170 } 00171 #endif 00172 } 00173 00174 /// Returns the full size of the WebNode including link arrays. 00175 size_t WebNode :: RealSize() { 00176 return sizeof(WebNode) + sizeof(Link) * data.num_tolinks 00177 + sizeof(Link) * data.num_fromlinks; 00178 } 00179 00180 00181 /// sifts LeafNode pointers upward in the tolinks array. 00182 /** 00183 * The code for this function is very similar to that of NormalizeRawLinks() 00184 */ 00185 void WebNode :: UpdateLeafLinks(SimpleLeafNodePtrHashTable *leaftable) { 00186 int i, j; 00187 for(i = data.num_valid_tolinks + data.num_leaflinks; i < data.num_tolinks; i++) { 00188 LeafNodePtr w = leaftable->Find(data.tolinks[i].data.pointer_diff); 00189 if( w ) { 00190 data.tolinks[i].data.leafnode_ptr = w; 00191 } else { // its dangling link 00192 // see if another leafnode link exists 00193 for(j = i + 1; j < data.num_tolinks; j++) { 00194 LeafNodePtr v = leaftable->Find(data.tolinks[j].data.pointer_diff); 00195 if( v ) { // found one, swap 00196 data.tolinks[j].data.pointer_diff = data.tolinks[i].data.pointer_diff; 00197 data.tolinks[i].data.leafnode_ptr = v; 00198 break; 00199 } 00200 } 00201 if( j == data.num_tolinks ) { // all other links were dangling 00202 // so all elements i, i+1, i+2,... are dangling links 00203 break; 00204 } 00205 } 00206 } 00207 00208 data.num_leaflinks = i - data.num_valid_tolinks; 00209 00210 #ifndef NDEBUG 00211 // consistency check/validation 00212 for(int k = 0; k < NumberOfLeafLinks(); k++) { 00213 assert(ValidLeafLink(k)); 00214 assert(ValidLeafLink(k)->OccupationCount() == 0); 00215 } 00216 for(int k = NumberOfValidToLinks() + NumberOfLeafLinks(); k < data.num_tolinks; k++) { 00217 assert(!leaftable->Find(data.tolinks[k].data.pointer_diff)); 00218 } 00219 #endif 00220 00221 }