Fixing OMF API not being remove on delete from _apis dict in omf_api_factory
[nepi.git] / src / nepi / resources / omf / omf_api_factory.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
5 #    This program is free software: you can redistribute it and/or modify
6 #    it under the terms of the GNU General Public License as published by
7 #    the Free Software Foundation, either version 3 of the License, or
8 #    (at your option) any later version.
9 #
10 #    This program is distributed in the hope that it will be useful,
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #    GNU General Public License for more details.
14 #
15 #    You should have received a copy of the GNU General Public License
16 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19 #         Julien Tribino <julien.tribino@inria.fr>
20
21
22 import time
23 import hashlib
24 import threading
25
26 from nepi.resources.omf.omf5_api import OMF5API
27 from nepi.resources.omf.omf6_api import OMF6API
28
29 class OMFAPIFactory(object):
30     """ 
31     .. note::
32
33         It allows the different RM to use the same xmpp client if they use 
34         the same credentials.  For the moment, it is focused on XMPP.
35
36     """
37     # use lock to avoid concurrent access to the Api list at the same times by 2 
38     # different threads
39     lock = threading.Lock()
40     _apis = dict()
41
42     @classmethod 
43     def get_api(cls, version, server, user, port, password, exp_id = None):
44         """ Get an OMF Api
45
46         :param version: OMF Version. Either 5 or 6
47         :type version: str
48         :param server: Xmpp Server Adress
49         :type server: str
50         :param user: Xmpp User
51         :type user: str
52         :param port: Xmpp Port (Default : 5222)
53         :type port: str
54         :param password: Xmpp Password
55         :type password: str
56         :param exp_id: Id of the experiment
57         :type exp_id: str
58
59         """
60         if version and user and server and port and password:
61             key = cls._make_key(version, server, user, port, password, exp_id)
62             cls.lock.acquire()
63             if key in cls._apis:
64                 #print "Api Counter : " + str(cls._apis[key]['cnt'])
65                 cls._apis[key]['cnt'] += 1
66                 cls.lock.release()
67                 return cls._apis[key]['api']
68             else :
69                 omf_api = cls.create_api(version, server, user, port, password, exp_id)
70                 cls.lock.release()
71                 return omf_api
72         return None
73
74     @classmethod 
75     def create_api(cls, version, server, user, port, password, exp_id):
76         """ Create an OMF API if this one doesn't exist yet with this credentials
77
78         :param version: OMF Version. Either 5 or 6
79         :type version: str
80         :param server: Xmpp Server Adress
81         :type server: str
82         :param user: Xmpp User
83         :type user: str
84         :param port: Xmpp Port (Default : 5222)
85         :type port: str
86         :param password: Xmpp Password
87         :type password: str
88         :param exp_id: Id of the experiment
89         :type exp_id: str
90
91         """
92         key = cls._make_key(version, server, user, port, password, exp_id)
93         if version == "5":
94             omf_api = OMF5API(server, user, port, password, exp_id = exp_id)
95         else :
96             omf_api = OMF6API(server, user = user, port = port, password = password, exp_id = exp_id)
97         cls._apis[key] = {}
98         cls._apis[key]['api'] = omf_api
99         cls._apis[key]['cnt'] = 1
100         return omf_api
101
102     @classmethod 
103     def release_api(cls, version, server, user, port, password, exp_id = None):
104         """ Release an OMF API with this credentials
105
106         :param version: OMF Version. Either 5 or 6
107         :type version: str
108         :param server: Xmpp Server Adress
109         :type server: str
110         :param user: Xmpp User
111         :type user: str
112         :param port: Xmpp Port (Default : 5222)
113         :type port: str
114         :param password: Xmpp Password
115         :type password: str
116         :param exp_id: Id of the experiment
117         :type exp_id: str
118
119         """
120         if version and user and server and port and password:
121             key = cls._make_key(version, server, user, port, password, exp_id)
122             if key in cls._apis:
123                 cls._apis[key]['cnt'] -= 1
124                 #print "Api Counter : " + str(cls._apis[key]['cnt'])
125                 if cls._apis[key]['cnt'] == 0:
126                     omf_api = cls._apis[key]['api']
127                     omf_api.disconnect()
128                     del cls._apis[key]
129
130     @classmethod 
131     def _make_key(cls, *args):
132         """ Hash the credentials in order to create a key
133
134         :param args: list of arguments used to create the hash (server, user, port, ...)
135         :type args: list
136
137         """
138         skey = "".join(map(str, args))
139         return hashlib.md5(skey).hexdigest()
140
141
142