1.1 --- a/docs/wiki/Preferences Tue Feb 09 12:19:13 2016 +0100
1.2 +++ b/docs/wiki/Preferences Tue Feb 09 14:17:52 2016 +0100
1.3 @@ -110,33 +110,6 @@
1.4 .. all event details
1.5 }}}
1.6
1.7 -=== confirmation_function ===
1.8 -
1.9 - Default:: (none)
1.10 - Alternatives:: (see below)
1.11 -
1.12 -Indicates the confirmation functions used by [[../Resources|resources]] to be
1.13 -invoked when an event is scheduled. Such functions support certain scheduling
1.14 -functions that require a record of scheduling activity.
1.15 -
1.16 -The `imiptools.handlers.scheduling` module contains the built-in confirmation
1.17 -functions which include the following:
1.18 -
1.19 -{{{#!table
1.20 -`add_to_quota` ||<rowspan="2"> add the details of an event to quota
1.21 - .. records for the indicated quota group
1.22 -==
1.23 -`add_to_quota` ''`quota-group`''
1.24 -==
1.25 -`add_to_quota_freebusy` ||<rowspan="2"> add the details of an event to
1.26 - .. free/busy records stored by the indicated quota
1.27 - .. group
1.28 -==
1.29 -`add_to_quota_freebusy` ''`quota-group`''
1.30 -}}}
1.31 -
1.32 -See also `retraction_function` and `scheduling_function`.
1.33 -
1.34 === event_refreshing ===
1.35
1.36 Default:: `never`
1.37 @@ -294,33 +267,6 @@
1.38 minute values that correspond to permitted values in this participant's own
1.39 time zone.
1.40
1.41 -=== retraction_function ===
1.42 -
1.43 - Default:: (none)
1.44 - Alternatives:: (see below)
1.45 -
1.46 -Indicates the retraction functions used by [[../Resources|resources]] to be
1.47 -invoked when an event is cancelled. Such functions support certain scheduling
1.48 -functions that require a record of scheduling activity.
1.49 -
1.50 -The `imiptools.handlers.scheduling` module contains the built-in retraction
1.51 -functions which include the following:
1.52 -
1.53 -{{{#!table
1.54 -`remove_from_quota` ||<rowspan="2"> remove the details of an event from
1.55 - .. quota records for the indicated quota group
1.56 -==
1.57 -`remove_from_quota` ''`quota-group`''
1.58 -==
1.59 -`remove_from_quota_freebusy` ||<rowspan="2"> remove the details of an event
1.60 - .. from free/busy records stored by the
1.61 - .. indicated quota group
1.62 -==
1.63 -`remove_from_quota_freebusy` ''`quota-group`''
1.64 -}}}
1.65 -
1.66 -See also `confirmation_function` and `scheduling_function`.
1.67 -
1.68 === scheduling_function ===
1.69
1.70 Default:: `schedule_in_freebusy`
1.71 @@ -373,5 +319,3 @@
1.72
1.73 The scheduling mechanism can be extended by implementing additional scheduling
1.74 functions or by extending the handler framework directly.
1.75 -
1.76 -See also `confirmation_function` and `retraction_function`.
2.1 --- a/docs/wiki/Resources Tue Feb 09 12:19:13 2016 +0100
2.2 +++ b/docs/wiki/Resources Tue Feb 09 14:17:52 2016 +0100
2.3 @@ -17,92 +17,6 @@
2.4
2.5 <<TableOfContents(2,4)>>
2.6
2.7 -== Confirmation and Retraction Functions ==
2.8 -
2.9 -Confirmation and retraction functions are used to update other resources and
2.10 -systems with the details of scheduled events. When an event is successfully
2.11 -scheduled (according to the scheduling functions), all registered confirmation
2.12 -functions are invoked to perform such notifications. Similarly, when an event
2.13 -is cancelled, all registered retraction functions are invoked to inform other
2.14 -components of the removal of the event from schedules.
2.15 -
2.16 -The [[../Preferences#confirmation_function|confirmation_function]] and
2.17 -[[../Preferences#retraction_function|retraction_function]] settings indicate
2.18 -the behaviour of a resource when such circumstances arise. By themselves,
2.19 -these settings do no more than keep a kind of journal of scheduling events,
2.20 -but certain scheduling functions may build upon such journals to make
2.21 -scheduling decisions. For example:
2.22 -
2.23 -{{{{#!table
2.24 -'''All Functions''' || '''Decision Process'''
2.25 -==
2.26 -<style="vertical-align: top;">
2.27 -
2.28 -Scheduling functions:
2.29 -
2.30 -{{{
2.31 -check_quota
2.32 -}}}
2.33 -
2.34 -Confirmation functions:
2.35 -
2.36 -{{{
2.37 -add_to_quota
2.38 -}}}
2.39 -
2.40 -Retraction functions:
2.41 -
2.42 -{{{
2.43 -remove_from_quota
2.44 -}}}
2.45 -
2.46 -||
2.47 -
2.48 -{{{#!graphviz
2.49 -//format=svg
2.50 -//transform=notugly
2.51 -digraph scheduling_decisions {
2.52 - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"];
2.53 - edge [tooltip="Scheduling decisions"];
2.54 -
2.55 - subgraph {
2.56 - rank=same;
2.57 - mail [label="Incoming mail\nfrom vincent.vole@example.com",shape=folder,style=filled,fillcolor=cyan];
2.58 - cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan];
2.59 - }
2.60 -
2.61 - subgraph {
2.62 - rank=same;
2.63 - check_quota [label="Is allowed by quota?",shape=ellipse,style=filled,fillcolor=gold];
2.64 - quota [label="Quota for resource",shape=folder];
2.65 - quota_for_vole [label="...applying to\nvincent.vole@example.com",shape=folder];
2.66 - }
2.67 -
2.68 - schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold];
2.69 -
2.70 - subgraph {
2.71 - rank=same;
2.72 - accept [label="Accept",shape=folder,style=filled,fillcolor=cyan];
2.73 - decline [label="Decline",shape=folder,style=filled,fillcolor=cyan];
2.74 - }
2.75 -
2.76 - add_to_quota [label="Add to quota",shape=ellipse,style=filled,fillcolor=darkorange];
2.77 - remove_from_quota [label="Remove from quota",shape=ellipse,style=filled,fillcolor=darkorange];
2.78 -
2.79 - mail -> check_quota -> schedule -> accept;
2.80 - check_quota -> decline [style=dashed];
2.81 - schedule -> add_to_quota -> quota;
2.82 - quota -> quota_for_vole -> check_quota;
2.83 -
2.84 - cancel -> remove_from_quota -> quota;
2.85 -}
2.86 -}}}
2.87 -
2.88 -}}}}
2.89 -
2.90 -See the [[#Quota_Controls|quota controls]] documentation for more information
2.91 -about applying quotas to resources.
2.92 -
2.93 == Scheduling Functions ==
2.94
2.95 The [[../Preferences#scheduling_function|scheduling_function]] setting
2.96 @@ -441,10 +355,6 @@
2.97
2.98 === Quota Controls ===
2.99
2.100 -The [[#Confirmation_and_Retraction_Functions|confirmation and retraction functions]]
2.101 -section provides an example of applying quotas to event participants. However,
2.102 -this section describes the operation of the quota system in more detail.
2.103 -
2.104 In contrast to each user's stored information which consolidates information
2.105 related to that user's own schedule, the quota system consolidates information
2.106 related to the schedules of one or more resources, thus enabling observations
2.107 @@ -515,9 +425,60 @@
2.108
2.109 The trivial case of applying quotas is to give a resource its own quota. This
2.110 is achieved by not specifying any arguments to the `check_quota` scheduling
2.111 -function or to the `add_to_quota` and `remove_from_quota` functions. See the
2.112 -[[#Confirmation_and_Retraction_Functions|confirmation and retraction functions]]
2.113 -section for an example of this.
2.114 +function or to the `add_to_quota` and `remove_from_quota` functions.
2.115 +
2.116 +{{{{#!table
2.117 +'''Scheduling Functions''' || '''Decision Process'''
2.118 +==
2.119 +<style="vertical-align: top;">
2.120 +
2.121 +{{{
2.122 +check_quota
2.123 +}}}
2.124 +
2.125 +||
2.126 +
2.127 +{{{#!graphviz
2.128 +//format=svg
2.129 +//transform=notugly
2.130 +digraph scheduling_decisions {
2.131 + node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"];
2.132 + edge [tooltip="Scheduling decisions"];
2.133 +
2.134 + subgraph {
2.135 + rank=same;
2.136 + mail [label="Incoming mail\nfrom vincent.vole@example.com",shape=folder,style=filled,fillcolor=cyan];
2.137 + cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan];
2.138 + }
2.139 +
2.140 + subgraph {
2.141 + rank=same;
2.142 + check_quota [label="Is allowed by quota?",shape=ellipse,style=filled,fillcolor=gold];
2.143 + quota [label="Quota for resource",shape=folder];
2.144 + quota_for_vole [label="...applying to\nvincent.vole@example.com",shape=folder];
2.145 + }
2.146 +
2.147 + schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold];
2.148 +
2.149 + subgraph {
2.150 + rank=same;
2.151 + accept [label="Accept",shape=folder,style=filled,fillcolor=cyan];
2.152 + decline [label="Decline",shape=folder,style=filled,fillcolor=cyan];
2.153 + }
2.154 +
2.155 + add_to_quota [label="Add to quota",shape=ellipse,style=filled,fillcolor=darkorange];
2.156 + remove_from_quota [label="Remove from quota",shape=ellipse,style=filled,fillcolor=darkorange];
2.157 +
2.158 + mail -> check_quota -> schedule -> accept;
2.159 + check_quota -> decline [style=dashed];
2.160 + schedule -> add_to_quota -> quota;
2.161 + quota -> quota_for_vole -> check_quota;
2.162 +
2.163 + cancel -> remove_from_quota -> quota;
2.164 +}
2.165 +}}}
2.166 +
2.167 +}}}}
2.168
2.169 ==== Common Resource Quotas ====
2.170
2.171 @@ -526,28 +487,14 @@
2.172 function invocations to pool their knowledge about their schedules.
2.173
2.174 {{{{#!table
2.175 -'''All Functions''' || '''Decision Process'''
2.176 +'''Scheduling Functions''' || '''Decision Process'''
2.177 ==
2.178 <style="vertical-align: top;">
2.179
2.180 -Scheduling functions:
2.181 -
2.182 {{{
2.183 check_quota cars
2.184 }}}
2.185
2.186 -Confirmation functions:
2.187 -
2.188 -{{{
2.189 -add_to_quota cars
2.190 -}}}
2.191 -
2.192 -Retraction functions:
2.193 -
2.194 -{{{
2.195 -remove_from_quota cars
2.196 -}}}
2.197 -
2.198 ||
2.199
2.200 {{{#!graphviz
2.201 @@ -611,28 +558,14 @@
2.202 scheduling decisions and are employed as follows:
2.203
2.204 {{{{#!table
2.205 -'''All Functions''' || '''Decision Process'''
2.206 +'''Scheduling Functions''' || '''Decision Process'''
2.207 ==
2.208 <style="vertical-align: top;">
2.209
2.210 -Scheduling functions:
2.211 -
2.212 {{{
2.213 schedule_within_quota cars
2.214 }}}
2.215
2.216 -Confirmation functions:
2.217 -
2.218 -{{{
2.219 -add_to_quota_freebusy cars
2.220 -}}}
2.221 -
2.222 -Retraction functions:
2.223 -
2.224 -{{{
2.225 -remove_from_quota_freebusy cars
2.226 -}}}
2.227 -
2.228 ||
2.229
2.230 {{{#!graphviz
3.1 --- a/imiptools/handlers/resource.py Tue Feb 09 12:19:13 2016 +0100
3.2 +++ b/imiptools/handlers/resource.py Tue Feb 09 14:17:52 2016 +0100
3.3 @@ -176,6 +176,13 @@
3.4
3.5 # Scheduling details.
3.6
3.7 + def get_scheduling_functions(self):
3.8 +
3.9 + "Return the scheduling functions for the resource."
3.10 +
3.11 + return self.get_preferences().get("scheduling_function",
3.12 + "schedule_in_freebusy").split("\n")
3.13 +
3.14 def schedule(self):
3.15
3.16 """
3.17 @@ -185,39 +192,25 @@
3.18 invalid requests.
3.19 """
3.20
3.21 - # Obtain a list of scheduling functions.
3.22 -
3.23 - functions = self.get_preferences().get("scheduling_function",
3.24 - "schedule_in_freebusy").split("\n")
3.25 -
3.26 - return apply_scheduling_functions(functions, self)
3.27 + return apply_scheduling_functions(self)
3.28
3.29 def confirm_scheduling(self):
3.30
3.31 "Confirm that this event has been scheduled."
3.32
3.33 - functions = self.get_preferences().get("confirmation_function")
3.34 -
3.35 - if functions:
3.36 - confirm_scheduling(functions.split("\n"), self)
3.37 + confirm_scheduling(self)
3.38
3.39 def finish_scheduling(self):
3.40
3.41 "Finish the scheduling, unlocking resources where appropriate."
3.42
3.43 - functions = self.get_preferences().get("scheduling_function",
3.44 - "schedule_in_freebusy").split("\n")
3.45 -
3.46 - finish_scheduling(functions, self)
3.47 + finish_scheduling(self)
3.48
3.49 def retract_scheduling(self):
3.50
3.51 "Retract this event from scheduling records."
3.52
3.53 - functions = self.get_preferences().get("retraction_function")
3.54 -
3.55 - if functions:
3.56 - retract_scheduling(functions.split("\n"), self)
3.57 + retract_scheduling(self)
3.58
3.59 class Event(ResourceHandler):
3.60
4.1 --- a/imiptools/handlers/scheduling/__init__.py Tue Feb 09 12:19:13 2016 +0100
4.2 +++ b/imiptools/handlers/scheduling/__init__.py Tue Feb 09 14:17:52 2016 +0100
4.3 @@ -28,21 +28,21 @@
4.4
4.5 # Function application/invocation.
4.6
4.7 -def apply_scheduling_functions(functions, handler):
4.8 +def apply_scheduling_functions(handler):
4.9
4.10 """
4.11 - Apply the given scheduling 'functions' in the current object of the given
4.12 + Apply the scheduling functions for the current object of the given
4.13 'handler'. This function starts a transaction that should be finalised using
4.14 the 'finish_scheduling' function.
4.15 """
4.16
4.17 # First, lock the resources to be used.
4.18
4.19 - start_scheduling(functions, handler)
4.20 + start_scheduling(handler)
4.21
4.22 # Obtain the actual scheduling functions with arguments.
4.23
4.24 - schedulers = get_function_calls(functions, scheduling_functions)
4.25 + schedulers = get_function_calls(handler.get_scheduling_functions(), scheduling_functions)
4.26
4.27 # Then, invoke the scheduling functions.
4.28
4.29 @@ -74,41 +74,40 @@
4.30
4.31 return response
4.32
4.33 -def confirm_scheduling(functions, handler):
4.34 +def confirm_scheduling(handler):
4.35
4.36 """
4.37 - Confirm scheduling using the given listener 'functions' for the current
4.38 - object of the given 'handler'. This function continues a transaction that
4.39 - should be finalised using the 'finish_scheduling' function.
4.40 + Confirm scheduling using confirmation functions for the current object of
4.41 + the given 'handler'. This function continues a transaction that should be
4.42 + finalised using the 'finish_scheduling' function.
4.43 """
4.44
4.45 - # Obtain the actual listener functions with arguments.
4.46 + # Obtain the actual confirmation functions with arguments.
4.47
4.48 - functions = get_function_calls(functions, confirmation_functions)
4.49 + functions = get_function_calls(handler.get_scheduling_functions(), confirmation_functions)
4.50 apply_functions(functions, handler)
4.51
4.52 -def retract_scheduling(functions, handler):
4.53 +def retract_scheduling(handler):
4.54
4.55 """
4.56 - Retract scheduling using the given listener 'functions' for the current
4.57 - object of the given 'handler'. This function is a complete transaction in
4.58 - itself.
4.59 + Retract scheduling using retraction functions for the current object of the
4.60 + given 'handler'. This function is a complete transaction in itself.
4.61 """
4.62
4.63 # First, lock the resources to be used.
4.64
4.65 - start_scheduling(functions, handler)
4.66 + start_scheduling(handler)
4.67
4.68 - # Obtain the actual listener functions with arguments.
4.69 + # Obtain the actual retraction functions with arguments.
4.70
4.71 - retractors = get_function_calls(functions, retraction_functions)
4.72 - apply_functions(retractors, handler)
4.73 + functions = get_function_calls(handler.get_scheduling_functions(), retraction_functions)
4.74 + apply_functions(functions, handler)
4.75
4.76 # Finally, unlock the resources.
4.77
4.78 - finish_scheduling(functions, handler)
4.79 + finish_scheduling(handler)
4.80
4.81 -def start_scheduling(functions, handler):
4.82 +def start_scheduling(handler):
4.83
4.84 """
4.85 Apply locking functions for the given scheduling 'functions' and for the
4.86 @@ -117,10 +116,10 @@
4.87
4.88 # Obtain functions to lock resources.
4.89
4.90 - locks = get_function_calls(functions, locking_functions)
4.91 - apply_functions(locks, handler)
4.92 + functions = get_function_calls(handler.get_scheduling_functions(), locking_functions)
4.93 + apply_functions(functions, handler)
4.94
4.95 -def finish_scheduling(functions, handler):
4.96 +def finish_scheduling(handler):
4.97
4.98 """
4.99 Finish scheduling using the given scheduling 'functions' for the current
4.100 @@ -129,24 +128,28 @@
4.101
4.102 # Obtain functions to unlock resources.
4.103
4.104 - locks = get_function_calls(functions, unlocking_functions)
4.105 - apply_functions(locks, handler)
4.106 + functions = get_function_calls(handler.get_scheduling_functions(), unlocking_functions)
4.107 + apply_functions(functions, handler)
4.108
4.109 def apply_functions(functions, handler):
4.110
4.111 """
4.112 Apply the given notification 'functions' for the current object of the given
4.113 - 'handler'.
4.114 + 'handler'. Where functions are provided more than once, they will be called
4.115 + only once for each distinct set of arguments.
4.116 """
4.117
4.118 + applied = set()
4.119 +
4.120 for fn, args in functions:
4.121
4.122 # NOTE: Should signal an error for incorrectly configured resources.
4.123
4.124 - if not fn:
4.125 + if not fn or (fn, args) in applied:
4.126 continue
4.127
4.128 fn(handler, args)
4.129 + applied.add((fn, args))
4.130
4.131 # Function lookup.
4.132
4.133 @@ -169,7 +172,7 @@
4.134
4.135 for line in lines:
4.136 parts = parse_line(line)
4.137 - functions.append((registry.get(parts[0]), parts[1:]))
4.138 + functions.append((registry.get(parts[0]), tuple(parts[1:])))
4.139
4.140 return functions
4.141
5.1 --- a/imiptools/handlers/scheduling/quota.py Tue Feb 09 12:19:13 2016 +0100
5.2 +++ b/imiptools/handlers/scheduling/quota.py Tue Feb 09 14:17:52 2016 +0100
5.3 @@ -340,28 +340,24 @@
5.4
5.5 locking_functions = {
5.6 "check_quota" : lock_journal,
5.7 - "remove_from_quota" : lock_journal,
5.8 - "remove_from_quota_freebusy" : lock_journal,
5.9 "schedule_across_quota" : lock_journal,
5.10 }
5.11
5.12 unlocking_functions = {
5.13 "check_quota" : unlock_journal,
5.14 - "remove_from_quota" : unlock_journal,
5.15 - "remove_from_quota_freebusy" : unlock_journal,
5.16 "schedule_across_quota" : unlock_journal,
5.17 }
5.18
5.19 # Registries of listener functions.
5.20
5.21 confirmation_functions = {
5.22 - "add_to_quota" : add_to_quota,
5.23 - "add_to_quota_freebusy" : add_to_quota_freebusy,
5.24 + "check_quota" : add_to_quota,
5.25 + "schedule_across_quota" : add_to_quota_freebusy,
5.26 }
5.27
5.28 retraction_functions = {
5.29 - "remove_from_quota" : remove_from_quota,
5.30 - "remove_from_quota_freebusy" : remove_from_quota_freebusy,
5.31 + "check_quota" : remove_from_quota,
5.32 + "schedule_across_quota" : remove_from_quota_freebusy,
5.33 }
5.34
5.35 # vim: tabstop=4 expandtab shiftwidth=4
6.1 --- a/tests/test_resource_invitation_constraints_quota.sh Tue Feb 09 12:19:13 2016 +0100
6.2 +++ b/tests/test_resource_invitation_constraints_quota.sh Tue Feb 09 14:17:52 2016 +0100
6.3 @@ -18,12 +18,6 @@
6.4 schedule_in_freebusy
6.5 check_quota $QUOTA
6.6 EOF
6.7 -cat > "$PREFS/$USER1/confirmation_function" <<EOF
6.8 -add_to_quota $QUOTA
6.9 -EOF
6.10 -cat > "$PREFS/$USER1/retraction_function" <<EOF
6.11 -remove_from_quota $QUOTA
6.12 -EOF
6.13
6.14 mkdir -p "$PREFS/$USER2"
6.15 echo 'Europe/Oslo' > "$PREFS/$USER2/TZID"
6.16 @@ -32,12 +26,6 @@
6.17 schedule_in_freebusy
6.18 check_quota $QUOTA
6.19 EOF
6.20 -cat > "$PREFS/$USER2/confirmation_function" <<EOF
6.21 -add_to_quota $QUOTA
6.22 -EOF
6.23 -cat > "$PREFS/$USER2/retraction_function" <<EOF
6.24 -remove_from_quota $QUOTA
6.25 -EOF
6.26
6.27 mkdir -p "$JOURNAL/$QUOTA"
6.28 echo '* PT1H' > "$JOURNAL/$QUOTA/limits"
6.29 @@ -191,28 +179,12 @@
6.30 schedule_across_quota $QUOTA
6.31 check_quota $QUOTA
6.32 EOF
6.33 -cat > "$PREFS/$USER1/confirmation_function" <<EOF
6.34 -add_to_quota_freebusy $QUOTA
6.35 -add_to_quota $QUOTA
6.36 -EOF
6.37 -cat > "$PREFS/$USER1/retraction_function" <<EOF
6.38 -remove_from_quota_freebusy $QUOTA
6.39 -remove_from_quota $QUOTA
6.40 -EOF
6.41
6.42 cat > "$PREFS/$USER2/scheduling_function" <<EOF
6.43 schedule_in_freebusy
6.44 schedule_across_quota $QUOTA
6.45 check_quota $QUOTA
6.46 EOF
6.47 -cat > "$PREFS/$USER2/confirmation_function" <<EOF
6.48 -add_to_quota_freebusy $QUOTA
6.49 -add_to_quota $QUOTA
6.50 -EOF
6.51 -cat > "$PREFS/$USER2/retraction_function" <<EOF
6.52 -remove_from_quota_freebusy $QUOTA
6.53 -remove_from_quota $QUOTA
6.54 -EOF
6.55
6.56 # Remind the resource about the second event.
6.57
7.1 --- a/tests/test_resource_invitation_constraints_quota_recurring.sh Tue Feb 09 12:19:13 2016 +0100
7.2 +++ b/tests/test_resource_invitation_constraints_quota_recurring.sh Tue Feb 09 14:17:52 2016 +0100
7.3 @@ -16,12 +16,6 @@
7.4 schedule_in_freebusy
7.5 check_quota
7.6 EOF
7.7 -cat > "$PREFS/$USER/confirmation_function" <<EOF
7.8 -add_to_quota
7.9 -EOF
7.10 -cat > "$PREFS/$USER/retraction_function" <<EOF
7.11 -remove_from_quota
7.12 -EOF
7.13
7.14 # Employ a user-specific quota (no argument with the functions above).
7.15
8.1 --- a/tests/test_resource_invitation_constraints_quota_recurring_limits.sh Tue Feb 09 12:19:13 2016 +0100
8.2 +++ b/tests/test_resource_invitation_constraints_quota_recurring_limits.sh Tue Feb 09 14:17:52 2016 +0100
8.3 @@ -23,12 +23,6 @@
8.4 schedule_in_freebusy
8.5 check_quota $QUOTA
8.6 EOF
8.7 -cat > "$PREFS/$USER1/confirmation_function" <<EOF
8.8 -add_to_quota $QUOTA
8.9 -EOF
8.10 -cat > "$PREFS/$USER1/retraction_function" <<EOF
8.11 -remove_from_quota $QUOTA
8.12 -EOF
8.13
8.14 mkdir -p "$PREFS/$USER2"
8.15 echo 'Europe/Oslo' > "$PREFS/$USER2/TZID"
8.16 @@ -37,12 +31,6 @@
8.17 schedule_in_freebusy
8.18 check_quota $QUOTA
8.19 EOF
8.20 -cat > "$PREFS/$USER2/confirmation_function" <<EOF
8.21 -add_to_quota $QUOTA
8.22 -EOF
8.23 -cat > "$PREFS/$USER2/retraction_function" <<EOF
8.24 -remove_from_quota $QUOTA
8.25 -EOF
8.26
8.27 mkdir -p "$JOURNAL/$QUOTA"
8.28 cat > "$JOURNAL/$QUOTA/limits" <<EOF