Annotation of parser3/src/main/pa_stylesheet_manager.C, revision 1.16.2.4
1.1 parser 1: /** @file
2: Parser: sql driver manager implementation.
3:
1.16.2.1 paf 4: Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
1.13 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1 parser 6: */
7: #include "pa_config_includes.h"
8: #ifdef XML
1.14 paf 9:
1.16.2.4! paf 10: static const char* IDENT_STYLESHEET_MANAGER_C="$Date: 2003/02/19 16:19:01 $";
1.1 parser 11:
12: #include "pa_stylesheet_manager.h"
13: #include "pa_stylesheet_connection.h"
14: #include "pa_exception.h"
15: #include "pa_common.h"
16: #include "pa_threads.h"
17: #include "pa_stack.h"
1.2 paf 18: #include "pa_vhash.h"
1.3 paf 19: #include "pa_vtable.h"
1.1 parser 20:
21: // globals
22:
23: Stylesheet_manager *stylesheet_manager;
24:
25: // consts
26:
27: const int EXPIRE_UNUSED_CONNECTION_SECONDS=5*60;
28: const int CHECK_EXPIRED_CONNECTION_SECONDS=EXPIRE_UNUSED_CONNECTION_SECONDS*2;
29:
30: // helpers
31:
32: static void expire_connection(Array::Item *value, void *info) {
33: Stylesheet_connection& connection=*static_cast<Stylesheet_connection *>(value);
34: time_t older_dies=reinterpret_cast<time_t>(info);
35:
36: if(connection.connected() && connection.expired(older_dies))
37: connection.disconnect();
38: }
39: static void expire_connections(const Hash::Key& key, Hash::Val *value, void *info) {
40: Stack& stack=*static_cast<Stack *>(value);
41: for(int i=0; i<=stack.top_index(); i++)
42: expire_connection(stack.get(i), info);
43: }
44:
45: // Stylesheet_manager
46:
1.6 paf 47: Stylesheet_manager::Stylesheet_manager(Pool& apool) : Cache_manager(apool),
1.3 paf 48: connection_cache(apool),
1.1 parser 49: prev_expiration_pass_time(0) {
1.5 paf 50: }
1.1 parser 51: Stylesheet_manager::~Stylesheet_manager() {
52: connection_cache.for_each(expire_connections,
1.8 paf 53: reinterpret_cast<void *>(time(0)+1/*=in future=expire all*/));
1.1 parser 54: }
55:
1.10 paf 56: Stylesheet_connection_ptr Stylesheet_manager::get_connection(const String& request_file_spec) {
1.1 parser 57: Pool& pool=request_file_spec.pool(); // request pool
58:
59: // first trying to get cached stylesheet
1.10 paf 60: Stylesheet_connection *connection=get_connection_from_cache(request_file_spec);
61: if(!connection) {
1.1 parser 62: // then just construct it
63:
64: // make global_file_spec C-string on global pool
1.16.2.4! paf 65: CharPtr global_file_spec_cstr=request_file_spec.cstr(this->pool(pool), String::UL_FILE_SPEC);
1.1 parser 66: // make global_file_spec string on global pool
1.16.2.4! paf 67: String& global_file_spec=*new(this->pool()) String(this->pool(), global_file_spec_cstr);
1.1 parser 68:
1.10 paf 69: connection=new(this->pool()) Stylesheet_connection(this->pool(), global_file_spec);
1.1 parser 70: }
71: // associate with services[request] (deassociates at close)
1.10 paf 72: connection->set_services(&pool);
73: // return autoclosing object for it
1.11 paf 74: return Stylesheet_connection_ptr(connection);
1.1 parser 75: }
76:
77: void Stylesheet_manager::close_connection(const String& file_spec,
78: Stylesheet_connection& connection) {
79: // deassociate from services[request]
80: connection.set_services(0);
81: put_connection_to_cache(file_spec, connection);
82: }
83:
84:
85: // stylesheet cache
86: /// @todo get rid of memory spending Stack [zeros deep inside got accumulated]
87: Stylesheet_connection *Stylesheet_manager::get_connection_from_cache(const String& file_spec) {
88: SYNCHRONIZED;
89:
90: if(Stack *connections=static_cast<Stack *>(connection_cache.get(file_spec)))
91: while(connections->top_index()>=0) { // there are cached stylesheets to that 'file_spec'
92: Stylesheet_connection *result=static_cast<Stylesheet_connection *>(connections->pop());
93: if(result->connected()) // not expired?
94: return result;
95: }
96:
97: return 0;
98: }
99:
100: void Stylesheet_manager::put_connection_to_cache(const String& file_spec,
101: Stylesheet_connection& connection) {
102: SYNCHRONIZED;
103:
104: Stack *connections=static_cast<Stack *>(connection_cache.get(file_spec));
105: if(!connections) { // there are no cached stylesheets to that 'file_spec' yet?
106: connections=NEW Stack(pool()); // NOTE: never freed up!
107: connection_cache.put(file_spec, connections);
108: }
109: connections->push(&connection);
110: }
111:
1.5 paf 112: void Stylesheet_manager::maybe_expire_cache() {
1.1 parser 113: time_t now=time(0);
114:
115: if(prev_expiration_pass_time<now-CHECK_EXPIRED_CONNECTION_SECONDS) {
116: connection_cache.for_each(expire_connections,
117: reinterpret_cast<void *>(now-EXPIRE_UNUSED_CONNECTION_SECONDS));
118:
119: prev_expiration_pass_time=now;
120: }
121: }
1.2 paf 122:
1.3 paf 123: static void add_connection_to_status_cache_table(Array::Item *value, void *info) {
124: Stylesheet_connection& connection=*static_cast<Stylesheet_connection *>(value);
125: Table& table=*static_cast<Table *>(info);
126:
127: if(connection.connected()) {
128: Pool& pool=table.pool();
1.4 paf 129: Array& row=*new(pool) Array(pool);
1.3 paf 130:
1.4 paf 131: // file
1.3 paf 132: row+=&connection.file_spec();
1.4 paf 133: // time
1.3 paf 134: time_t time_stamp=connection.get_time_used();
1.16.2.2 paf 135: row+=new(pool) String(pool, pool.copy(ctime(&time_stamp)));
1.3 paf 136:
137: table+=&row;
138: }
139: }
140: static void add_connections_to_status_cache_table(const Hash::Key& key, Hash::Val *value, void *info) {
141: Stack& stack=*static_cast<Stack *>(value);
142: Array_iter iter(stack);
143: for(int countdown=stack.top_index(); countdown-->=0; )
144: add_connection_to_status_cache_table(iter.next(), info);
145: }
1.2 paf 146: Value& Stylesheet_manager::get_status(Pool& pool, const String *source) {
147: VHash& result=*new(pool) VHash(pool);
1.3 paf 148:
1.2 paf 149: // cache
150: {
1.4 paf 151: Array& columns=*new(pool) Array(pool);
1.3 paf 152: columns+=new(pool) String(pool, "file");
1.2 paf 153: columns+=new(pool) String(pool, "time");
154: Table& table=*new(pool) Table(pool, 0, &columns, connection_cache.size());
155:
156: connection_cache.for_each(add_connections_to_status_cache_table, &table);
157:
158: result.hash(source).put(*new(pool) String(pool, "cache"), new(pool) VTable(pool, &table));
159: }
1.3 paf 160:
1.2 paf 161: return result;
162: }
163:
1.1 parser 164: #endif
E-mail: