r66599 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r66598‎ | r66599 | r66600 >
Date:02:38, 18 May 2010
Author:tstarling
Status:deferred
Tags:
Comment:
* Split off Session class from App.
* Reset sessions explicitly instead of using the shared_ptr destructor. Improves performance slightly by not copying shared_ptr's so often.
* Use a boost::pool for CacheEntry allocation. Doesn't really make any difference, may need to be reverted.
Modified paths:
  • /trunk/tools/maxcache/App.cpp (modified) (history)
  • /trunk/tools/maxcache/App.h (modified) (history)
  • /trunk/tools/maxcache/Cache.cpp (modified) (history)
  • /trunk/tools/maxcache/Cache.h (modified) (history)
  • /trunk/tools/maxcache/CacheEntry.h (modified) (history)
  • /trunk/tools/maxcache/Makefile (modified) (history)
  • /trunk/tools/maxcache/Session.cpp (added) (history)
  • /trunk/tools/maxcache/Session.h (added) (history)
  • /trunk/tools/maxcache/typedefs.h (modified) (history)

Diff [purge]

Index: trunk/tools/maxcache/App.cpp
@@ -10,7 +10,22 @@
1111 using namespace MaxCache;
1212
1313 const Time App::NO_TIME( boost::posix_time::not_a_date_time );
 14+const Time App::INFIN_TIME( boost::posix_time::pos_infin );
1415
 16+App::~App() {
 17+ SessionList::iterator i;
 18+ for ( i = mActiveSessions.begin(); i != mActiveSessions.end(); i = mActiveSessions.begin() ) {
 19+ Session & session = *i;
 20+ mActiveSessions.erase( i );
 21+ delete &session;
 22+ }
 23+ for ( i = mFreeSessions.begin(); i != mFreeSessions.end(); i = mFreeSessions.begin() ) {
 24+ Session & session = *i;
 25+ mFreeSessions.erase( i );
 26+ delete &session;
 27+ }
 28+}
 29+
1530 void App::run( int argc, char** argv ) {
1631 Endpoint endpoint( Tcp::v4(), 9999 );
1732 mAcceptor = AcceptorPtr( new Acceptor( mService, endpoint ) );
@@ -22,204 +37,42 @@
2338 } while ( numHandlers );
2439 }
2540
 41+Session & App::activateSession() {
 42+ Session * session;
 43+ if ( mFreeSessions.empty() ) {
 44+ session = new Session( *this );
 45+ mActiveSessions.push_front( *session );
 46+ } else {
 47+ SessionList::iterator i = mFreeSessions.begin();
 48+ mFreeSessions.erase( i );
 49+ mActiveSessions.push_front( *i );
 50+ session = &*i;
 51+ }
 52+ return *session;
 53+}
 54+
 55+void App::freeSession( Session & session ) {
 56+ session.reset();
 57+ mActiveSessions.erase( mActiveSessions.iterator_to( session ) );
 58+ mFreeSessions.push_front( session );
 59+}
 60+
2661 void App::startAccept() {
27 - // Create the peer socket
28 - SocketPtr peer( new Socket( mService ) );
 62+ // Get a session
 63+ Session & session = activateSession();
 64+
2965 // Start accepting connections
30 - mAcceptor->async_accept( *peer, boost::bind( &App::onAccept, this, peer, _1 ) );
 66+ mAcceptor->async_accept( session.getSocket(),
 67+ boost::bind( &App::onAccept, this, boost::ref( session ), _1 ) );
3168 }
3269
33 -void App::onAccept( SocketPtr peer, const ErrorCode & acceptError ) {
 70+void App::onAccept( Session & session, const ErrorCode & acceptError ) {
3471 if ( acceptError ) {
3572 throw SystemError( acceptError );
3673 }
3774 // Handle this connection
38 - startRead( peer );
 75+ session.startRead();
3976 // Listen for another connection
4077 startAccept();
4178 }
4279
43 -void App::startRead( SocketPtr peer ) {
44 - BufferPtr buffer( new Buffer( getMaxCmdLength() ) );
45 - Asio::async_read_until( *peer, *buffer, "\r\n",
46 - boost::bind( &App::onLineReady, this, peer, buffer, _1, _2 ) );
47 -}
48 -
49 -void App::onLineReady( SocketPtr peer, BufferPtr buffer,
50 - const ErrorCode & readError, std::size_t n )
51 -{
52 - if ( readError ) {
53 - // Close connection
54 - return;
55 - }
56 -
57 - std::istream stream( buffer.get() );
58 - std::string command;
59 -
60 - // Formatted extraction requires a sensible locale to be set
61 - stream.imbue( std::locale( "C" ) );
62 -
63 - stream >> command;
64 - if ( handleTooFewParams( peer, stream ) ) return;
65 -
66 - if ( command == "get" ) {
67 - std::string key;
68 - stream >> key;
69 - if ( handleTooFewParams( peer, stream ) ) return;
70 -
71 - CacheEntry * entry = mCache.getEntry( key );
72 - if ( !entry ) {
73 - writeMessage( peer, "NO: Item not found\r\n" );
74 - return;
75 - }
76 -
77 - writeCacheEntry( peer, entry->getValue() );
78 -
79 - } else if ( command == "set" ) {
80 - // Usage: set <key> <expiry> <cost> <value>
81 - std::string key;
82 - boost::uint32_t expiryInterval, clientCost;
83 - StringPtr value( new std::string );
84 -
85 - stream.width( mMaxKeyLength + 1 );
86 - stream >> key;
87 - if ( handleTooFewParams( peer, stream ) ) return;
88 - if ( key.size() > mMaxKeyLength ) {
89 - writeMessage( peer, "ERROR: Key too long\r\n" );
90 - return;
91 - }
92 -
93 - stream >> expiryInterval;
94 - if ( handleTooFewParams( peer, stream ) ) return;
95 - if ( stream.fail() ) {
96 - writeMessage( peer, "ERROR: invalid expiry interval\r\n" );
97 - return;
98 - }
99 -
100 - // Read the client cost, which is later divided by the size to get the
101 - // real cost
102 - stream >> clientCost;
103 - if ( handleTooFewParams( peer, stream ) ) return;
104 - if ( stream.fail() ) {
105 - writeMessage( peer, "ERROR: invalid clientCost\r\n" );
106 - return;
107 - }
108 -
109 - stream >> *value;
110 - if ( handleTooFewParams( peer, stream ) ) return;
111 - if ( value->size() > mCache.getMaxEntrySize() ) {
112 - writeMessage( peer, "ERROR: value too big\r\n" );
113 - return;
114 - }
115 -
116 - Time expiry;
117 - if ( expiryInterval ) {
118 - expiry = getTime() + boost::posix_time::microseconds( expiryInterval );
119 - } else {
120 - expiry = Time( boost::posix_time::pos_infin );
121 - }
122 -
123 - mCache.setEntry( key, value, clientCost, expiry );
124 - writeMessage( peer, "OK: value set\r\n" );
125 - } else if ( command == "delete" ) {
126 - std::string key;
127 - stream.width( mMaxKeyLength + 1 );
128 - stream >> key;
129 - if ( handleTooFewParams( peer, stream ) ) return;
130 - if ( key.size() > mMaxKeyLength ) {
131 - writeMessage( peer, "ERROR: Key too long\r\n" );
132 - return;
133 - }
134 -
135 - if ( mCache.deleteEntry( key ) ) {
136 - writeMessage( peer, "OK: deleted\r\n" );
137 - } else {
138 - writeMessage( peer, "NO: not found\r\n" );
139 - }
140 - } else if ( command == "quit" ) {
141 - // Let peer go out of scope and die
142 - } else if ( command == "stats" ) {
143 - writeStats( peer );
144 - } else if ( command == "kill" ) {
145 - // TODO: for debugging only, remove this
146 - mService.stop();
147 - } else {
148 - writeMessage( peer, "ERROR: Unknown command\r\n" );
149 - }
150 -}
151 -
152 -void App::writeMessage( SocketPtr peer, const char * msg ) {
153 - Asio::async_write(
154 - *peer,
155 - Asio::const_buffers_1( msg, std::strlen( msg ) ),
156 - boost::bind( &App::onWriteMessageDone, this, peer, _1, _2 ) );
157 -}
158 -
159 -void App::onWriteMessageDone( SocketPtr peer, const ErrorCode & writeError, std::size_t n ) {
160 - if ( writeError ) {
161 - // Close connection
162 - return;
163 - }
164 -
165 - startRead( peer );
166 -}
167 -
168 -void App::writeCacheEntry( SocketPtr peer, StringPtr entry ) {
169 - const char prefix[] = "VALUE: ";
170 - boost::array<Asio::const_buffer, 3> buffers;
171 - buffers[0] = Asio::const_buffer( prefix, sizeof( prefix ) );
172 - buffers[1] = Asio::const_buffer( entry->data(), entry->size() );
173 - buffers[2] = Asio::const_buffer( "\r\n", 2 );
174 -
175 - Asio::async_write( *peer, buffers,
176 - boost::bind(
177 - &App::onWriteCacheEntryDone, this, peer,
178 - entry, // just to keep a reference in memory so buffers[1] doesn't dangle
179 - _1, _2
180 - )
181 - );
182 -}
183 -
184 -void App::onWriteCacheEntryDone( SocketPtr peer, StringPtr entry,
185 - const ErrorCode & writeError, std::size_t n )
186 -{
187 - if ( writeError ) {
188 - // Close connection
189 - return;
190 - }
191 - startRead( peer );
192 - // entry will go out of scope here and may be deleted
193 -}
194 -
195 -void App::writeStats( SocketPtr peer ) {
196 - std::stringstream s;
197 - s << "STATS:"
198 - << " num-bytes=" << mCache.getNumBytes()
199 - << " num-entries=" << mCache.getSize()
200 - << " load-factor=" << mCache.getLoadFactor()
201 - << " max-bytes=" << mCache.getMaxBytes()
202 - << " max-load-factor=" << mCache.getMaxLoadFactor()
203 - << "\r\n";
204 - StringPtr sp( new std::string( s.str() ) );
205 - Asio::async_write(
206 - *peer,
207 - Asio::const_buffers_1( sp->data(), sp->size() ),
208 - boost::bind(
209 - &App::onWriteStatsDone, this, peer,
210 - sp, // just to keep a reference to sp
211 - _1, _2
212 - )
213 - );
214 -}
215 -
216 -void App::onWriteStatsDone( SocketPtr peer, StringPtr buffer,
217 - const ErrorCode & writeError, std::size_t n )
218 -{
219 - if ( writeError ) {
220 - // Close connection
221 - return;
222 - }
223 - startRead( peer );
224 - // buffer will go out of scope here and will be deleted
225 -}
226 -
Index: trunk/tools/maxcache/Cache.cpp
@@ -9,6 +9,7 @@
1010 mBuckets( new KeyTable::bucket_type[mNumBuckets] ),
1111 mKeyTable( KeyTable::bucket_traits( mBuckets.get(), mNumBuckets ) ),
1212 mClock( 0 ),
 13+ mEntryPool( 1024 ),
1314 mNumBytes( mNumBuckets * sizeof( KeyTable::bucket_type ) ),
1415 mMaxBytes( maxBytes ),
1516 mMaxEntrySizeLog2( 28 ),
@@ -31,7 +32,7 @@
3233 {
3334 boost::uint64_t cost = ( (boost::uint64_t)clientCost << mMaxEntrySizeLog2 )
3435 / value->size();
35 - CacheEntry * entry = new CacheEntry( *this, key, value, cost, expiry );
 36+ CacheEntry * entry = newEntry( key, value, cost, expiry );
3637 setEntryPointer( entry );
3738 }
3839
@@ -45,7 +46,7 @@
4647 // Too big, ignore this request.
4748 // This is equivalent to immediate eviction, so it doesn't break
4849 // the semantics of the insert operation.
49 - delete entry;
 50+ freeEntry( entry );
5051 return;
5152 }
5253
@@ -93,7 +94,7 @@
9495 mKeyTable.erase( mKeyTable.iterator_to( entry ) );
9596 mCostTree.erase( mCostTree.iterator_to( entry ) );
9697 mExpiryTree.erase( mExpiryTree.iterator_to( entry ) );
97 - delete &entry;
 98+ freeEntry( &entry );
9899 }
99100
100101 void Cache::evictUntilNormalSize() {
Index: trunk/tools/maxcache/Session.cpp
@@ -0,0 +1,216 @@
 2+#include "Session.h"
 3+#include "App.h"
 4+#include <boost/bind.hpp>
 5+#include <boost/foreach.hpp>
 6+
 7+using namespace MaxCache;
 8+
 9+Session::Session( App & app )
 10+ : mApp( app ),
 11+ mSocket( app.getService() ),
 12+ mInputBuffer( app.getMaxCmdLength() )
 13+{}
 14+
 15+void Session::reset()
 16+{
 17+ if ( mSocket.is_open() ) {
 18+ mSocket.shutdown( Socket::shutdown_both );
 19+ mSocket.close();
 20+ }
 21+ if ( mInputBuffer.size() ) {
 22+ mInputBuffer.consume( mInputBuffer.size() );
 23+ }
 24+ mWriteBuffer.clear();
 25+}
 26+
 27+void Session::startRead()
 28+{
 29+ Asio::async_read_until( mSocket, mInputBuffer, "\r\n",
 30+ boost::bind( &Session::onLineReady, this, _1, _2 ) );
 31+}
 32+
 33+void Session::onLineReady( const ErrorCode & readError, std::size_t n )
 34+{
 35+ if ( readError ) {
 36+ // Close connection
 37+ mApp.freeSession( *this );
 38+ return;
 39+ }
 40+
 41+ std::string line;
 42+ line.reserve( n );
 43+ BOOST_FOREACH( Asio::const_buffer block, mInputBuffer.data() ) {
 44+ line.append( Asio::buffer_cast<const char*>( block ), Asio::buffer_size( block ) );
 45+ }
 46+ mInputBuffer.consume( n );
 47+ std::stringstream stream( line );
 48+
 49+ // Formatted extraction requires a sensible locale to be set
 50+ stream.imbue( std::locale( "C" ) );
 51+
 52+ std::string command;
 53+ stream >> command;
 54+ if ( handleTooFewParams( stream ) ) return;
 55+
 56+ if ( command == "get" ) {
 57+ std::string key;
 58+ stream >> key;
 59+ if ( handleTooFewParams( stream ) ) return;
 60+
 61+ CacheEntry * entry = mApp.getCache().getEntry( key );
 62+ if ( !entry ) {
 63+ writeMessage( "NO: Item not found\r\n" );
 64+ return;
 65+ }
 66+
 67+ writeCacheEntry( entry->getValue() );
 68+
 69+ } else if ( command == "set" ) {
 70+ // Usage: set <key> <expiry> <cost> <value>
 71+ std::string key;
 72+ boost::uint32_t expiryInterval, clientCost;
 73+ StringPtr value( new std::string );
 74+
 75+ stream.width( mApp.getMaxKeyLength() + 1 );
 76+ stream >> key;
 77+ if ( handleTooFewParams( stream ) ) return;
 78+ if ( key.size() > mApp.getMaxKeyLength() ) {
 79+ writeMessage( "ERROR: Key too long\r\n" );
 80+ return;
 81+ }
 82+
 83+ stream >> expiryInterval;
 84+ if ( handleTooFewParams( stream ) ) return;
 85+ if ( stream.fail() ) {
 86+ writeMessage( "ERROR: invalid expiry interval\r\n" );
 87+ return;
 88+ }
 89+
 90+ // Read the client cost, which is later divided by the size to get the
 91+ // real cost
 92+ stream >> clientCost;
 93+ if ( handleTooFewParams( stream ) ) return;
 94+ if ( stream.fail() ) {
 95+ writeMessage( "ERROR: invalid clientCost\r\n" );
 96+ return;
 97+ }
 98+
 99+ stream >> *value;
 100+ if ( handleTooFewParams( stream ) ) return;
 101+ if ( value->size() > mApp.getCache().getMaxEntrySize() ) {
 102+ // This won't happen very often, usually the ASIO buffer limit will
 103+ // be exceeded instead.
 104+ writeMessage( "ERROR: value too big\r\n" );
 105+ return;
 106+ }
 107+
 108+ Time expiry;
 109+ if ( expiryInterval ) {
 110+ expiry = mApp.getTime() + boost::posix_time::microseconds( expiryInterval );
 111+ } else {
 112+ expiry = Time( App::INFIN_TIME );
 113+ }
 114+
 115+ mApp.getCache().setEntry( key, value, clientCost, expiry );
 116+ writeMessage( "OK: value set\r\n" );
 117+ } else if ( command == "delete" ) {
 118+ std::string key;
 119+ stream.width( mApp.getMaxKeyLength() + 1 );
 120+ stream >> key;
 121+ if ( handleTooFewParams( stream ) ) return;
 122+ if ( key.size() > mApp.getMaxKeyLength() ) {
 123+ writeMessage( "ERROR: Key too long\r\n" );
 124+ return;
 125+ }
 126+
 127+ if ( mApp.getCache().deleteEntry( key ) ) {
 128+ writeMessage( "OK: deleted\r\n" );
 129+ } else {
 130+ writeMessage( "NO: not found\r\n" );
 131+ }
 132+ } else if ( command == "quit" ) {
 133+ mApp.freeSession( *this );
 134+ } else if ( command == "stats" ) {
 135+ writeStats();
 136+ } else if ( command == "kill" ) {
 137+ // TODO: for debugging only, remove this
 138+ mApp.stop();
 139+ } else {
 140+ writeMessage( "ERROR: Unknown command\r\n" );
 141+ }
 142+}
 143+
 144+void Session::writeMessage( const char * msg ) {
 145+ Asio::async_write(
 146+ mSocket,
 147+ Asio::const_buffers_1( msg, std::strlen( msg ) ),
 148+ boost::bind( &Session::onWriteMessageDone, this, _1, _2 ) );
 149+}
 150+
 151+void Session::onWriteMessageDone( const ErrorCode & writeError, std::size_t n ) {
 152+ if ( writeError ) {
 153+ // Close connection
 154+ mApp.freeSession( *this );
 155+ return;
 156+ }
 157+
 158+ startRead();
 159+}
 160+
 161+void Session::writeCacheEntry( StringPtr entry ) {
 162+ const char prefix[] = "VALUE: ";
 163+
 164+ boost::array<Asio::const_buffer, 3> buffers;
 165+ buffers[0] = Asio::const_buffer( prefix, sizeof( prefix ) );
 166+ buffers[1] = Asio::const_buffer( entry->data(), entry->size() );
 167+ buffers[2] = Asio::const_buffer( "\r\n", 2 );
 168+
 169+ Asio::async_write( mSocket, buffers,
 170+ boost::bind(
 171+ &Session::onWriteCacheEntryDone, this,
 172+ entry, // just to keep a reference in memory so buffers[1] doesn't dangle
 173+ _1, _2
 174+ )
 175+ );
 176+}
 177+
 178+void Session::onWriteCacheEntryDone( StringPtr entry, const ErrorCode & writeError,
 179+ std::size_t n )
 180+{
 181+ if ( writeError ) {
 182+ // Close connection
 183+ mApp.freeSession( *this );
 184+ return;
 185+ }
 186+ startRead();
 187+ // entry will go out of scope here and may be deleted
 188+}
 189+
 190+void Session::writeStats() {
 191+ std::stringstream s;
 192+ s << "STATS:"
 193+ << " num-bytes=" << mApp.getCache().getNumBytes()
 194+ << " num-entries=" << mApp.getCache().getSize()
 195+ << " load-factor=" << mApp.getCache().getLoadFactor()
 196+ << " max-bytes=" << mApp.getCache().getMaxBytes()
 197+ << " max-load-factor=" << mApp.getCache().getMaxLoadFactor()
 198+ << "\r\n";
 199+ mWriteBuffer = s.str();
 200+ Asio::async_write(
 201+ mSocket,
 202+ Asio::const_buffers_1( mWriteBuffer.data(), mWriteBuffer.size() ),
 203+ boost::bind( &Session::onWriteStatsDone, this, _1, _2 )
 204+ );
 205+}
 206+
 207+void Session::onWriteStatsDone( const ErrorCode & writeError, std::size_t n )
 208+{
 209+ if ( writeError ) {
 210+ // Close connection
 211+ mApp.freeSession( *this );
 212+ return;
 213+ }
 214+ startRead();
 215+ // buffer will go out of scope here and will be deleted
 216+}
 217+
Property changes on: trunk/tools/maxcache/Session.cpp
___________________________________________________________________
Name: svn:eol-style
1218 + native
Index: trunk/tools/maxcache/App.h
@@ -9,22 +9,11 @@
1010 #include <string>
1111 #include "typedefs.h"
1212 #include "Cache.h"
 13+#include "Session.h"
1314
1415 namespace MaxCache {
1516
16 -namespace Asio = boost::asio;
17 -typedef boost::asio::ip::tcp Tcp;
18 -typedef boost::asio::io_service Service;
19 -typedef Tcp::endpoint Endpoint;
20 -typedef Tcp::acceptor Acceptor;
21 -typedef boost::shared_ptr<Acceptor> AcceptorPtr;
22 -typedef Tcp::socket Socket;
23 -typedef boost::shared_ptr<Socket> SocketPtr;
24 -typedef boost::system::error_code ErrorCode;
25 -typedef boost::system::system_error SystemError;
26 -typedef boost::asio::streambuf Buffer;
27 -typedef boost::shared_ptr<Buffer> BufferPtr;
28 -typedef boost::asio::buffers_iterator< Buffer::const_buffers_type > BufferIterator;
 17+typedef Intrusive::list< Session, SessionListMemberOption > SessionList;
2918
3019 class App {
3120 public:
@@ -33,8 +22,17 @@
3423 mCache( *this, 100000000 )
3524 {}
3625
 26+ ~App();
 27+
3728 void run( int argc, char** argv );
3829
 30+ Session & activateSession();
 31+ void freeSession( Session & session );
 32+
 33+ void stop() {
 34+ mService.stop();
 35+ }
 36+
3937 Service & getService() {
4038 return mService;
4139 }
@@ -56,47 +54,31 @@
5755 mTime = NO_TIME;
5856 }
5957
 58+ std::size_t getMaxKeyLength() const { return mMaxKeyLength; }
 59+
6060 std::size_t getMaxCmdLength() const {
6161 return mCache.getMaxEntrySize() + mMaxKeyLength + sizeof( "blah\r\n" );
6262 }
6363
 64+ const Cache & getCache() const { return mCache; }
 65+ Cache & getCache() { return mCache; }
 66+
6467 void startAccept();
65 - void onAccept( SocketPtr peer, const ErrorCode & acceptError );
 68+ void onAccept( Session & session, const ErrorCode & acceptError );
6669
67 - void startRead( SocketPtr peer );
68 - void onLineReady( SocketPtr peer, BufferPtr buffer,
69 - const ErrorCode & readError, std::size_t n );
70 -
71 - void writeMessage( SocketPtr peer, const char * msg );
72 - void onWriteMessageDone( SocketPtr peer, const ErrorCode & writeMessage, std::size_t n );
73 -
74 - void writeCacheEntry( SocketPtr peer, StringPtr entry );
75 - void onWriteCacheEntryDone( SocketPtr peer, StringPtr entry,
76 - const ErrorCode & writeError, std::size_t n );
77 -
78 - void writeStats( SocketPtr peer );
79 - void onWriteStatsDone( SocketPtr peer, StringPtr buffer,
80 - const ErrorCode & writeError, std::size_t n );
 70+ const static Time NO_TIME;
 71+ const static Time INFIN_TIME;
8172 protected:
82 - bool handleTooFewParams( SocketPtr peer, std::istream & stream ) {
83 - if ( stream.eof() ) {
84 - writeMessage( peer, "ERROR: Not enough parameters\r\n" );
85 - return true;
86 - } else {
87 - return false;
88 - }
89 - }
9073
91 -
9274 Service mService;
9375 AcceptorPtr mAcceptor;
 76+ SessionList mFreeSessions;
 77+ SessionList mActiveSessions;
9478
9579 const std::size_t mMaxKeyLength;
9680
9781 Cache mCache;
9882 Time mTime;
99 -
100 - const static Time NO_TIME;
10183 };
10284
10385 }
Index: trunk/tools/maxcache/Cache.h
@@ -4,6 +4,7 @@
55 #include "boost-config.h"
66 #include "CacheEntry.h"
77 #include <boost/shared_array.hpp>
 8+#include <boost/pool/object_pool.hpp>
89
910 namespace MaxCache {
1011
@@ -27,6 +28,8 @@
2829 compare< CacheEntry::CompareExpiries >
2930 > ExpiryTree;
3031
 32+typedef boost::object_pool<CacheEntry> CacheEntryPool;
 33+
3134 class App;
3235
3336 class Cache {
@@ -119,6 +122,27 @@
120123 */
121124 void evictExpiredEntries();
122125
 126+ /**
 127+ * Create a new CacheEntry object
 128+ */
 129+ CacheEntry * newEntry( const std::string & key, StringPtr value,
 130+ boost::uint64_t cost, Time expiry )
 131+ {
 132+ CacheEntry * entry = mEntryPool.malloc();
 133+ mEntryPool.set_next_size( 1024 );
 134+ new ( entry ) CacheEntry( *this, key, value, cost, expiry );
 135+ return entry;
 136+ //return new CacheEntry( *this, key, value, cost, expiry );
 137+ }
 138+
 139+ /**
 140+ * Free a CacheEntry object created by newEntry()
 141+ */
 142+ void freeEntry( CacheEntry * entry ) {
 143+ mEntryPool.free( entry );
 144+ //delete entry;
 145+ }
 146+
123147 float mMaxLoadFactor;
124148 std::size_t mNumBuckets;
125149 boost::shared_array<KeyTable::bucket_type> mBuckets;
@@ -128,6 +152,8 @@
129153 ExpiryTree mExpiryTree;
130154 boost::uint64_t mClock;
131155
 156+ CacheEntryPool mEntryPool;
 157+
132158 std::size_t mNumBytes;
133159 std::size_t mMaxBytes;
134160 unsigned char mMaxEntrySizeLog2;
Index: trunk/tools/maxcache/Session.h
@@ -0,0 +1,58 @@
 2+#ifndef MAXCACHE_SESSION_H
 3+#define MAXCACHE_SESSION_H
 4+
 5+#include "boost-config.h"
 6+#include <boost/intrusive/list.hpp>
 7+#include "typedefs.h"
 8+
 9+using namespace boost::intrusive;
 10+
 11+namespace MaxCache {
 12+
 13+typedef Intrusive::list_member_hook<> ListHook;
 14+
 15+class App;
 16+
 17+class Session {
 18+ public:
 19+ Session( App & app );
 20+ void reset();
 21+
 22+ Socket & getSocket() {
 23+ return mSocket;
 24+ }
 25+
 26+ void startRead();
 27+ void onLineReady( const ErrorCode & readError, std::size_t n );
 28+
 29+ void writeMessage( const char * msg );
 30+ void onWriteMessageDone( const ErrorCode & writeError, std::size_t n );
 31+
 32+ void writeCacheEntry( StringPtr entry );
 33+ void onWriteCacheEntryDone( StringPtr entry, const ErrorCode & writeError, std::size_t n );
 34+
 35+ void writeStats();
 36+ void onWriteStatsDone( const ErrorCode & writeError, std::size_t n );
 37+
 38+ ListHook mListHook;
 39+
 40+ protected:
 41+ bool handleTooFewParams( std::istream & stream ) {
 42+ if ( stream.eof() ) {
 43+ writeMessage( "ERROR: Not enough parameters\r\n" );
 44+ return true;
 45+ } else {
 46+ return false;
 47+ }
 48+ }
 49+
 50+ App & mApp;
 51+ Socket mSocket;
 52+ Buffer mInputBuffer;
 53+ std::string mWriteBuffer;
 54+};
 55+
 56+typedef Intrusive::member_hook< Session, ListHook, &Session::mListHook > SessionListMemberOption;
 57+
 58+}
 59+#endif
Property changes on: trunk/tools/maxcache/Session.h
___________________________________________________________________
Name: svn:eol-style
160 + native
Index: trunk/tools/maxcache/typedefs.h
@@ -1,12 +1,36 @@
22 #ifndef MAXCACHE_TYPEDEFS_H
33 #define MAXCACHE_TYPEDEFS_H
44
 5+#include "boost-config.h"
56 #include <string>
67 #include <boost/shared_ptr.hpp>
78 #include <boost/date_time/posix_time/posix_time_types.hpp>
 9+#include <boost/intrusive/intrusive_fwd.hpp>
 10+#include <boost/asio.hpp>
 11+
812 namespace MaxCache {
 13+ // Misc
914 typedef boost::shared_ptr<std::string> StringPtr;
1015 typedef boost::posix_time::ptime Time;
 16+
 17+ // Intrusive
 18+ namespace Intrusive = boost::intrusive;
 19+
 20+ // Asio
 21+ namespace Asio = boost::asio;
 22+
 23+ typedef Asio::ip::tcp Tcp;
 24+ typedef Asio::io_service Service;
 25+ typedef Tcp::endpoint Endpoint;
 26+ typedef Tcp::acceptor Acceptor;
 27+ typedef boost::shared_ptr<Acceptor> AcceptorPtr;
 28+ typedef boost::system::error_code ErrorCode;
 29+ typedef boost::system::system_error SystemError;
 30+
 31+ typedef Asio::streambuf Buffer;
 32+ typedef Asio::buffers_iterator< Buffer::const_buffers_type > BufferIterator;
 33+ typedef Tcp::socket Socket;
 34+
1135 }
1236
1337 #endif
Index: trunk/tools/maxcache/CacheEntry.h
@@ -14,10 +14,8 @@
1515
1616 namespace MaxCache {
1717
18 -namespace Intrusive = boost::intrusive;
19 -
2018 typedef Intrusive::unordered_set_member_hook< store_hash<true> > HashHook;
21 -typedef Intrusive::set_base_hook<> TreeHook;
 19+typedef Intrusive::set_member_hook<> TreeHook;
2220
2321 class Cache;
2422
Index: trunk/tools/maxcache/Makefile
@@ -2,7 +2,7 @@
33
44 CFLAGS:=$(CFLAGS) -ggdb3 -Wall
55
6 -maxcache: maxcache.o App.o CacheEntry.o Cache.o
 6+maxcache: maxcache.o App.o CacheEntry.o Cache.o Session.o
77 g++ $^ $(CFLAGS) -lboost_system -o $@
88
99 %.o : %.cpp

Status & tagging log