diff options
author | Mike Buland <eichlan@xagasoft.com> | 2013-03-17 23:22:35 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2013-03-17 23:22:35 +0000 |
commit | a6d249cad214dc0baff0e80e56ffdec91d8a1cf0 (patch) | |
tree | ef74be780dc2d065ae07bd633518efff17f874e3 | |
parent | 55f8e2c01fe4513d5e3de55f567c392b4a18ecc2 (diff) | |
download | libbu++-a6d249cad214dc0baff0e80e56ffdec91d8a1cf0.tar.gz libbu++-a6d249cad214dc0baff0e80e56ffdec91d8a1cf0.tar.bz2 libbu++-a6d249cad214dc0baff0e80e56ffdec91d8a1cf0.tar.xz libbu++-a6d249cad214dc0baff0e80e56ffdec91d8a1cf0.zip |
The new cache system is tested and ready, it just needs to be put in it's place.
The old cache system will be going away now, so if you need it for anything,
grab a version before this commit.
Oh, also, happy 1,000th commit!
-rw-r--r-- | src/tests/cache.cpp | 361 |
1 files changed, 330 insertions, 31 deletions
diff --git a/src/tests/cache.cpp b/src/tests/cache.cpp index aa71c39..112d916 100644 --- a/src/tests/cache.cpp +++ b/src/tests/cache.cpp | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <bu/file.h> | 6 | #include <bu/file.h> |
7 | #include <bu/streamstack.h> | 7 | #include <bu/streamstack.h> |
8 | #include <bu/readwritemutex.h> | 8 | #include <bu/readwritemutex.h> |
9 | #include <bu/mutexlocker.h> | ||
9 | 10 | ||
10 | #include <bu/sio.h> | 11 | #include <bu/sio.h> |
11 | #include <bu/string.h> | 12 | #include <bu/string.h> |
@@ -15,6 +16,7 @@ | |||
15 | // | 16 | // |
16 | 17 | ||
17 | template<typename keytype, typename obtype> class CacheBase; | 18 | template<typename keytype, typename obtype> class CacheBase; |
19 | template<typename keytype, typename obtype> class CacheEntry; | ||
18 | 20 | ||
19 | template<typename keytype, typename obtype> | 21 | template<typename keytype, typename obtype> |
20 | class CacheObject | 22 | class CacheObject |
@@ -36,6 +38,27 @@ public: | |||
36 | virtual keytype getKey() const=0; | 38 | virtual keytype getKey() const=0; |
37 | virtual int getPersistenceScore() const { return 0; } | 39 | virtual int getPersistenceScore() const { return 0; } |
38 | 40 | ||
41 | void lock() | ||
42 | { | ||
43 | pEntry->lock(); | ||
44 | } | ||
45 | |||
46 | void unlock() | ||
47 | { | ||
48 | pEntry->unlock(); | ||
49 | } | ||
50 | |||
51 | int getRefCount() const | ||
52 | { | ||
53 | return pEntry->getRefCount(); | ||
54 | } | ||
55 | |||
56 | bool hasChanged() const | ||
57 | { | ||
58 | return bChanged; | ||
59 | } | ||
60 | |||
61 | protected: | ||
39 | void changed( bool bChanged=true ) | 62 | void changed( bool bChanged=true ) |
40 | { | 63 | { |
41 | if( this->bChanged == false && bChanged == true ) | 64 | if( this->bChanged == false && bChanged == true ) |
@@ -45,13 +68,16 @@ public: | |||
45 | } | 68 | } |
46 | 69 | ||
47 | private: | 70 | private: |
48 | void setCache( CacheType *pCache ) | 71 | typedef CacheEntry<keytype, obtype> Entry; |
72 | void setCache( CacheType *pCache, Entry *pEntry ) | ||
49 | { | 73 | { |
50 | this->pCache = pCache; | 74 | this->pCache = pCache; |
75 | this->pEntry = pEntry; | ||
51 | } | 76 | } |
52 | 77 | ||
53 | private: | 78 | private: |
54 | CacheType *pCache; | 79 | CacheType *pCache; |
80 | Entry *pEntry; | ||
55 | bool bChanged; | 81 | bool bChanged; |
56 | }; | 82 | }; |
57 | 83 | ||
@@ -93,6 +119,11 @@ public: | |||
93 | mObject.unlock(); | 119 | mObject.unlock(); |
94 | } | 120 | } |
95 | 121 | ||
122 | Bu::Mutex &getMutex() | ||
123 | { | ||
124 | return mObject; | ||
125 | } | ||
126 | |||
96 | void incRef() | 127 | void incRef() |
97 | { | 128 | { |
98 | mEntry.lock(); | 129 | mEntry.lock(); |
@@ -263,7 +294,13 @@ public: | |||
263 | 294 | ||
264 | return *this; | 295 | return *this; |
265 | } | 296 | } |
266 | 297 | ||
298 | template<typename castto> | ||
299 | CachePtr<keytype, castto, basetype> cast() | ||
300 | { | ||
301 | return pCache->cast<obtype, castto>( *this ); | ||
302 | } | ||
303 | |||
267 | bool operator==( const MyType &rhs ) const | 304 | bool operator==( const MyType &rhs ) const |
268 | { | 305 | { |
269 | return pCache == rhs.pCache && | 306 | return pCache == rhs.pCache && |
@@ -339,6 +376,7 @@ template<typename keytype, typename obtype> | |||
339 | class CacheBase | 376 | class CacheBase |
340 | { | 377 | { |
341 | friend class CachePtrInterface<keytype, obtype>; | 378 | friend class CachePtrInterface<keytype, obtype>; |
379 | friend class CacheObject<keytype, obtype>; | ||
342 | public: | 380 | public: |
343 | CacheBase() | 381 | CacheBase() |
344 | { | 382 | { |
@@ -346,13 +384,14 @@ public: | |||
346 | 384 | ||
347 | virtual ~CacheBase() | 385 | virtual ~CacheBase() |
348 | { | 386 | { |
387 | Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); | ||
388 | syncChanges(); | ||
349 | } | 389 | } |
350 | 390 | ||
351 | typedef CacheEntry<keytype, obtype> Entry; | 391 | typedef CacheEntry<keytype, obtype> Entry; |
352 | typedef Bu::List<keytype> KeyList; | 392 | typedef Bu::List<keytype> KeyList; |
353 | 393 | ||
354 | 394 | CachePtr<keytype, obtype> insert( obtype *pObject ) | |
355 | CachePtr<keytype, obtype> insert( const obtype *pObject ) | ||
356 | { | 395 | { |
357 | Entry *pEnt = addEntry( pObject ); | 396 | Entry *pEnt = addEntry( pObject ); |
358 | 397 | ||
@@ -362,9 +401,9 @@ public: | |||
362 | } | 401 | } |
363 | 402 | ||
364 | template<typename supertype> | 403 | template<typename supertype> |
365 | CachePtr<keytype, supertype, obtype> insert( const supertype *pObject ) | 404 | CachePtr<keytype, supertype, obtype> insert( supertype *pObject ) |
366 | { | 405 | { |
367 | const obtype *pCast = dynamic_cast<const obtype *>( pObject ); | 406 | obtype *pCast = dynamic_cast<obtype *>( pObject ); |
368 | if( pCast == NULL ) | 407 | if( pCast == NULL ) |
369 | throw std::bad_cast(); | 408 | throw std::bad_cast(); |
370 | 409 | ||
@@ -399,9 +438,45 @@ public: | |||
399 | return CachePtr<keytype, supertype, obtype>( this, key ); | 438 | return CachePtr<keytype, supertype, obtype>( this, key ); |
400 | } | 439 | } |
401 | 440 | ||
441 | template<typename supertype, typename castto> | ||
442 | CachePtr<keytype, castto, obtype> cast( CachePtr<keytype, supertype, obtype> &ptr ) | ||
443 | { | ||
444 | if( ptr.pEnt ) | ||
445 | return CachePtr<keytype, castto, obtype>( this, ptr.pEnt, ptr.kId ); | ||
446 | else | ||
447 | return CachePtr<keytype, castto, obtype>( this, ptr.kId ); | ||
448 | } | ||
449 | |||
450 | void erase( const keytype &key ) | ||
451 | { | ||
452 | Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); | ||
453 | if( hCacheEntry.has( key ) ) | ||
454 | { | ||
455 | Entry *pEnt = hCacheEntry.get( key ); | ||
456 | pEnt->mEntry.lock(); | ||
457 | if( pEnt->iRefCount > 0 ) | ||
458 | { | ||
459 | int iCount = pEnt->iRefCount; | ||
460 | pEnt->mEntry.unlock(); | ||
461 | throw Bu::ExceptionBase( Bu::String("Cache entry %1 cannot be erased, there are %2 active references.").arg( key ).arg( iCount ).end().getStr() ); | ||
462 | } | ||
463 | delete pEnt->pObject; | ||
464 | delete pEnt; | ||
465 | hCacheEntry.erase( key ); | ||
466 | } | ||
467 | _erase( key ); | ||
468 | } | ||
469 | |||
402 | virtual KeyList getKeys() const=0; | 470 | virtual KeyList getKeys() const=0; |
471 | virtual int getSize() const=0; | ||
403 | 472 | ||
404 | virtual void sync()=0; | 473 | void sync() |
474 | { | ||
475 | Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); | ||
476 | Bu::println("Syncing storage layer..."); | ||
477 | _sync(); | ||
478 | syncChanges(); | ||
479 | } | ||
405 | 480 | ||
406 | void _debug() | 481 | void _debug() |
407 | { | 482 | { |
@@ -428,9 +503,10 @@ protected: | |||
428 | 503 | ||
429 | void objectChanged( const keytype &k ) | 504 | void objectChanged( const keytype &k ) |
430 | { | 505 | { |
506 | Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); | ||
507 | hChanged.insert( k, true ); | ||
431 | } | 508 | } |
432 | 509 | ||
433 | |||
434 | protected: | 510 | protected: |
435 | virtual void _create( const obtype *o )=0; | 511 | virtual void _create( const obtype *o )=0; |
436 | virtual void _erase( const keytype &k )=0; | 512 | virtual void _erase( const keytype &k )=0; |
@@ -438,14 +514,17 @@ protected: | |||
438 | virtual obtype *_load( const keytype &k )=0; | 514 | virtual obtype *_load( const keytype &k )=0; |
439 | virtual void _save( const obtype *o )=0; | 515 | virtual void _save( const obtype *o )=0; |
440 | 516 | ||
517 | virtual void _sync()=0; | ||
518 | |||
441 | private: | 519 | private: |
442 | Entry *addEntry( const obtype *pObject ) | 520 | Entry *addEntry( obtype *pObject ) |
443 | { | 521 | { |
444 | Entry *pEnt = new Entry( const_cast<obtype *>(pObject) ); | 522 | Entry *pEnt = new Entry( pObject ); |
445 | mCacheEntry.lockWrite(); | 523 | mCacheEntry.lockWrite(); |
446 | hCacheEntry.insert( pObject->getKey(), pEnt ); | 524 | hCacheEntry.insert( pObject->getKey(), pEnt ); |
447 | mCacheEntry.unlockWrite(); | 525 | mCacheEntry.unlockWrite(); |
448 | _create( pObject ); | 526 | _create( pObject ); |
527 | pObject->setCache( this, pEnt ); | ||
449 | 528 | ||
450 | return pEnt; | 529 | return pEnt; |
451 | } | 530 | } |
@@ -463,25 +542,60 @@ private: | |||
463 | // try to load the object from the backing store | 542 | // try to load the object from the backing store |
464 | obtype *pObject = _load( k ); | 543 | obtype *pObject = _load( k ); |
465 | pEnt = new Entry( pObject ); | 544 | pEnt = new Entry( pObject ); |
545 | pObject->setCache( this, pEnt ); | ||
466 | Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); | 546 | Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); |
467 | hCacheEntry.insert( k, pEnt ); | 547 | hCacheEntry.insert( k, pEnt ); |
468 | } | 548 | } |
469 | return pEnt; | 549 | return pEnt; |
470 | } | 550 | } |
471 | 551 | ||
552 | void syncChanges() | ||
553 | { | ||
554 | Bu::println("Syncing: %1 entries changed.").arg( hChanged.getSize() ); | ||
555 | if( !hChanged.isEmpty() ) | ||
556 | { | ||
557 | for( typename CacheKeySet::iterator i = hChanged.begin(); i; i++ ) | ||
558 | { | ||
559 | Entry *pEnt = hCacheEntry.get( i.getKey() ); | ||
560 | Bu::MutexLocker ml( pEnt->getMutex() ); | ||
561 | _save( pEnt->getPtr() ); | ||
562 | } | ||
563 | hChanged.clear(); | ||
564 | } | ||
565 | } | ||
566 | |||
472 | private: | 567 | private: |
473 | typedef Bu::Hash<keytype, Entry *> CacheEntryHash; | 568 | typedef Bu::Hash<keytype, Entry *> CacheEntryHash; |
569 | typedef Bu::Hash<keytype, bool> CacheKeySet; | ||
474 | CacheEntryHash hCacheEntry; | 570 | CacheEntryHash hCacheEntry; |
571 | CacheKeySet hChanged; | ||
475 | Bu::ReadWriteMutex mCacheEntry; | 572 | Bu::ReadWriteMutex mCacheEntry; |
476 | }; | 573 | }; |
477 | 574 | ||
575 | template<typename obtype> | ||
576 | void _cacheObjectSave( Bu::Stream &s, obtype *pObject ) | ||
577 | { | ||
578 | Bu::Archive ar( s, Bu::Archive::save ); | ||
579 | ar << *pObject; | ||
580 | } | ||
581 | |||
582 | template<typename obtype> | ||
583 | obtype *_cacheObjectLoad( Bu::Stream &s ) | ||
584 | { | ||
585 | Bu::Archive ar( s, Bu::Archive::load ); | ||
586 | obtype *ret = new obtype(); | ||
587 | ar >> *ret; | ||
588 | return ret; | ||
589 | } | ||
590 | |||
478 | template<typename keytype, typename obtype> | 591 | template<typename keytype, typename obtype> |
479 | class MyriadCache : public CacheBase<keytype, obtype> | 592 | class MyriadCache : public CacheBase<keytype, obtype> |
480 | { | 593 | { |
481 | public: | 594 | public: |
482 | MyriadCache( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ) : | 595 | MyriadCache( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ) : |
483 | sStore( sStore ), | 596 | sStore( sStore ), |
484 | mStore( sStore, iBlockSize, iPreallocate ) | 597 | mStore( sStore, iBlockSize, iPreallocate ), |
598 | bStructureChanged( false ) | ||
485 | { | 599 | { |
486 | try | 600 | try |
487 | { | 601 | { |
@@ -502,13 +616,14 @@ public: | |||
502 | if( mStore.createStreamWithId( 1 ) != 1 ) | 616 | if( mStore.createStreamWithId( 1 ) != 1 ) |
503 | throw Bu::ExceptionBase("Error creating index stream."); | 617 | throw Bu::ExceptionBase("Error creating index stream."); |
504 | 618 | ||
505 | sync(); | 619 | _sync(); |
506 | } | 620 | } |
507 | } | 621 | } |
508 | 622 | ||
509 | virtual ~MyriadCache() | 623 | virtual ~MyriadCache() |
510 | { | 624 | { |
511 | sync(); | 625 | Bu::println("MyriadCache destroying."); |
626 | _sync(); | ||
512 | } | 627 | } |
513 | 628 | ||
514 | using typename CacheBase<keytype,obtype>::KeyList; | 629 | using typename CacheBase<keytype,obtype>::KeyList; |
@@ -518,47 +633,60 @@ public: | |||
518 | Bu::ReadWriteMutex::ReadLocker rl( rwStore ); | 633 | Bu::ReadWriteMutex::ReadLocker rl( rwStore ); |
519 | return hIndex.getKeys(); | 634 | return hIndex.getKeys(); |
520 | } | 635 | } |
521 | 636 | ||
522 | virtual void sync() | 637 | virtual int getSize() const |
523 | { | 638 | { |
524 | Bu::ReadWriteMutex::ReadLocker wl( rwStore ); | 639 | Bu::ReadWriteMutex::ReadLocker rl( rwStore ); |
525 | Bu::MyriadStream ms = mStore.openStream( 1 ); | 640 | return hIndex.getSize(); |
526 | Bu::Archive ar( ms, Bu::Archive::save ); | ||
527 | ar << (uint8_t)0 << hIndex; | ||
528 | ar.close(); | ||
529 | ms.setSize( ms.tell() ); | ||
530 | } | 641 | } |
531 | 642 | ||
532 | protected: | 643 | protected: |
533 | virtual void _create( const obtype *o ) | 644 | virtual void _create( const obtype *o ) |
534 | { | 645 | { |
646 | Bu::ReadWriteMutex::WriteLocker wl( rwStore ); | ||
535 | hIndex.insert( o->getKey(), mStore.createStream() ); | 647 | hIndex.insert( o->getKey(), mStore.createStream() ); |
536 | _save( o ); | 648 | _save( o ); |
649 | |||
650 | bStructureChanged = true; | ||
537 | } | 651 | } |
538 | 652 | ||
539 | virtual void _erase( const keytype &k ) | 653 | virtual void _erase( const keytype &k ) |
540 | { | 654 | { |
655 | Bu::ReadWriteMutex::WriteLocker wl( rwStore ); | ||
541 | mStore.deleteStream( hIndex.get( k ) ); | 656 | mStore.deleteStream( hIndex.get( k ) ); |
542 | hIndex.erase( k ); | 657 | hIndex.erase( k ); |
658 | |||
659 | bStructureChanged = true; | ||
543 | } | 660 | } |
544 | 661 | ||
545 | virtual obtype *_load( const keytype &k ) | 662 | virtual obtype *_load( const keytype &k ) |
546 | { | 663 | { |
547 | Bu::MyriadStream ms = mStore.openStream( hIndex.get( k ) ); | 664 | Bu::MyriadStream ms = mStore.openStream( hIndex.get( k ) ); |
548 | Bu::Archive ar( ms, Bu::Archive::load ); | 665 | return _cacheObjectLoad<obtype>( ms ); |
549 | obtype *ret = new obtype(); | ||
550 | ar >> *ret; | ||
551 | return ret; | ||
552 | } | 666 | } |
553 | 667 | ||
554 | virtual void _save( const obtype *o ) | 668 | virtual void _save( const obtype *o ) |
555 | { | 669 | { |
556 | Bu::MyriadStream ms = mStore.openStream( hIndex.get( o->getKey() ) ); | 670 | Bu::MyriadStream ms = mStore.openStream( hIndex.get( o->getKey() ) ); |
557 | { | 671 | _cacheObjectSave( ms, o ); |
558 | Bu::Archive ar( ms, Bu::Archive::save ); | 672 | ms.setSize( ms.tell() ); |
559 | ar << *o; | 673 | } |
560 | } | 674 | |
675 | virtual void _sync() | ||
676 | { | ||
677 | Bu::println("Syncing myriad header."); | ||
678 | Bu::ReadWriteMutex::ReadLocker wl( rwStore ); | ||
679 | if( !bStructureChanged ) | ||
680 | return; | ||
681 | |||
682 | Bu::println(" --> Header changed, write required."); | ||
683 | Bu::MyriadStream ms = mStore.openStream( 1 ); | ||
684 | Bu::Archive ar( ms, Bu::Archive::save ); | ||
685 | ar << (uint8_t)0 << hIndex; | ||
686 | ar.close(); | ||
561 | ms.setSize( ms.tell() ); | 687 | ms.setSize( ms.tell() ); |
688 | |||
689 | bStructureChanged = false; | ||
562 | } | 690 | } |
563 | 691 | ||
564 | private: | 692 | private: |
@@ -566,6 +694,7 @@ private: | |||
566 | Bu::Myriad mStore; | 694 | Bu::Myriad mStore; |
567 | Bu::Hash<keytype, int> hIndex; | 695 | Bu::Hash<keytype, int> hIndex; |
568 | mutable Bu::ReadWriteMutex rwStore; | 696 | mutable Bu::ReadWriteMutex rwStore; |
697 | bool bStructureChanged; | ||
569 | }; | 698 | }; |
570 | 699 | ||
571 | // | 700 | // |
@@ -596,16 +725,72 @@ public: | |||
596 | return uId; | 725 | return uId; |
597 | } | 726 | } |
598 | 727 | ||
599 | Bu::String getName() | 728 | Bu::String getName() const |
600 | { | 729 | { |
601 | return sName; | 730 | return sName; |
602 | } | 731 | } |
603 | 732 | ||
733 | void setName( const Bu::String &sNewName ) | ||
734 | { | ||
735 | sName = sNewName; | ||
736 | changed(); | ||
737 | } | ||
738 | |||
739 | virtual Bu::String toString() const=0; | ||
740 | |||
604 | private: | 741 | private: |
605 | Bu::Uuid uId; | 742 | Bu::Uuid uId; |
606 | Bu::String sName; | 743 | Bu::String sName; |
607 | }; | 744 | }; |
608 | 745 | ||
746 | class SubSomethingA : public Something | ||
747 | { | ||
748 | friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, SubSomethingA &s ); | ||
749 | friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const SubSomethingA &s ); | ||
750 | public: | ||
751 | SubSomethingA() | ||
752 | { | ||
753 | } | ||
754 | |||
755 | SubSomethingA( const Bu::String &sName, int iNumber ) : | ||
756 | Something( sName ), | ||
757 | iNumber( iNumber ) | ||
758 | { | ||
759 | } | ||
760 | |||
761 | virtual Bu::String toString() const | ||
762 | { | ||
763 | return Bu::String("[typeA] %1 (%2)").arg( getName() ).arg( iNumber ); | ||
764 | } | ||
765 | |||
766 | private: | ||
767 | int iNumber; | ||
768 | }; | ||
769 | |||
770 | class SubSomethingB : public Something | ||
771 | { | ||
772 | friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, SubSomethingB &s ); | ||
773 | friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const SubSomethingB &s ); | ||
774 | public: | ||
775 | SubSomethingB() | ||
776 | { | ||
777 | } | ||
778 | |||
779 | SubSomethingB( const Bu::String &sName, const Bu::String &sString ) : | ||
780 | Something( sName ), | ||
781 | sString( sString ) | ||
782 | { | ||
783 | } | ||
784 | |||
785 | virtual Bu::String toString() const | ||
786 | { | ||
787 | return Bu::String("[typeB] %1 (%2)").arg( getName() ).arg( sString ); | ||
788 | } | ||
789 | |||
790 | private: | ||
791 | Bu::String sString; | ||
792 | }; | ||
793 | |||
609 | Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Something &s ) | 794 | Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Something &s ) |
610 | { | 795 | { |
611 | return ar >> s.uId >> s.sName; | 796 | return ar >> s.uId >> s.sName; |
@@ -616,7 +801,77 @@ Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Something &s ) | |||
616 | return ar << s.uId << s.sName; | 801 | return ar << s.uId << s.sName; |
617 | } | 802 | } |
618 | 803 | ||
804 | Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, SubSomethingA &s ) | ||
805 | { | ||
806 | return ar >> (Something &)s >> s.iNumber; | ||
807 | } | ||
808 | |||
809 | Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const SubSomethingA &s ) | ||
810 | { | ||
811 | return ar << (Something &)s << s.iNumber; | ||
812 | } | ||
813 | |||
814 | Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, SubSomethingB &s ) | ||
815 | { | ||
816 | return ar >> (Something &)s >> s.sString; | ||
817 | } | ||
818 | |||
819 | Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const SubSomethingB &s ) | ||
820 | { | ||
821 | return ar << (Something &)s << s.sString; | ||
822 | } | ||
823 | |||
824 | template<> | ||
825 | void _cacheObjectSave<const Something>( Bu::Stream &s, const Something *pObject ) | ||
826 | { | ||
827 | Bu::Archive ar( s, Bu::Archive::save ); | ||
828 | if( typeid(*pObject) == typeid(SubSomethingA) ) | ||
829 | { | ||
830 | ar << (uint8_t)1 << (SubSomethingA &)*pObject; | ||
831 | } | ||
832 | else if( typeid(*pObject) == typeid(SubSomethingB) ) | ||
833 | { | ||
834 | ar << (uint8_t)2 << (SubSomethingB &)*pObject; | ||
835 | } | ||
836 | else | ||
837 | { | ||
838 | Bu::println("Not a recognized type!"); | ||
839 | throw Bu::ExceptionBase("Not recognized type!"); | ||
840 | } | ||
841 | } | ||
842 | |||
843 | template<> | ||
844 | Something *_cacheObjectLoad<Something>( Bu::Stream &s ) | ||
845 | { | ||
846 | Bu::Archive ar( s, Bu::Archive::load ); | ||
847 | uint8_t uType; | ||
848 | ar >> uType; | ||
849 | switch( uType ) | ||
850 | { | ||
851 | case 1: | ||
852 | { | ||
853 | SubSomethingA *ret = new SubSomethingA(); | ||
854 | ar >> *ret; | ||
855 | return ret; | ||
856 | } | ||
857 | break; | ||
858 | |||
859 | case 2: | ||
860 | { | ||
861 | SubSomethingB *ret = new SubSomethingB(); | ||
862 | ar >> *ret; | ||
863 | return ret; | ||
864 | } | ||
865 | break; | ||
866 | |||
867 | default: | ||
868 | throw Bu::ExceptionBase("Flagrant error! Invalid type!"); | ||
869 | } | ||
870 | } | ||
871 | |||
619 | typedef CachePtr<Bu::Uuid, Something> SomethingPtr; | 872 | typedef CachePtr<Bu::Uuid, Something> SomethingPtr; |
873 | typedef CachePtr<Bu::Uuid, SubSomethingA, Something> SomethingAPtr; | ||
874 | typedef CachePtr<Bu::Uuid, SubSomethingB, Something> SomethingBPtr; | ||
620 | typedef MyriadCache<Bu::Uuid, Something> SomethingCache; | 875 | typedef MyriadCache<Bu::Uuid, Something> SomethingCache; |
621 | 876 | ||
622 | int main( int argc, char *argv[] ) | 877 | int main( int argc, char *argv[] ) |
@@ -624,6 +879,39 @@ int main( int argc, char *argv[] ) | |||
624 | Bu::File fStore("test.myr", Bu::File::Create|Bu::File::ReadWrite); | 879 | Bu::File fStore("test.myr", Bu::File::Create|Bu::File::ReadWrite); |
625 | SomethingCache c( fStore ); | 880 | SomethingCache c( fStore ); |
626 | 881 | ||
882 | SomethingPtr ptr; | ||
883 | if( time(NULL)%2 ) | ||
884 | ptr = c.insert( new SubSomethingA("Hello", 55) ).cast<Something>(); | ||
885 | else | ||
886 | ptr = c.insert( new SubSomethingB("Goodbye", "Things") ).cast<Something>(); | ||
887 | |||
888 | Bu::println("Something[%1]: %2"). | ||
889 | arg( ptr.getKey() ). | ||
890 | arg( ptr->getName() ); | ||
891 | |||
892 | SomethingCache::KeyList lKeys = c.getKeys(); | ||
893 | Bu::println("Count: %1").arg( lKeys.getSize() ); | ||
894 | int j = 0; | ||
895 | for( SomethingCache::KeyList::iterator i = lKeys.begin(); i; i++ ) | ||
896 | { | ||
897 | Bu::println(" - %1: '%2'").arg( *i ).arg( c.get( *i )->toString() ); | ||
898 | } | ||
899 | Bu::println("Count: %1").arg( c.getSize() ); | ||
900 | |||
901 | SomethingPtr p2 = c.get( ptr.getKey() ); | ||
902 | Bu::println("%1 == %2").arg( p2->getName() ).arg( ptr->getName() ); | ||
903 | SomethingPtr p3 = ptr.cast<Something>(); | ||
904 | Bu::println("%1: %2").arg( p3.getKey() ).arg( p3->getName() ); | ||
905 | |||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | /* | ||
910 | int main( int argc, char *argv[] ) | ||
911 | { | ||
912 | Bu::File fStore("test.myr", Bu::File::Create|Bu::File::ReadWrite); | ||
913 | SomethingCache c( fStore ); | ||
914 | |||
627 | for( int j = 1; j < argc; j++ ) | 915 | for( int j = 1; j < argc; j++ ) |
628 | { | 916 | { |
629 | SomethingPtr ptr = c.insert( new Something(argv[j]) ); | 917 | SomethingPtr ptr = c.insert( new Something(argv[j]) ); |
@@ -634,10 +922,15 @@ int main( int argc, char *argv[] ) | |||
634 | } | 922 | } |
635 | 923 | ||
636 | SomethingCache::KeyList lKeys = c.getKeys(); | 924 | SomethingCache::KeyList lKeys = c.getKeys(); |
925 | Bu::println("Count: %1").arg( lKeys.getSize() ); | ||
926 | int j = 0; | ||
637 | for( SomethingCache::KeyList::iterator i = lKeys.begin(); i; i++ ) | 927 | for( SomethingCache::KeyList::iterator i = lKeys.begin(); i; i++ ) |
638 | { | 928 | { |
639 | Bu::println(" - %1: '%2'").arg( *i ).arg( c.get( *i )->getName() ); | 929 | Bu::println(" - %1: '%2'").arg( *i ).arg( c.get( *i )->getName() ); |
930 | if( ((j++)%2) ) | ||
931 | c.erase( *i ); | ||
640 | } | 932 | } |
933 | Bu::println("Count: %1").arg( c.getSize() ); | ||
641 | 934 | ||
642 | c._debug(); | 935 | c._debug(); |
643 | 936 | ||
@@ -673,12 +966,18 @@ int main( int argc, char *argv[] ) | |||
673 | 966 | ||
674 | c._debug(); | 967 | c._debug(); |
675 | 968 | ||
969 | { | ||
676 | SomethingPtr::Locker l( p3 ); | 970 | SomethingPtr::Locker l( p3 ); |
677 | 971 | ||
678 | Bu::println("Name again: %1").arg( p3->getName() ); | 972 | Bu::println("Name again: %1").arg( p3->getName() ); |
679 | 973 | ||
974 | p3->setName( p3->getName() + " - again" ); | ||
975 | } | ||
976 | |||
977 | c.sync(); | ||
978 | |||
680 | c._debug(); | 979 | c._debug(); |
681 | 980 | ||
682 | return 0; | 981 | return 0; |
683 | } | 982 | } |
684 | 983 | */ | |