Pol  Revision:cb584c9
storage.cpp
Go to the documentation of this file.
1 
8 #include "storage.h"
9 
10 #include <exception>
11 #include <string>
12 #include <time.h>
13 
14 #include "../bscript/berror.h"
15 #include "../bscript/bobject.h"
16 #include "../bscript/contiter.h"
17 #include "../bscript/impstr.h"
18 #include "../clib/cfgelem.h"
19 #include "../clib/cfgfile.h"
20 #include "../clib/clib.h"
21 #include "../clib/compilerspecifics.h"
22 #include "../clib/logfacility.h"
23 #include "../clib/rawtypes.h"
24 #include "../clib/streamsaver.h"
25 #include "../plib/systemstate.h"
26 #include "containr.h"
27 #include "fnsearch.h"
28 #include "globals/object_storage.h"
29 #include "globals/uvars.h"
30 #include "item/item.h"
31 #include "loaddata.h"
32 #include "mkscrobj.h"
33 #include "polcfg.h"
34 #include "poltype.h"
35 #include "ufunc.h"
36 
37 namespace Pol
38 {
39 namespace Core
40 {
41 using namespace Bscript;
42 
43 StorageArea::StorageArea( std::string name ) : _name( name ) {}
44 
46 {
47  while ( !_items.empty() )
48  {
49  Cont::iterator itr = _items.begin();
50  Items::Item* item = ( *itr ).second;
51  item->destroy();
52  _items.erase( itr );
53  }
54 }
55 
57 {
58  size_t size = _name.capacity();
59  for ( const auto& item : _items )
60  size += item.first.capacity() + sizeof( Items::Item* ) + ( sizeof( void* ) * 3 + 1 ) / 2;
61  return size;
62 }
63 
64 
66 {
67  // LINEAR_SEARCH
68  Cont::iterator itr = _items.find( name );
69  if ( itr != _items.end() )
70  {
71  return ( *itr ).second;
72  }
73  return nullptr;
74 }
75 
76 bool StorageArea::delete_root_item( const std::string& name )
77 {
78  Cont::iterator itr = _items.find( name );
79  if ( itr != _items.end() )
80  {
81  Items::Item* item = ( *itr ).second;
82  item->destroy();
83  _items.erase( itr );
84  return true;
85  }
86  return false;
87 }
88 
90 {
91  item->inuse( true );
92 
93  _items.insert( make_pair( item->name(), item ) );
94 }
95 
96 extern Items::Item* read_item( Clib::ConfigElem& elem ); // from UIMPORT.CPP
97 
99 {
100  // if this object is modified in a subsequent incremental save,
101  // don't load it yet.
102  pol_serial_t serial = 0;
103  elem.get_prop( "SERIAL", &serial );
105  return;
106 
107  u32 container_serial = 0; // defaults to item at storage root,
108  (void)elem.remove_prop( "CONTAINER", &container_serial ); // so the return value can be ignored
109 
110  Items::Item* item = read_item( elem );
111  // Austin added 8/10/2006, protect against further crash if item is null. Should throw instead?
112  if ( item == nullptr )
113  {
114  elem.warn_with_line( "Error reading item SERIAL or OBJTYPE." );
115  return;
116  }
117  if ( container_serial == 0 )
118  {
119  insert_root_item( item );
120  }
121  else
122  {
123  Items::Item* cont_item = Core::system_find_item( container_serial );
124 
125  if ( cont_item )
126  {
127  add_loaded_item( cont_item, item );
128  }
129  else
130  {
131  defer_item_insertion( item, container_serial );
132  }
133  }
134 }
135 StorageArea* Storage::find_area( const std::string& name )
136 {
137  AreaCont::iterator itr = areas.find( name );
138  if ( itr == areas.end() )
139  return nullptr;
140  else
141  return ( *itr ).second;
142 }
143 
144 StorageArea* Storage::create_area( const std::string& name )
145 {
146  AreaCont::iterator itr = areas.find( name );
147  if ( itr == areas.end() )
148  {
149  StorageArea* area = new StorageArea( name );
150  areas[name] = area;
151  return area;
152  }
153  else
154  {
155  return ( *itr ).second;
156  }
157 }
158 
160 {
161  const char* rest = elem.rest();
162  if ( rest != nullptr && rest[0] )
163  {
164  return create_area( rest );
165  }
166  else
167  {
168  std::string name = elem.remove_string( "NAME" );
169  return create_area( name );
170  }
171 }
172 
173 
175 {
176  for ( const auto& cont_item : _items )
177  {
178  const Items::Item* item = cont_item.second;
179  if ( item->saveonexit() )
180  sw << *item;
181  }
182 }
183 
185 {
186  for ( Cont::const_iterator itr = _items.begin(), itrend = _items.end(); itr != itrend; ++itr )
187  {
188  Items::Item* item = ( *itr ).second;
189  if ( item )
190  {
191  setrealmif( item, (void*)realm );
192  if ( item->isa( UOBJ_CLASS::CLASS_CONTAINER ) )
193  {
194  UContainer* cont = static_cast<UContainer*>( item );
195  cont->for_each_item( setrealmif, (void*)realm );
196  }
197  }
198  }
199 }
200 
202 {
203  for ( AreaCont::const_iterator itr = areas.begin(), itrend = areas.end(); itr != itrend; ++itr )
204  {
205  itr->second->on_delete_realm( realm );
206  }
207 }
208 
210 {
211  static int num_until_dot = 1000;
212  unsigned int nobjects = 0;
213 
214  StorageArea* area = nullptr;
215  Clib::ConfigElem elem;
216 
217  clock_t start = clock();
218 
219  while ( cf.read( elem ) )
220  {
221  if ( --num_until_dot == 0 )
222  {
223  INFO_PRINT << ".";
224  num_until_dot = 1000;
225  }
226  if ( elem.type_is( "StorageArea" ) )
227  {
228  area = create_area( elem );
229  }
230  else if ( elem.type_is( "Item" ) )
231  {
232  if ( area != nullptr )
233  {
234  try
235  {
236  area->load_item( elem );
237  }
238  catch ( std::exception& )
239  {
240  if ( !Plib::systemstate.config.ignore_load_errors )
241  throw;
242  }
243  }
244  else
245  {
246  ERROR_PRINT << "Storage: Got an ITEM element, but don't have a StorageArea to put it.\n";
247  throw std::runtime_error( "Data file integrity error" );
248  }
249  }
250  else
251  {
252  ERROR_PRINT << "Unexpected element type " << elem.type() << " in storage file.\n";
253  throw std::runtime_error( "Data file integrity error" );
254  }
255  ++nobjects;
256  }
257 
258  clock_t end = clock();
259  int ms = static_cast<int>( ( end - start ) * 1000.0 / CLOCKS_PER_SEC );
260 
261  INFO_PRINT << " " << nobjects << " elements in " << ms << " ms.\n";
262 }
263 
265 {
266  for ( const auto& area : areas )
267  {
268  sw() << "StorageArea" << '\n'
269  << "{" << '\n'
270  << "\tName\t" << area.first << '\n'
271  << "}" << '\n'
272  << '\n';
273  area.second->print( sw );
274  sw() << '\n';
275  }
276 }
277 
279 {
280  while ( !areas.empty() )
281  {
282  delete ( ( *areas.begin() ).second );
283  areas.erase( areas.begin() );
284  }
285 }
286 
287 size_t Storage::estimateSize() const
288 {
289  size_t size = 0;
290  for ( const auto& area : areas )
291  {
292  size += area.first.capacity() + ( sizeof( void* ) * 3 + 1 ) / 2;
293  if ( area.second != nullptr )
294  size += area.second->estimateSize();
295  }
296  return size;
297 }
298 
300 {
301 public:
302  StorageAreaIterator( StorageArea* area, BObject* pIter );
303  virtual BObject* step() POL_OVERRIDE;
304 
305 private:
307  std::string key;
309 };
310 
312  : ContIterator(), m_pIterVal( pIter ), key( "" ), _area( area )
313 {
314 }
315 
317 {
318  StorageArea::Cont::iterator itr = _area->_items.lower_bound( key );
319  if ( !key.empty() && itr != _area->_items.end() )
320  {
321  ++itr;
322  }
323 
324  if ( itr == _area->_items.end() )
325  return nullptr;
326 
327  key = ( *itr ).first;
328  m_pIterVal->setimp( new String( key ) );
329  BObject* result = new BObject( make_itemref( ( *itr ).second ) );
330  return result;
331 }
332 
333 
335 {
336 public:
338  virtual BObjectImp* copy() const POL_OVERRIDE { return new StorageAreaImp( _area ); }
339  virtual std::string getStringRep() const POL_OVERRIDE { return _area->_name; }
340  virtual size_t sizeEstimate() const POL_OVERRIDE { return sizeof( *this ); }
342  {
343  return new StorageAreaIterator( _area, pIterVal );
344  }
345 
346  BObjectRef get_member( const char* membername ) POL_OVERRIDE;
347 
348 private:
350 };
351 BObjectRef StorageAreaImp::get_member( const char* membername )
352 {
353  if ( stricmp( membername, "count" ) == 0 )
354  {
355  return BObjectRef( new BLong( static_cast<int>( _area->_items.size() ) ) );
356  }
357  else if ( stricmp( membername, "totalcount" ) == 0 )
358  {
359  unsigned int total = 0;
360  for ( StorageArea::Cont::iterator itr = _area->_items.begin(); itr != _area->_items.end();
361  ++itr )
362  {
363  Items::Item* item = ( *itr ).second;
364  total += item->item_count();
365  }
366  return BObjectRef( new BLong( total ) );
367  }
368  return BObjectRef( UninitObject::create() );
369 }
370 
371 
373 {
374 public:
375  StorageAreasIterator( BObject* pIter );
376  virtual BObject* step() POL_OVERRIDE;
377 
378 private:
380  std::string key;
381 };
382 
384  : ContIterator(), m_pIterVal( pIter ), key( "" )
385 {
386 }
387 
389 {
390  Storage::AreaCont::iterator itr = gamestate.storage.areas.lower_bound( key );
391  if ( !key.empty() && itr != gamestate.storage.areas.end() )
392  {
393  ++itr;
394  }
395 
396  if ( itr == gamestate.storage.areas.end() )
397  return nullptr;
398 
399  key = ( *itr ).first;
400  m_pIterVal->setimp( new String( key ) );
401  BObject* result = new BObject( new StorageAreaImp( ( *itr ).second ) );
402  return result;
403 }
404 
406 {
407 public:
409  virtual BObjectImp* copy() const POL_OVERRIDE { return new StorageAreasImp(); }
410  virtual std::string getStringRep() const POL_OVERRIDE { return "<StorageAreas>"; }
411  virtual size_t sizeEstimate() const POL_OVERRIDE { return sizeof( *this ); }
413  {
414  return new StorageAreasIterator( pIterVal );
415  }
416 
417  BObjectRef get_member( const char* membername ) POL_OVERRIDE;
418 
420 };
421 
423 {
424  return new StorageAreasImp();
425 }
426 
427 BObjectRef StorageAreasImp::get_member( const char* membername )
428 {
429  if ( stricmp( membername, "count" ) == 0 )
430  {
431  return BObjectRef( new BLong( static_cast<int>( gamestate.storage.areas.size() ) ) );
432  }
433  return BObjectRef( UninitObject::create() );
434 }
436 {
437  if ( obj.isa( OTString ) )
438  {
439  String& rtstr = (String&)obj.impref();
440  std::string key = rtstr.value();
441 
442  Storage::AreaCont::iterator itr = gamestate.storage.areas.find( key );
443  if ( itr != gamestate.storage.areas.end() )
444  {
445  return BObjectRef( new BObject( new StorageAreaImp( ( *itr ).second ) ) );
446  }
447  else
448  {
449  return BObjectRef( new BObject( new BError( "Storage Area not found" ) ) );
450  }
451  }
452  return BObjectRef( new BObject( new BError( "Invalid parameter type" ) ) );
453 }
454 }
455 }
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: storage.cpp:409
virtual BObjectRef get_member(const char *membername)
Definition: object.cpp:930
#define POL_OVERRIDE
void warn_with_line(const std::string &errmsg) const
Definition: cfgfile.cpp:304
ContIterator * createIterator(BObject *pIterVal) POL_OVERRIDE
Definition: storage.cpp:341
const std::string & value() const
Definition: impstr.h:67
std::string remove_string(const char *propname)
Definition: cfgfile.cpp:381
std::string _name
Definition: storage.h:49
void get_prop(const char *propname, unsigned int *plong) const
Definition: cfgfile.cpp:185
void add_loaded_item(Items::Item *cont_item, Items::Item *item)
Definition: loaddata.cpp:248
StorageAreaImp(StorageArea *area)
Definition: storage.cpp:337
SystemState systemstate
Definition: systemstate.cpp:12
void on_delete_realm(Realms::Realm *realm)
Definition: storage.cpp:201
BObjectRef get_member(const char *membername) POL_OVERRIDE
Definition: storage.cpp:351
virtual std::string name() const POL_OVERRIDE
Definition: item.cpp:110
bool delete_root_item(const std::string &name)
Definition: storage.cpp:76
virtual BObject * step() POL_OVERRIDE
Definition: storage.cpp:316
StorageArea * create_area(const std::string &name)
Definition: storage.cpp:144
Bscript::BObjectImp * CreateStorageAreasImp()
Definition: storage.cpp:422
bool isa(BObjectImp::BObjectType type) const
Definition: bobject.h:423
virtual std::string getStringRep() const POL_OVERRIDE
Definition: storage.cpp:410
void print(Clib::StreamWriter &sw) const
Definition: storage.cpp:264
ContIterator * createIterator(BObject *pIterVal) POL_OVERRIDE
Definition: storage.cpp:412
size_t estimateSize() const
Definition: storage.cpp:56
void print(Clib::StreamWriter &sw) const
Definition: storage.cpp:174
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: storage.cpp:338
const char * rest() const
Definition: cfgfile.cpp:71
unsigned int u32
Definition: rawtypes.h:27
StorageArea * find_area(const std::string &name)
Definition: storage.cpp:135
virtual void destroy()
Definition: uobject.cpp:122
StorageAreasIterator(BObject *pIter)
Definition: storage.cpp:383
void on_delete_realm(Realms::Realm *realm)
Definition: storage.cpp:184
AreaCont areas
Definition: storage.h:77
virtual BObjectRef OperSubscript(const BObject &obj)
Definition: object.cpp:903
static UninitObject * create()
Definition: bobject.h:482
BObjectRef get_member(const char *membername) POL_OVERRIDE
Definition: storage.cpp:427
virtual unsigned int item_count() const
Definition: item.cpp:944
GameState gamestate
Definition: uvars.cpp:74
Items::Item * read_item(Clib::ConfigElem &elem)
Definition: uimport.cpp:154
bool saveonexit() const
Definition: uobject.cpp:385
bool remove_prop(const char *propname, std::string *value)
Definition: cfgfile.cpp:128
Bscript::BObjectImp * make_itemref(Items::Item *item)
Definition: mkscrobj.cpp:19
void read(Clib::ConfigFile &cf)
Definition: storage.cpp:209
BObjectImp & impref()
Definition: bobject.h:438
Items::Item * system_find_item(u32 serial)
Definition: fnsearch.cpp:41
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: storage.cpp:340
void setrealmif(Item *item, void *arg)
Definition: ufunc.cpp:1577
BObjectRef OperSubscript(const BObject &obj) POL_OVERRIDE
Definition: storage.cpp:435
bool type_is(const char *name) const
Definition: cfgfile.cpp:95
void insert_root_item(Items::Item *item)
Definition: storage.cpp:89
u32 pol_serial_t
Definition: poltype.h:23
ObjectStorageManager objStorageManager
StorageAreaIterator(StorageArea *area, BObject *pIter)
Definition: storage.cpp:311
std::string name
Definition: osmod.cpp:943
bool isa(UOBJ_CLASS uobj_class) const
Definition: baseobject.h:99
#define ERROR_PRINT
Definition: logfacility.h:230
void load_item(Clib::ConfigElem &elem)
Definition: storage.cpp:98
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: storage.cpp:411
bool inuse() const
Definition: item.h:314
void defer_item_insertion(Items::Item *item, pol_serial_t container_serial)
Definition: loaddata.cpp:112
friend class StorageAreaIterator
Definition: storage.h:56
bool read(ConfigElem &elem)
Definition: cfgfile.cpp:1015
#define INFO_PRINT
Definition: logfacility.h:223
const char * type() const
Definition: cfgfile.cpp:66
size_t estimateSize() const
Definition: storage.cpp:287
unsigned get_save_index(pol_serial_t serial)
Definition: loaddata.cpp:70
Storage storage
Definition: uvars.h:156
Definition: berror.cpp:12
Items::Item * find_root_item(const std::string &name)
Definition: storage.cpp:65
virtual std::string getStringRep() const POL_OVERRIDE
Definition: storage.cpp:339
StorageArea(std::string name)
Definition: storage.cpp:43
virtual BObject * step() POL_OVERRIDE
Definition: storage.cpp:388
virtual void for_each_item(void(*f)(Item *item, void *a), void *arg)
Definition: containr.cpp:659