def _get_next_worker(sid): s_obj = WebServerModel.objects(sid=sid) lowest_time = api._get_current_time() for child in s_obj.get().children: ## list of nodes failed once if child.nid in q.get_custom_list(api.FAILED_NODES): print "failed nodes" print q.get_custom_list(api.FAILED_NODES) pass elif not 'last_work' in child: s_obj.filter( children__nid=child.nid).update_one( set__children__S__last_work=lowest_time) # set as now if new server s_obj.get().save() next_worker_id = child.nid elif child.last_work < lowest_time: lowest_time = child.last_work next_worker_id = child.nid try: s_obj.filter( children__nid=next_worker_id).update_one( set__children__S__last_work=api._get_current_time()) s_obj.get().save() print "next worker is... {}".format(next_worker_id) return next_worker_id except NameError: logger.error("no workers are available") return None
def _clean_session_garbages(): garbage = [] for s in Sessions.objects[:]: if s.expiration < api._get_current_time(): garbage.append(s.ssid) if garbage: for s in garbage: Sessions.objects(ssid=s).delete()
def get_user_list(sid): if _coordinate_acc_to_res(sid=sid): if _upload_user_sessions(): ## TODO: try with mongodb query but this requires to ## handle obtain 'modified' and convert into unix timestamp to compare ## within the query users = map(lambda x:{ 'user_name':json.loads(x.user_data)['user_name'], 'modified':x['modified'], 'ssid':x['ssid'] } if api._get_unix_from_datetime( api._get_current_time())-api._get_unix_from_datetime( x.modified)<api.TIME_DETERMINE_USER_ACTIVE else None, UserSessions.objects.all()) # release resource lock _coordinate_acc_to_res(sid, sid, api._ACTION_KEYS[6]) # return list of lately active users by removing None values return filter(None, users) else: # release resource lock _coordinate_acc_to_res(sid, sid, api._ACTION_KEYS[6]) else: users = map(lambda x:{ 'user_name':json.loads(x.user_data)['user_name'], 'modified':x['modified'], 'ssid':x['ssid'] } if api._get_unix_from_datetime( api._get_current_time())-api._get_unix_from_datetime( x.modified)<api.TIME_DETERMINE_USER_ACTIVE else None, Sessions.objects.all()) return filter(None, users) return None
def _update_last_access_time(nid, sid): collection = WebServerModel._get_collection() result = collection.update_one( { "_id":sid, "children._id":nid }, { "$set": { "children.$.last_access":api._get_current_time() } }) return True if result.modified_count == 1 and result.matched_count == 1 else False
def open_session(self, app, request): ssid = request.cookies.get(app.session_cookie_name) if ssid: stored_session = self.sessions.find_one({'ssid': ssid}) #print "matched_session {}".format(stored_session) if stored_session: if stored_session.get('expiration') > api._get_current_time(): print "session id not expired: {}".format(ssid) return MongoSession( initial=stored_session['user_data'], ssid=stored_session['ssid']) ssid = api._generate_session_id() print "new ssid: {}".format(ssid) return MongoSession(ssid=ssid)
def _inspect_inactive_children(sid): #print "inspection...{}".format(sid) s_obj = WebServerModel.objects(sid=sid) children = s_obj.get().children if children: for child in children: #logger.info(child.last_access) #logger.info(api._get_current_time()) if api._get_unix_from_datetime( api._get_current_time())-api._get_unix_from_datetime( child.last_access)>api.TIME_DETERMINE_INACTIVE: logger.info(child.nid+" -> user logged out") ## pull inactive user s_obj.update_one(pull__children__nid=child.nid) s_obj.get().save() ## notify all clients about inactive user message = json.dumps( { 'action':api._ACTION_KEYS[2], 'data':{ "nid":child.nid, } }) ## remove lock on shared resource if the inactive child is holding it if q.get(api.RES_HOLDER) == child.nid: logger.info("logging out user had locks") _coordinate_acc_to_res(sid, child.nid, api._ACTION_KEYS[6]) _broadcast_to_nodes(api.EXCHANGE_FOR_ALL, api.encrypt_msg(s_obj.scalar('common_key_public').get(), message)) _make_log(api._ACTION_KEYS[2], sid, child.nid) ## TODO: try deamon thread threading.Timer(api.INSPECTION_TIME_INTERVAL, _inspect_inactive_children, [sid]).start()
def _send_heartbeat(self, server_id, nid): retry = 0 while retry < api.MAX_TRY: try: proxy = callme.Proxy( server_id=server_id, amqp_host="localhost", amqp_port=5672, timeout=3) proxy.use_server(server_id).receive_heartbeats(nid, server_id) # try again retry = api.MAX_TRY ## record heartbeat locally as well AppModel.objects(nid=nid).update_one(last_access=api._get_current_time()) is_master_failing = False # try daemon thread #threading.Timer(3, _send_heart_beat).setDaemon(True) threading.Timer(api.CHECK_HEARTBEAT, self._send_heartbeat, [server_id, nid]).start() except: retry += 1 is_master_failing = True print "Server: {} is not responding, trying {} times...".format(server_id, str(retry)) #print "Master server is not responding" ## master server failed if is_master_failing: self.timer = ConnTimeout(api._TIMEOUT, app_api._send_handshake_msg, servers=3, args=[nid, AppModel.objects(nid=nid).get().public_key, AppModel.objects(nid=nid).get().created_at.isoformat()]) self.timer.start() """_send_handshake_msg(
def save_session(self, app, session, response): domain = self.get_cookie_domain(app) if not session: ## in web_server session is not defined print "delete cookies" response.delete_cookie(app.session_cookie_name, domain=domain) return session if self.get_expiration_time(app, session): expiration = self.get_expiration_time(app, session) else: expiration = api._get_expiration_time() print "expiration has been extended {}".format(expiration) res = self.sessions.update_one( {'ssid': session.ssid}, { '$set':{ 'by':self.by, 'ssid': session.ssid, 'user_data': session, 'expiration': expiration, 'modified':api._get_current_time() } }, upsert=True) ## upsert true if res.upserted_id: logger.info("New session id added to the system") elif res.matched_count == 1 and res.modified_count == 1: logger.info("Existing session id updated") else: logger.critical("Something wrong with user session") response.set_cookie(app.session_cookie_name, session.ssid, expires=self.get_expiration_time(app, session), httponly=True, domain=domain)
def process_msg_add_request(sid, uname, ssid, comment): ## if master fails to find slave node, try MAX_TRY times until it ## response 503 retry = 0 while retry < api.MAX_TRY: try: node = _get_next_worker(sid) if node == None: break s_time = api._get_current_time().isoformat() response = _send_add_comment_call(**{ 'nid':node, 'sid':sid, 'by':uname, 'session_id':ssid, 'comment':comment, 'created_at':s_time }) if not response: retry+=1 q.custom_push(api.FAILED_NODES, node) logger.error("failed... trying another node...") ## execution succeed else: return api.decrypt_msg( WebServerModel.objects(sid=sid).get().private_key, response) except: retry+=1 logger.error("failed... trying another node...") return { 'errorMsg':"chatting is not available at the moment" }