3 package OpenILS::Application::Storage;
4 use OpenSRF::Utils::Logger;
7 my $log = 'OpenSRF::Utils::Logger';
8 my $pg = 'OpenILS::Application::Storage::Driver::Pg';
11 $_->disconnect for $pg->db_Handles;
17 return $pg->current_xact_id;
19 __PACKAGE__->register_method(
20 method => 'current_xact',
21 api_name => 'open-ils.storage.transaction.current',
27 sub pg_begin_xaction {
31 local $OpenILS::Application::Storage::WRITE = 1;
33 if (my $old_xact = $pg->current_xact_session) {
34 if ($pg->current_xact_is_auto) {
35 $log->debug("Commiting old autocommit transaction with Open-ILS XACT-ID [$old_xact]", INFO);
36 $self->method_lookup("open-ils.storage.transaction.commit")->run();
38 $log->debug("Rolling back old NON-autocommit transaction with Open-ILS XACT-ID [$old_xact]", INFO);
39 $self->method_lookup("open-ils.storage.transaction.rollback")->run();
40 throw OpenSRF::DomainObject::oilsException->new(
42 status => "Previous transaction rolled back!",
47 $pg->set_xact_session( $client->session );
48 my $xact_id = $pg->current_xact_id;
50 $log->debug("Beginning a new transaction with Open-ILS XACT-ID [$xact_id]", INFO);
52 my $dbh = OpenILS::Application::Storage::CDBI->db_Main;
59 $log->debug("Failed to begin a new transaction with Open-ILS XACT-ID [$xact_id]: ".$e, INFO);
65 $dbh->do('SET LOCAL timezone TO ?;',{},$ENV{TZ});
69 $log->debug("Failed to set timezone: $ENV{TZ}", WARN);
74 if ($client->session) { # not a subrequest
75 my $death_cb = $client->session->register_callback(
77 __PACKAGE__->pg_rollback_xaction;
81 $log->debug("Registered 'death' callback [$death_cb] for new transaction with Open-ILS XACT-ID [$xact_id]", DEBUG);
83 $client->session->session_data( death_cb => $death_cb );
85 if ($self->api_name =~ /autocommit$/o) {
86 $pg->current_xact_is_auto(1);
87 my $dc_cb = $client->session->register_callback(
90 $ses->unregister_callback(death => $death_cb);
91 __PACKAGE__->pg_commit_xaction;
94 $log->debug("Registered 'disconnect' callback [$dc_cb] for new transaction with Open-ILS XACT-ID [$xact_id]", DEBUG);
95 if ($client and $client->session) {
96 $client->session->session_data( disconnect_cb => $dc_cb );
104 __PACKAGE__->register_method(
105 method => 'pg_begin_xaction',
106 api_name => 'open-ils.storage.transaction.begin',
110 __PACKAGE__->register_method(
111 method => 'pg_begin_xaction',
112 api_name => 'open-ils.storage.transaction.begin.autocommit',
117 sub pg_commit_xaction {
120 local $OpenILS::Application::Storage::WRITE = 1;
122 my $xact_id = $pg->current_xact_id;
126 $log->debug("Committing transaction with Open-ILS XACT-ID [$xact_id]", INFO) if ($xact_id);
127 my $dbh = OpenILS::Application::Storage::CDBI->db_Main;
132 $log->debug("Failed to commit transaction with Open-ILS XACT-ID [$xact_id]: ".$e, INFO);
136 if ($pg->current_xact_session) { # not a subrequest
137 $pg->current_xact_session->unregister_callback( death =>
138 $pg->current_xact_session->session_data( 'death_cb' )
139 ) if ($pg->current_xact_session);
141 if ($pg->current_xact_is_auto) {
142 $pg->current_xact_session->unregister_callback( disconnect =>
143 $pg->current_xact_session->session_data( 'disconnect_cb' )
148 $pg->unset_xact_session;
153 __PACKAGE__->register_method(
154 method => 'pg_commit_xaction',
155 api_name => 'open-ils.storage.transaction.commit',
160 sub pg_rollback_xaction {
163 local $OpenILS::Application::Storage::WRITE = 1;
165 my $xact_id = $pg->current_xact_id;
169 my $dbh = OpenILS::Application::Storage::CDBI->db_Main;
170 $log->debug("Rolling back a transaction with Open-ILS XACT-ID [$xact_id]", INFO);
175 $log->debug("Failed to roll back transaction with Open-ILS XACT-ID [$xact_id]: ".$e, INFO);
179 if ($pg->current_xact_session) { # not a subrequest
180 $pg->current_xact_session->unregister_callback( death =>
181 $pg->current_xact_session->session_data( 'death_cb' )
182 ) if ($pg->current_xact_session);
184 if ($pg->current_xact_is_auto) {
185 $pg->current_xact_session->unregister_callback( disconnect =>
186 $pg->current_xact_session->session_data( 'disconnect_cb' )
191 $pg->unset_xact_session;
195 __PACKAGE__->register_method(
196 method => 'pg_rollback_xaction',
197 api_name => 'open-ils.storage.transaction.rollback',
205 my $sp = shift || 'osrf_savepoint';
206 return OpenILS::Application::Storage::CDBI->db_Main->pg_savepoint($sp);
208 __PACKAGE__->register_method(
209 method => 'set_savepoint',
210 api_name => 'open-ils.storage.savepoint.set',
215 sub release_savepoint {
218 my $sp = shift || 'osrf_savepoint';
219 return OpenILS::Application::Storage::CDBI->db_Main->pg_release($sp);
221 __PACKAGE__->register_method(
222 method => 'release_savepoint',
223 api_name => 'open-ils.storage.savepoint.release',
228 sub rollback_to_savepoint {
231 my $sp = shift || 'osrf_savepoint';
232 return OpenILS::Application::Storage::CDBI->db_Main->pg_rollback_to($sp);
234 __PACKAGE__->register_method(
235 method => 'rollback_to_savepoint',
236 api_name => 'open-ils.storage.savepoint.rollback',
241 sub pg_set_audit_info {
244 my $authtoken = shift;
248 local $OpenILS::Application::Storage::WRITE = 1;
250 $log->debug("Setting auditor information", INFO);
252 if($pg->current_audit_session) {
253 $log->debug("Already sent audit data.", INFO);
257 my $dbh = OpenILS::Application::Storage::CDBI->db_Main;
261 my $ses = OpenSRF::AppSession->create('open-ils.auth');
262 my $content = $ses->request('open-ils.auth.session.retrieve', $authtoken, 1)->gather(1);
263 if(!$content or !$content->{userObj}) {
266 $user_id = $content->{userObj}->id;
267 $ws_id = $content->{userObj}->wsid;
269 $ws_id = 'NULL' unless $ws_id;
270 $dbh->do("SELECT auditor.set_audit_info($user_id, $ws_id);");
273 $log->debug("Failed to set auditor information: ".$e, INFO);
277 $pg->set_audit_session( $client->session );
279 if ($client->session) { # not a subrequest
280 my $death_cb = $client->session->register_callback(
282 __PACKAGE__->pg_clear_audit_info;
286 $log->debug("Registered 'death' callback [$death_cb] for clearing audit information", DEBUG);
288 $client->session->session_data( death_cb_ai => $death_cb );
294 __PACKAGE__->register_method(
295 method => 'pg_set_audit_info',
296 api_name => 'open-ils.storage.set_audit_info',
301 sub pg_clear_audit_info {
305 my $dbh = OpenILS::Application::Storage::CDBI->db_Main;
306 $log->debug("Clearing Audit Information", INFO);
307 $dbh->do("SELECT auditor.clear_audit_info();");
310 $log->debug("Failed to clear audit information: ".$e, INFO);
313 if ($pg->current_audit_session) { # not a subrequest
314 $pg->current_audit_session->unregister_callback( death =>
315 $pg->current_audit_session->session_data( 'death_cb_ai' )
316 ) if ($pg->current_audit_session);
319 $pg->unset_audit_session;
324 sub copy_create_start {
328 local $OpenILS::Application::Storage::WRITE = 1;
330 #return undef unless ($pg->current_xact_session);
332 my @cols = $self->{cdbi}->columns('Essential');
334 my ($p) = $self->{cdbi}->columns('Primary');
335 @cols = grep { $_ ne $p } @cols;
338 my $col_list = join ',', @cols;
340 $log->debug('Starting COPY import for '.$self->{cdbi}->table." ($col_list)", DEBUG);
341 $self->{cdbi}->sql_copy_start($self->{cdbi}->table, $col_list)->execute;
346 sub copy_create_push {
351 local $OpenILS::Application::Storage::WRITE = 1;
353 #return undef unless ($pg->current_xact_session);
355 my @cols = $self->{cdbi}->columns('Essential');
357 my ($p) = $self->{cdbi}->columns('Primary');
358 @cols = grep { $_ ne $p } @cols;
361 my $dbh = $self->{cdbi}->db_Main;
362 for my $node ( @fm_nodes ) {
364 my $line = join("\t", map { defined($node->$_()) ? $node->$_() : '\N' } @cols);
365 $log->debug("COPY line: [$line]",DEBUG);
366 $dbh->pg_putline($line."\n");
369 return scalar(@fm_nodes);
372 sub copy_create_finish {
377 local $OpenILS::Application::Storage::WRITE = 1;
379 #return undef unless ($pg->current_xact_session);
381 my $dbh = $self->{cdbi}->db_Main;
383 $dbh->pg_endcopy || $log->debug("Could not end COPY with pg_endcopy", WARN);
385 $log->debug('COPY import for '.$self->{cdbi}->table." ($col_list) complete", DEBUG);
395 local $NOPRIMARY = 1;
397 copy_create_start( $self => $client );
398 copy_create_push( $self => $client => @fm_nodes );
399 copy_create_finish( $self => $client );
401 return scalar(@fm_nodes);
407 $NOPRIMARY = $val if (defined $val);