Pol  Revision:cb584c9
objecthash.cpp
Go to the documentation of this file.
1 
8 #include "objecthash.h"
9 
10 #include <stddef.h>
11 
12 #include "../clib/clib_endian.h"
13 #include "../clib/logfacility.h"
14 #include "../clib/streamsaver.h"
15 #include "../plib/systemstate.h"
16 #include "accounts/account.h"
17 #include "globals/state.h"
18 #include "mobile/charactr.h"
19 #include "ufunc.h"
20 
21 
22 namespace Pol
23 {
24 namespace Core
25 {
26 ObjectHash::ObjectHash() : hash(), reap_iterator( hash.end() ){};
27 
29 
31 {
32  OH_iterator itr = hash.find( obj->serial );
33  if ( itr != hash.end() )
34  {
35  if ( Plib::systemstate.config.loglevel >= 5 )
36  POLLOG.Format( "ObjectHash insert failed for object serial 0x{:X}. (duplicate serial?)\n" )
37  << obj->serial;
38  return false;
39  }
40  hash.insert( hash.end(), std::make_pair( obj->serial, UObjectRef( obj ) ) );
41  return true;
42 }
43 
44 bool ObjectHash::Remove( u32 /*serial*/ )
45 {
46  // unsigned int num_erased = hash.erase( serial );
47  // return (num_erased>0);
48  return true;
49 }
50 
51 
53 {
54  OH_iterator itr = hash.find( serial );
55  if ( itr != hash.end() )
56  return ( itr->second ).get();
57  else
58  return nullptr;
59 }
60 
62 {
64  u32 tempserial = curr + 1;
65 
66  for ( ;; )
67  {
68  // recycle time. when we roll over the max serial, start from the beginning. now the find()
69  // below may take some time to get the next unused.
70  if ( tempserial < ITEMSERIAL_START || tempserial > ITEMSERIAL_END )
71  tempserial = ITEMSERIAL_START;
72 
73  if ( hash.find( tempserial ) != hash.end() )
74  {
75  tempserial++;
76  continue;
77  }
78  else if ( dirty_deleted.count( tempserial ) )
79  {
80  tempserial++;
81  continue;
82  }
83  else if ( clean_deleted.count( tempserial ) )
84  {
85  tempserial++;
86  continue;
87  }
88  else
89  {
90  break;
91  }
92  }
93  return tempserial;
94 };
95 
97 {
99  u32 tempserial = curr + 1;
100 
101  for ( ;; )
102  {
103  // recycle time. when we roll over the max serial, start from the beginning. now the find()
104  // below may take some time to get the next unused.
105  if ( tempserial < CHARACTERSERIAL_START || tempserial > CHARACTERSERIAL_END )
106  tempserial = CHARACTERSERIAL_START;
107 
108  if ( hash.find( tempserial ) != hash.end() )
109  {
110  tempserial++;
111  continue;
112  }
113  else if ( dirty_deleted.find( tempserial ) != dirty_deleted.end() )
114  {
115  tempserial++;
116  continue;
117  }
118  else if ( clean_deleted.find( tempserial ) != clean_deleted.end() )
119  {
120  tempserial++;
121  continue;
122  }
123  else
124  {
125  break;
126  }
127  }
128  return tempserial;
129 };
130 
132 {
133  OH_const_iterator itr, itrend;
134  sw() << "Object Count: " << hash.size() << "\n";
135  for ( itr = hash.begin(), itrend = hash.end(); itr != itrend; ++itr )
136  {
137  sw() << "type: " << itr->second->classname() << " serial: 0x"
138  << fmt::hexu( itr->second->serial ) << " name: " << itr->second->name() << "\n";
139  // itr->second->printOn( sw ); // its no more safe to try to print the complete object
140  }
141 }
142 
144 {
145  // this is called every 2 seconds (approximately)
146  // iterate through enough of the object hash that it will be swept entirely once every 30 minutes
147  // 2 minutes = 120 seconds = 60 reap calls per sweep
148  // 30 minutes = 1800 seconds = 900 reap calls per sweep
149 
150  // first, figure out how many objects to check:
151  hs::size_type count = hash.size();
152  if ( count == 0 )
153  return;
154  hs::size_type count_this = count / 60;
155  if ( count_this < 1 )
156  count_this = 1;
157  if ( reap_iterator == hash.end() )
158  reap_iterator = hash.begin();
159 
160  while ( count_this-- )
161  {
162  UObject* obj = ( *reap_iterator ).second.get();
163 
164  // We want the objecthash to be the holder of the last reference to an
165  // object when it is deleted - hence the ref_counted_count() check.
166  if ( obj->orphan() && obj->ref_counted_count() == 1 )
167  {
168  dirty_deleted.insert( cfBEu32( obj->serial_ext ) );
169  hash.erase( reap_iterator++ );
170  }
171  else
172  ++reap_iterator;
173 
174  if ( reap_iterator == hash.end() )
175  {
176  reap_iterator = hash.begin();
177  if ( reap_iterator == hash.end() )
178  break;
179  }
180  }
181 }
182 
184 {
185  bool any;
186  do
187  {
188  any = false;
189  unsigned skipped = 0;
190  for ( OH_iterator itr = hash.begin(), itrend = hash.end(); itr != itrend; )
191  {
192  UObject* obj = ( *itr ).second.get();
193 
194  if ( obj->orphan() && obj->ref_counted_count() == 1 )
195  {
196  hash.erase( itr++ );
197  any = true;
198  }
199  else
200  {
201  ++skipped;
202  ++itr;
203  }
204  }
205  } while ( any );
206  if ( !hash.empty() )
207  {
208  INFO_PRINT << "Leftover objects in objecthash: " << hash.size() << "\n";
209 
210  // the hash will be cleared after main() exits, with other statics.
211  // this usually causes assertion failures and crashes.
212  // creating a copy of the internal hash will ensure no refcounts reach zero.
213  INFO_PRINT << "Leaking a copy of the objecthash in order to avoid a crash.\n";
214  new hs( hash );
215  }
216  // hash.clear();
217 }
218 
219 
221 {
222  for ( OH_const_iterator itr = hash.begin(), itrend = hash.end(); itr != itrend; ++itr )
223  {
224  UObject* obj = ( *itr ).second.get();
225  if ( !obj->orphan() && obj->ismobile() )
226  {
227  Mobile::Character* chr = static_cast<Mobile::Character*>( obj );
228  // if (!chr->logged_in)
229  //{
230  chr->acct.clear(); // dave added 9/27/03, accounts and player characters have a mutual
231  // reference that prevents them getting cleaned up
232  // properly. So clear the reference now.
233  chr->destroy();
234  //}
235  }
236  }
237 }
238 
239 ObjectHash::hs::const_iterator ObjectHash::begin() const
240 {
241  return hash.begin();
242 }
243 
244 ObjectHash::hs::const_iterator ObjectHash::end() const
245 {
246  return hash.end();
247 }
248 
249 ObjectHash::ds::const_iterator ObjectHash::dirty_deleted_begin() const
250 {
251  return dirty_deleted.begin();
252 }
253 
254 ObjectHash::ds::const_iterator ObjectHash::dirty_deleted_end() const
255 {
256  return dirty_deleted.end();
257 }
258 
260 {
261  dirty_deleted.clear();
262  clean_deleted.clear();
263 }
264 
266 {
267  clean_deleted.insert( dirty_deleted.begin(), dirty_deleted.end() );
268  dirty_deleted.clear();
269 }
270 
272 {
273  clean_deleted.insert( serial );
274 }
275 }
276 }
std::map< u32, UObjectRef > hs
Definition: objecthash.h:45
SystemState systemstate
Definition: systemstate.cpp:12
hs::const_iterator OH_const_iterator
Definition: objecthash.h:47
#define cfBEu32(x)
Definition: clib_endian.h:43
bool ismobile() const
Definition: baseobject.h:104
OH_iterator reap_iterator
Definition: objecthash.h:76
hs::const_iterator begin() const
Definition: objecthash.cpp:239
hs::iterator OH_iterator
Definition: objecthash.h:46
unsigned ref_counted_count() const
Definition: uobject.h:306
void RegisterCleanDeletedSerial(u32 serial)
Definition: objecthash.cpp:271
UObject * Find(u32 serial)
Definition: objecthash.cpp:52
unsigned int u32
Definition: rawtypes.h:27
void clear()
Definition: refptr.h:283
const u32 CHARACTERSERIAL_START
Definition: state.h:18
const u32 CHARACTERSERIAL_END
Definition: state.h:19
Definition: refptr.h:65
ds::const_iterator dirty_deleted_end() const
Definition: objecthash.cpp:254
bool orphan() const
Definition: baseobject.h:119
void ClearCharacterAccountReferences()
Definition: objecthash.cpp:220
#define POLLOG
Definition: logfacility.h:219
virtual void destroy() POL_OVERRIDE
Definition: charactr.cpp:482
u32 GetCurrentItemSerialNumber(void)
Definition: ufunc.cpp:107
bool Insert(UObject *obj)
Definition: objecthash.cpp:30
bool Remove(u32 serial)
Definition: objecthash.cpp:44
Core::AccountRef acct
Definition: charactr.h:914
u32 GetCurrentCharSerialNumber(void)
Definition: ufunc.cpp:113
hs::const_iterator end() const
Definition: objecthash.cpp:244
void PrintContents(Clib::StreamWriter &sw) const
Definition: objecthash.cpp:131
const u32 ITEMSERIAL_START
Definition: state.h:20
ds::const_iterator dirty_deleted_begin() const
Definition: objecthash.cpp:249
#define INFO_PRINT
Definition: logfacility.h:223
Definition: berror.cpp:12
const u32 ITEMSERIAL_END
Definition: state.h:21