3 # Copyright 2016 RIFT.IO Inc
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
23 class ParameterValueError(Exception):
27 class ParameterValuePool(object):
28 def __init__(self
, log
, name
, value_iter
):
32 self
._used
_pool
_values
= []
33 self
._available
_pool
_values
= list(value_iter
)
35 self
._backing
_filepath
= os
.path
.join(
36 os
.environ
["RIFT_ARTIFACTS"],
41 self
._read
_used
_pool
_values
()
43 def _save_used_pool_values(self
):
44 dir_path
= os
.path
.dirname(self
._backing
_filepath
)
45 if not os
.path
.exists(dir_path
):
47 os
.makedirs(dir_path
, exist_ok
=True)
49 self
._log
.error("Could not create directory for save used pool: %s", str(e
))
52 with
open(self
._backing
_filepath
, "wb") as hdl
:
53 pickle
.dump(self
._used
_pool
_values
, hdl
)
56 "Could not open the parameter value pool file: %s",
58 except pickle
.PickleError
as e
:
60 "Could not pickle the used parameter value pool: %s",
63 def _read_used_pool_values(self
):
65 with
open(self
._backing
_filepath
, 'rb') as hdl
:
66 self
._used
_pool
_values
= pickle
.load(hdl
)
68 except (OSError, EOFError):
69 self
._log
.warning("Could not read from backing file: %s",
70 self
._backing
_filepath
)
71 self
._used
_pool
_values
= []
73 except pickle
.PickleError
as e
:
74 self
._log
.warning("Could not unpickle the used parameter value pool from %s: %s",
75 self
._backing
_filepath
, str(e
))
76 self
._used
_pool
_values
= []
78 for value
in self
._used
_pool
_values
:
79 self
._available
_pool
_values
.remove(value
)
81 def get_next_unused_value(self
):
82 if len(self
._available
_pool
_values
) == 0:
83 raise ParameterValueError("Not more parameter values to to allocate")
85 next_value
= self
._available
_pool
_values
[0]
86 self
._log
.debug("Got next value for parameter pool %s: %s", self
._name
, next_value
)
90 def add_used_value(self
, value
):
93 if len(self
._available
_pool
_values
) == 0:
94 raise ParameterValueError("Not more parameter values to to allocate")
96 if value
in self
._used
_pool
_values
:
97 raise ParameterValueError(
98 "Primitive value of {} was already used for pool name: {}".format(
104 if value
!= self
._available
_pool
_values
[0]:
105 raise ParameterValueError("Parameter value not the next in the available list: %s", value
)
107 self
._available
_pool
_values
.pop(0)
108 self
._used
_pool
_values
.append(value
)
109 self
._save
_used
_pool
_values
()
111 def remove_used_value(self
, value
):
112 if value
not in self
._used
_pool
_values
:
113 self
._log
.warning("Primitive value of %s was never allocated for pool name: %s",
118 self
._used
_pool
_values
.remove(value
)
119 self
._available
_pool
_values
.insert(0, value
)
120 self
._save
_used
_pool
_values
()
123 if __name__
== "__main__":
125 logging
.basicConfig(level
=logging
.DEBUG
)
126 logger
= logging
.getLogger("config_value_pool.py")
127 name
= str(uuid
.uuid4())
128 param_pool
= ParameterValuePool(logger
, name
, range(1000, 2000))
130 a
= param_pool
.get_next_unused_value()
133 param_pool
.add_used_value(a
)
135 a
= param_pool
.get_next_unused_value()
137 param_pool
.add_used_value(a
)
139 param_pool
= ParameterValuePool(logger
, name
, range(1000, 2000))
140 a
= param_pool
.get_next_unused_value()
144 param_pool
.add_used_value(1004)
145 except ParameterValueError
:
150 a
= param_pool
.get_next_unused_value()
152 param_pool
.add_used_value(1002)
154 param_pool
= ParameterValuePool(logger
, name
, range(1005, 2000))