MOON
Server: Apache/2.2.31 (Unix) mod_ssl/2.2.31 OpenSSL/0.9.8e-fips-rhel5 mod_bwlimited/1.4
System: Linux csr818.wilogic.com 2.6.18-419.el5xen #1 SMP Fri Feb 24 22:50:37 UTC 2017 x86_64
User: digitals (531)
PHP: 5.4.45
Disabled: NONE
Upload Files
File: //usr/local/ssl/local/share/man/man3/Cpanel::TaskQueue::Scheduler.3
.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sh \" Subsection heading
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  | will give a
.\" real vertical bar.  \*(C+ will give a nicer C++.  Capital omega is used to
.\" do unbreakable dashes and therefore won't be available.  \*(C` and \*(C'
.\" expand to `' in nroff, nothing in troff, for use with C<>.
.tr \(*W-|\(bv\*(Tr
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
'br\}
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.if \nF \{\
.    de IX
.    tm Index:\\$1\t\\n%\t"\\$2"
..
.    nr % 0
.    rr F
.\}
.\"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.hy 0
.if n .na
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
.    \" fudge factors for nroff and troff
.if n \{\
.    ds #H 0
.    ds #V .8m
.    ds #F .3m
.    ds #[ \f1
.    ds #] \fP
.\}
.if t \{\
.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
.    ds #V .6m
.    ds #F 0
.    ds #[ \&
.    ds #] \&
.\}
.    \" simple accents for nroff and troff
.if n \{\
.    ds ' \&
.    ds ` \&
.    ds ^ \&
.    ds , \&
.    ds ~ ~
.    ds /
.\}
.if t \{\
.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
.    \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
.    \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
.    \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
.    ds : e
.    ds 8 ss
.    ds o a
.    ds d- d\h'-1'\(ga
.    ds D- D\h'-1'\(hy
.    ds th \o'bp'
.    ds Th \o'LP'
.    ds ae ae
.    ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "Cpanel::TaskQueue::Scheduler 3"
.TH Cpanel::TaskQueue::Scheduler 3 "2011-01-04" "perl v5.8.8" "User Contributed Perl Documentation"
.SH "NAME"
Cpanel::TaskQueue::Scheduler \- Priority queue of Tasks to Queue at some time in the future.
.SH "VERSION"
.IX Header "VERSION"
This document describes Cpanel::TaskQueue::Scheduler version 0.307.
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
.Vb 2
\&    use Cpanel::TaskQueue;
\&    use Cpanel::TaskQueue::Scheduler;
.Ve
.PP
.Vb 2
\&    my $queue = Cpanel::TaskQueue->new( { name => 'tasks', cache_dir => '/home/$user/.cpanel/cache' } );
\&    my $sched = Cpanel::TaskQueue::Scheduler->new( { name => 'tasks', cache_dir => '/home/$user/.cpanel/cache' } );
.Ve
.PP
.Vb 2
\&    $sched->schedule_task( 'init_quota', {delay_seconds=>10} );
\&    $sched->schedule_task( 'edit_quota fred 0', {delay_seconds=>60} );
.Ve
.PP
.Vb 12
\&    # ... some time later ...
\&    # This processing loop is a it more complicated than the one for just
\&    # the TaskQueue.
\&    while (1) {
\&        eval {
\&            $sched->process_ready_tasks( $queue );
\&            if ( $queue->has_work_to_do() ) {
\&                $queue->process_next_task();
\&            }
\&            else {
\&                my $wait = $sched->seconds_until_next_task();
\&                next if defined $wait and 0 == $wait;
.Ve
.PP
.Vb 6
\&                $wait = $default_wait if !$wait || $wait > $default_wait;
\&                sleep $wait;
\&            }
\&        };
\&        Carp::carp "Exception detected: $@" if $@;
\&    }
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
This module provides the ability to schedule tasks for later insertion into a
\&\f(CW\*(C`Cpanel::TaskQueue\*(C'\fR.
.SH "PUBLIC METHODS"
.IX Header "PUBLIC METHODS"
.ie n .IP "Cpanel::TaskQueue::Scheduler\->new( $hashref )" 4
.el .IP "Cpanel::TaskQueue::Scheduler\->new( \f(CW$hashref\fR )" 4
.IX Item "Cpanel::TaskQueue::Scheduler->new( $hashref )"
Creates a new TaskQueue::Scheduler object based on the parameters from the
supplied hashref.
.RS 4
.IP "\fIcache_dir\fR" 4
.IX Item "cache_dir"
This required parameter specifies a directory where the cache should be written.
This directory is created if it does not exist.
.IP "\fIname\fR" 4
.IX Item "name"
This required parameter specifies the name of the scheduler. This name is used
to construct the name of the cache file used to store the scheduler information.
.IP "\fIcache_timeout\fR" 4
.IX Item "cache_timeout"
This optional parameter specifies the timeout to use for flocking the cache file.
The value is in seconds and defaults to the Cpanel::CacheFile default value.
.IP "\fItoken\fR" 4
.IX Item "token"
If a valid token parameter is supplied, recreate the \f(CW\*(C`Scheduler\*(C'\fR described by
the token. This allows recreating access to a Scheduler that was instantiated
in another process.  It also helps support serializing information about a
\&\f(CW\*(C`Scheduler\*(C'\fR as part of a defined task.
.Sp
If a token is supplied, the \fIname\fR and \fIcache_dir\fR parameters are ignored
because the token encodes that information.
.RE
.RS 4
.RE
.IP "$s\->\fIget_name()\fR" 4
.IX Item "$s->get_name()"
Returns the name of the \f(CW\*(C`Scheduler\*(C'\fR object.
.ie n .IP "$s\->schedule_task( $command\fR, \f(CW$hashref )" 4
.el .IP "$s\->schedule_task( \f(CW$command\fR, \f(CW$hashref\fR )" 4
.IX Item "$s->schedule_task( $command, $hashref )"
Schedule the supplied \fIcommand\fR to be queued as described by the parameters in the supplied \fIhashref\fR.
The \fIhashref\fR has three optional parameters that specify the scheduling time:
.RS 4
.IP "\fIat_time\fR" 4
.IX Item "at_time"
This parameter specifies a specific time in epoch seconds after which the command will be queued.
.IP "\fIdelay_seconds\fR" 4
.IX Item "delay_seconds"
This parameter specifies a number of seconds to wait before scheduling the supplied command. If both
\&\fIat_time\fR and \fIdelay_seconds\fR are specified, \fIat_time\fR is used.
.IP "\fIattempts\fR" 4
.IX Item "attempts"
Specifies retry count for the task to be rescheduled if the task times out.
.RE
.RS 4
.RE
.ie n .IP "$s\->unschedule_task( $uuid )" 4
.el .IP "$s\->unschedule_task( \f(CW$uuid\fR )" 4
.IX Item "$s->unschedule_task( $uuid )"
Remove the task associated with the supplied \fIuuid\fR from the schedule, if
it has not been processed yet. Returns true on success.
.IP "$s\->\fIget_token()\fR" 4
.IX Item "$s->get_token()"
Returns an opaque string containing the information needed to construct a new
copy of this scheduler. Normally used when requesting a new scheduling at a later
point in time.
.ie n .IP "$s\->throw( $msg )" 4
.el .IP "$s\->throw( \f(CW$msg\fR )" 4
.IX Item "$s->throw( $msg )"
Log the supplied message and \f(CW\*(C`die\*(C'\fR.
.ie n .IP "$s\->warn( $msg )" 4
.el .IP "$s\->warn( \f(CW$msg\fR )" 4
.IX Item "$s->warn( $msg )"
Log the supplied message as a warning.
.ie n .IP "$s\->info( $msg )" 4
.el .IP "$s\->info( \f(CW$msg\fR )" 4
.IX Item "$s->info( $msg )"
Log the supplied message as an informational message.
.Sh "\s-1QUEUE\s0 \s-1INFORMATION\s0"
.IX Subsection "QUEUE INFORMATION"
.IP "$s\->\fIpeek_next_task()\fR" 4
.IX Item "$s->peek_next_task()"
Get a copy of the next Task to be scheduled or \f(CW\*(C`undef\*(C'\fR if the scheduler is
empty.
.Sp
Because of the nature of a task scheduler, there is no guarantee that this task
will remain unscheduled after the method call. That is one reason that a copy
is returned.
.ie n .IP "$s\->is_task_scheduled( $uuid )" 4
.el .IP "$s\->is_task_scheduled( \f(CW$uuid\fR )" 4
.IX Item "$s->is_task_scheduled( $uuid )"
Does the specified \fIuuid\fR reference a task to be scheduled?
.Sp
Because of the nature of a task scheduler, the particular \fIuuid\fR tested may
be scheduled for processsing immediately after the test. Therefore, a true answer
is not as useful as it might seem. A false answer does tell us that the item is
no longer waiting.
.ie n .IP "$s\->when_is_task_scheduled( $uuid )" 4
.el .IP "$s\->when_is_task_scheduled( \f(CW$uuid\fR )" 4
.IX Item "$s->when_is_task_scheduled( $uuid )"
Returns the time (in epoch seconds) when the Task referenced by \fIuuid\fR is
scheduled to be run or \f(CW\*(C`undef\*(C'\fR if \fIuuid\fR does not reference a valid task.
.Sp
Because of the nature of a task scheduler, the particular \fIuuid\fR tested may
be scheduled for processsing immediately after the test.
.IP "$s\->\fIhow_many_scheduled()\fR" 4
.IX Item "$s->how_many_scheduled()"
Gives a count at this particular point in time of the number of items currently
in the scheduler. Since an item may be removed and processed any time the
\&\f(CW\*(C`process_ready_tasks()\*(C'\fR method is called, this count may not be correct immediately
after the method returns.
.Sp
Most useful for the general case of telling if the queue is really full, or
mostly empty.
.IP "$s\->\fIseconds_until_next_task()\fR" 4
.IX Item "$s->seconds_until_next_task()"
Returns the number of seconds until the next task is ready to be processed, or
\&\f(CW\*(C`undef\*(C'\fR if there are no tasks to process.
.IP "$s\->\fIsnapshot_task_schedule()\fR" 4
.IX Item "$s->snapshot_task_schedule()"
Returns an array reference containing a series of hashes continaing the \fItime\fR
a task is scheduled to run and a copy of the \fItask\fR to run at that time. The
first item in the array is guaranteed to be the next task to run. The order of
the rest of the list is not guaranteed.
.Sp
This lack of guarantee allows the internal code to be implemented as either a sorted
array or a heap without requiring this method to fix up the array.
.Sh "\s-1SCHEDULING\s0"
.IX Subsection "SCHEDULING"
.ie n .IP "$s\->process_ready_tasks( $queue )" 4
.el .IP "$s\->process_ready_tasks( \f(CW$queue\fR )" 4
.IX Item "$s->process_ready_tasks( $queue )"
This method takes all of the Tasks that have reached (or passed) their schedule
time and passes them to the \f(CW\*(C`queue_task\*(C'\fR method of the supplied \fIqueue\fR object.
No object is removed from the scheduler unless \f(CW\*(C`queue_task\*(C'\fR runs without an
exception.
.Sp
In addition, the process of moving a Task from the scheduler to the queue replaces
it's \fIuuid\fR, so don't expect the \f(CW\*(C`uuid\*(C'\fR from the scheduler to have any relation
to the \f(CW\*(C`uuid\*(C'\fR of the same task in the \f(CW\*(C`TaskQueue\*(C'\fR.
.Sp
Returns the number of tasks processed, \f(CW0\fR if there were no tasks to process.
.Sh "\s-1CACHE\s0 \s-1SUPPORT\s0"
.IX Subsection "CACHE SUPPORT"
These methods should not be used directly, they exist to support the
\&\f(CW\*(C`Cpanel::CacheFile\*(C'\fR interface that persists the scheduler information to disk.
.ie n .IP "$q\->load_from_cache( $fh )" 4
.el .IP "$q\->load_from_cache( \f(CW$fh\fR )" 4
.IX Item "$q->load_from_cache( $fh )"
This method loads the scheduler information from the disk cache. It is called
by the \f(CW\*(C`Cpanel::CacheFile\*(C'\fR object owned by this object.
.Sp
The user of this class should never need to call this method.
.ie n .IP "$q\->save_to_cache( $fh )" 4
.el .IP "$q\->save_to_cache( \f(CW$fh\fR )" 4
.IX Item "$q->save_to_cache( $fh )"
This method saves the scheduler information to the disk cache. It is called by
the \f(CW\*(C`Cpanel::CacheFile\*(C'\fR object owned by this object.
.Sp
The user of this class should never need to call this method.
.SH "LOGGER OBJECT"
.IX Header "LOGGER OBJECT"
By default, the \f(CW\*(C`Scheduler\*(C'\fR uses \f(CW\*(C`die\*(C'\fR and \f(CW\*(C`warn\*(C'\fR for all messages during
runtime. However, it supports a mechanism that allows you to insert a
logging/reporting system in place by providing an object to do the logging for
us.
.PP
To provide a different method of logging/reporting, supply an object to do the
logging as follows when \f(CW\*(C`use\*(C'\fRing the module.
.PP
.Vb 1
\&   use Cpanel::TaskQueue::Scheduler ( '-logger' => $logger );
.Ve
.PP
The supplied object should supply (at least) 3 methods: \f(CW\*(C`throw\*(C'\fR, \f(CW\*(C`warn\*(C'\fR, and
\&\f(CW\*(C`info\*(C'\fR. When needed these methods will be called with the messages to be logged.
.PP
The \f(CW\*(C`throw\*(C'\fR method is expected to use \f(CW\*(C`die\*(C'\fR to exit the method. The others
are expected to continue. For example, an appropriate class for \f(CW\*(C`Log::Log4perl\*(C'\fR
might do something like the following:
.PP
.Vb 4
\&    package Policy::Log4perl;
\&    use strict;
\&    use warnings;
\&    use Log::Log4perl;
.Ve
.PP
.Vb 7
\&    sub new {
\&        my ($class) = shift;
\&        my $self = {
\&            logger => Log::Log4perl->get_logger( @_ )
\&        };
\&        return bless, $class;
\&    }
.Ve
.PP
.Vb 5
\&    sub throw {
\&        my $self = shift;
\&        $self->{logger}->error( @_ );
\&        die @_;
\&    }
.Ve
.PP
.Vb 4
\&    sub warn {
\&        my $self = shift;
\&        $self->{logger}->warn( @_ );
\&    }
.Ve
.PP
.Vb 4
\&    sub info {
\&        my $self = shift;
\&        $self->{logger}->info( @_ );
\&    }
.Ve
.PP
This would call the \f(CW\*(C`Log4perl\*(C'\fR code as errors or other messages result in
messages.
.PP
This only works once for a given program, so you can't reset the policy in
multiple modules and expect it to work.
.PP
In addition to setting a global logger, a new logger object can be supplied
when creating a specific \f(CW\*(C`Scheduler\*(C'\fR object.
.SH "DIAGNOSTICS"
.IX Header "DIAGNOSTICS"
The following messages can be reported by this module:
.ie n .IP """Invalid token.""" 4
.el .IP "\f(CWInvalid token.\fR" 4
.IX Item "Invalid token."
The \fItoken\fR parameter supplied to \fInew\fR is not of the correct form to be a \f(CW\*(C`Cpanel::TaskQueue::Scheduler\*(C'\fR token.
.ie n .IP """No caching directory supplied.""" 4
.el .IP "\f(CWNo caching directory supplied.\fR" 4
.IX Item "No caching directory supplied."
The required \fIcache_dir\fR parameter was missing when constructing the
\&\f(CW\*(C`TaskQueue::Scheduler\*(C'\fR object. The object was not created.
.ie n .IP """No queue name supplied.""" 4
.el .IP "\f(CWNo queue name supplied.\fR" 4
.IX Item "No queue name supplied."
The required \fIname\fR parameter was missing when constructing the \f(CW\*(C`TaskQueue::Scheduler\*(C'\fR
object. The object was not created.
.ie n .IP """Not a recognized TaskQueue Scheduler cache.""" 4
.el .IP "\f(CWNot a recognized TaskQueue Scheduler cache.\fR" 4
.IX Item "Not a recognized TaskQueue Scheduler cache."
.PD 0
.ie n .IP """Invalid version of TaskQueue Scheduler cache.""" 4
.el .IP "\f(CWInvalid version of TaskQueue Scheduler cache.\fR" 4
.IX Item "Invalid version of TaskQueue Scheduler cache."
.PD
Either the cache file is invalid or it is not a \f(CW\*(C`Cpanel::TaskQueue::Scheduler\*(C'\fR
cache file.
.ie n .IP """Cannot queue an empty command.""" 4
.el .IP "\f(CWCannot queue an empty command.\fR" 4
.IX Item "Cannot queue an empty command."
The command string supplied to \f(CW\*(C`schedule_task_*\*(C'\fR was either \f(CW\*(C`undef\*(C'\fR or empty.
.ie n .IP """Task with 0 retries not scheduled.""" 4
.el .IP "\f(CWTask with 0 retries not scheduled.\fR" 4
.IX Item "Task with 0 retries not scheduled."
The \f(CW\*(C`Task\*(C'\fR supplied to one of the \f(CW\*(C`schedule_task*\*(C'\fR methods has a remaining retry count of 0. The task
has been discarded. This is an informational message only.
.ie n .IP """No Task uuid argument passed to %s.""" 4
.el .IP "\f(CWNo Task uuid argument passed to %s.\fR" 4
.IX Item "No Task uuid argument passed to %s."
The specified method requires a \fIuuid\fR to specify which task to operate on.
None was supplied.
.ie n .IP """No valid queue supplied.""" 4
.el .IP "\f(CWNo valid queue supplied.\fR" 4
.IX Item "No valid queue supplied."
The \f(CW\*(C`process_ready_tasks\*(C'\fR methods requires a \f(CW\*(C`TaskQueue\*(C'\fR as a parameter. (Or, at least, an object with a \f(CW\*(C`queue_task\*(C'\fR method.)
.ie n .IP """Not an even number of arguments to the Cpanel::TaskQueue::Scheduler module""" 4
.el .IP "\f(CWNot an even number of arguments to the Cpanel::TaskQueue::Scheduler module\fR" 4
.IX Item "Not an even number of arguments to the Cpanel::TaskQueue::Scheduler module"
The parameters passed to the \f(CW\*(C`import\*(C'\fR method should be name/value pairs.
.ie n .IP """Policies already set elsewhere""" 4
.el .IP "\f(CWPolicies already set elsewhere\fR" 4
.IX Item "Policies already set elsewhere"
Some other file has already set the policies.
.ie n .IP """Unrecognized policy '%s'""" 4
.el .IP "\f(CWUnrecognized policy '%s'\fR" 4
.IX Item "Unrecognized policy '%s'"
The only policy supported by \f(CW\*(C`Cpane::TaskQueue::Scheduler\*(C'\fR is \fI\-logger\fR.
.SH "DEPENDENCIES"
.IX Header "DEPENDENCIES"
YAML::Syck
.PP
Cpanel::TaskQueue, Cpanel::TaskQueue::Task, Cpanel::CacheFile
.SH "INCOMPATIBILITIES"
.IX Header "INCOMPATIBILITIES"
None reported.
.SH "BUGS AND LIMITATIONS"
.IX Header "BUGS AND LIMITATIONS"
none reported.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
Cpanel::TaskQueue::Processor, Cpanel::TaskQueue::Task, and Cpanel::CacheFile
.SH "LICENCE AND COPYRIGHT"
.IX Header "LICENCE AND COPYRIGHT"
Copyright (c) 2009, CPanel. All rights reserved.
.PP
This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself. See perlartistic.
.SH "DISCLAIMER OF WARRANTY"
.IX Header "DISCLAIMER OF WARRANTY"
\&\s-1BECAUSE\s0 \s-1THIS\s0 \s-1SOFTWARE\s0 \s-1IS\s0 \s-1LICENSED\s0 \s-1FREE\s0 \s-1OF\s0 \s-1CHARGE\s0, \s-1THERE\s0 \s-1IS\s0 \s-1NO\s0 \s-1WARRANTY\s0
\&\s-1FOR\s0 \s-1THE\s0 \s-1SOFTWARE\s0, \s-1TO\s0 \s-1THE\s0 \s-1EXTENT\s0 \s-1PERMITTED\s0 \s-1BY\s0 \s-1APPLICABLE\s0 \s-1LAW\s0. \s-1EXCEPT\s0 \s-1WHEN\s0
\&\s-1OTHERWISE\s0 \s-1STATED\s0 \s-1IN\s0 \s-1WRITING\s0 \s-1THE\s0 \s-1COPYRIGHT\s0 \s-1HOLDERS\s0 \s-1AND/OR\s0 \s-1OTHER\s0 \s-1PARTIES\s0
\&\s-1PROVIDE\s0 \s-1THE\s0 \s-1SOFTWARE\s0 \*(L"\s-1AS\s0 \s-1IS\s0\*(R" \s-1WITHOUT\s0 \s-1WARRANTY\s0 \s-1OF\s0 \s-1ANY\s0 \s-1KIND\s0, \s-1EITHER\s0
\&\s-1EXPRESSED\s0 \s-1OR\s0 \s-1IMPLIED\s0, \s-1INCLUDING\s0, \s-1BUT\s0 \s-1NOT\s0 \s-1LIMITED\s0 \s-1TO\s0, \s-1THE\s0 \s-1IMPLIED\s0
\&\s-1WARRANTIES\s0 \s-1OF\s0 \s-1MERCHANTABILITY\s0 \s-1AND\s0 \s-1FITNESS\s0 \s-1FOR\s0 A \s-1PARTICULAR\s0 \s-1PURPOSE\s0. \s-1THE\s0
\&\s-1ENTIRE\s0 \s-1RISK\s0 \s-1AS\s0 \s-1TO\s0 \s-1THE\s0 \s-1QUALITY\s0 \s-1AND\s0 \s-1PERFORMANCE\s0 \s-1OF\s0 \s-1THE\s0 \s-1SOFTWARE\s0 \s-1IS\s0 \s-1WITH\s0
\&\s-1YOU\s0. \s-1SHOULD\s0 \s-1THE\s0 \s-1SOFTWARE\s0 \s-1PROVE\s0 \s-1DEFECTIVE\s0, \s-1YOU\s0 \s-1ASSUME\s0 \s-1THE\s0 \s-1COST\s0 \s-1OF\s0 \s-1ALL\s0
\&\s-1NECESSARY\s0 \s-1SERVICING\s0, \s-1REPAIR\s0, \s-1OR\s0 \s-1CORRECTION\s0.
.PP
\&\s-1IN\s0 \s-1NO\s0 \s-1EVENT\s0 \s-1UNLESS\s0 \s-1REQUIRED\s0 \s-1BY\s0 \s-1APPLICABLE\s0 \s-1LAW\s0 \s-1OR\s0 \s-1AGREED\s0 \s-1TO\s0 \s-1IN\s0 \s-1WRITING\s0
\&\s-1WILL\s0 \s-1ANY\s0 \s-1COPYRIGHT\s0 \s-1HOLDER\s0, \s-1OR\s0 \s-1ANY\s0 \s-1OTHER\s0 \s-1PARTY\s0 \s-1WHO\s0 \s-1MAY\s0 \s-1MODIFY\s0 \s-1AND/OR\s0
\&\s-1REDISTRIBUTE\s0 \s-1THE\s0 \s-1SOFTWARE\s0 \s-1AS\s0 \s-1PERMITTED\s0 \s-1BY\s0 \s-1THE\s0 \s-1ABOVE\s0 \s-1LICENCE\s0, \s-1BE\s0
\&\s-1LIABLE\s0 \s-1TO\s0 \s-1YOU\s0 \s-1FOR\s0 \s-1DAMAGES\s0, \s-1INCLUDING\s0 \s-1ANY\s0 \s-1GENERAL\s0, \s-1SPECIAL\s0, \s-1INCIDENTAL\s0,
\&\s-1OR\s0 \s-1CONSEQUENTIAL\s0 \s-1DAMAGES\s0 \s-1ARISING\s0 \s-1OUT\s0 \s-1OF\s0 \s-1THE\s0 \s-1USE\s0 \s-1OR\s0 \s-1INABILITY\s0 \s-1TO\s0 \s-1USE\s0
\&\s-1THE\s0 \s-1SOFTWARE\s0 (\s-1INCLUDING\s0 \s-1BUT\s0 \s-1NOT\s0 \s-1LIMITED\s0 \s-1TO\s0 \s-1LOSS\s0 \s-1OF\s0 \s-1DATA\s0 \s-1OR\s0 \s-1DATA\s0 \s-1BEING\s0
\&\s-1RENDERED\s0 \s-1INACCURATE\s0 \s-1OR\s0 \s-1LOSSES\s0 \s-1SUSTAINED\s0 \s-1BY\s0 \s-1YOU\s0 \s-1OR\s0 \s-1THIRD\s0 \s-1PARTIES\s0 \s-1OR\s0 A
\&\s-1FAILURE\s0 \s-1OF\s0 \s-1THE\s0 \s-1SOFTWARE\s0 \s-1TO\s0 \s-1OPERATE\s0 \s-1WITH\s0 \s-1ANY\s0 \s-1OTHER\s0 \s-1SOFTWARE\s0), \s-1EVEN\s0 \s-1IF\s0
\&\s-1SUCH\s0 \s-1HOLDER\s0 \s-1OR\s0 \s-1OTHER\s0 \s-1PARTY\s0 \s-1HAS\s0 \s-1BEEN\s0 \s-1ADVISED\s0 \s-1OF\s0 \s-1THE\s0 \s-1POSSIBILITY\s0 \s-1OF\s0
\&\s-1SUCH\s0 \s-1DAMAGES\s0.