Annotation of parser3/src/main/pa_stylesheet_manager.C, revision 1.12
1.1 parser 1: /** @file
2: Parser: sql driver manager implementation.
3:
1.12 ! paf 4: Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)
1.4 paf 5: Author: Alexander Petrosyan <paf@design.ru> (http://paf.design.ru)
1.1 parser 6:
1.12 ! paf 7: $Id: pa_stylesheet_manager.C,v 1.11 2002/01/21 16:44:49 paf Exp $
1.1 parser 8: */
9: #include "pa_config_includes.h"
10: #ifdef XML
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
65: const char *request_file_spec_cstr=request_file_spec.cstr(String::UL_FILE_SPEC);
66: char *global_file_spec_cstr=(char *)malloc(strlen(request_file_spec_cstr)+1);
67: strcpy(global_file_spec_cstr, request_file_spec_cstr);
68: // make global_file_spec string on global pool
69: String& global_file_spec=*new(this->pool()) String(this->pool(), global_file_spec_cstr);
70:
1.10 paf 71: connection=new(this->pool()) Stylesheet_connection(this->pool(), global_file_spec);
1.1 parser 72: }
73: // associate with services[request] (deassociates at close)
1.10 paf 74: connection->set_services(&pool);
75: // return autoclosing object for it
1.11 paf 76: return Stylesheet_connection_ptr(connection);
1.1 parser 77: }
78:
79: void Stylesheet_manager::close_connection(const String& file_spec,
80: Stylesheet_connection& connection) {
81: // deassociate from services[request]
82: connection.set_services(0);
83: put_connection_to_cache(file_spec, connection);
84: }
85:
86:
87: // stylesheet cache
88: /// @todo get rid of memory spending Stack [zeros deep inside got accumulated]
89: Stylesheet_connection *Stylesheet_manager::get_connection_from_cache(const String& file_spec) {
90: SYNCHRONIZED;
91:
92: if(Stack *connections=static_cast<Stack *>(connection_cache.get(file_spec)))
93: while(connections->top_index()>=0) { // there are cached stylesheets to that 'file_spec'
94: Stylesheet_connection *result=static_cast<Stylesheet_connection *>(connections->pop());
95: if(result->connected()) // not expired?
96: return result;
97: }
98:
99: return 0;
100: }
101:
102: void Stylesheet_manager::put_connection_to_cache(const String& file_spec,
103: Stylesheet_connection& connection) {
104: SYNCHRONIZED;
105:
106: Stack *connections=static_cast<Stack *>(connection_cache.get(file_spec));
107: if(!connections) { // there are no cached stylesheets to that 'file_spec' yet?
108: connections=NEW Stack(pool()); // NOTE: never freed up!
109: connection_cache.put(file_spec, connections);
110: }
111: connections->push(&connection);
112: }
113:
1.5 paf 114: void Stylesheet_manager::maybe_expire_cache() {
1.1 parser 115: time_t now=time(0);
116:
117: if(prev_expiration_pass_time<now-CHECK_EXPIRED_CONNECTION_SECONDS) {
118: connection_cache.for_each(expire_connections,
119: reinterpret_cast<void *>(now-EXPIRE_UNUSED_CONNECTION_SECONDS));
120:
121: prev_expiration_pass_time=now;
122: }
123: }
1.2 paf 124:
1.3 paf 125: static void add_connection_to_status_cache_table(Array::Item *value, void *info) {
126: Stylesheet_connection& connection=*static_cast<Stylesheet_connection *>(value);
127: Table& table=*static_cast<Table *>(info);
128:
129: if(connection.connected()) {
130: Pool& pool=table.pool();
1.4 paf 131: Array& row=*new(pool) Array(pool);
1.3 paf 132:
1.4 paf 133: // file
1.3 paf 134: row+=&connection.file_spec();
1.4 paf 135: // time
1.3 paf 136: time_t time_stamp=connection.get_time_used();
137: const char *unsafe_time_cstr=ctime(&time_stamp);
138: int time_buf_size=strlen(unsafe_time_cstr);
139: char *safe_time_buf=(char *)pool.malloc(time_buf_size);
140: memcpy(safe_time_buf, unsafe_time_cstr, time_buf_size);
141: row+=new(pool) String(pool, safe_time_buf, time_buf_size);
142:
143: table+=&row;
144: }
145: }
146: static void add_connections_to_status_cache_table(const Hash::Key& key, Hash::Val *value, void *info) {
147: Stack& stack=*static_cast<Stack *>(value);
148: Array_iter iter(stack);
149: for(int countdown=stack.top_index(); countdown-->=0; )
150: add_connection_to_status_cache_table(iter.next(), info);
151: }
1.2 paf 152: Value& Stylesheet_manager::get_status(Pool& pool, const String *source) {
153: VHash& result=*new(pool) VHash(pool);
1.3 paf 154:
1.2 paf 155: // cache
156: {
1.4 paf 157: Array& columns=*new(pool) Array(pool);
1.3 paf 158: columns+=new(pool) String(pool, "file");
1.2 paf 159: columns+=new(pool) String(pool, "time");
160: Table& table=*new(pool) Table(pool, 0, &columns, connection_cache.size());
161:
162: connection_cache.for_each(add_connections_to_status_cache_table, &table);
163:
164: result.hash(source).put(*new(pool) String(pool, "cache"), new(pool) VTable(pool, &table));
165: }
1.3 paf 166:
1.2 paf 167: return result;
168: }
169:
1.1 parser 170: #endif
E-mail: