diff --git a/README.md b/README.md index 680e6d31..d9fb705f 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ $ zeronet.py Congratulations, you're finished! Now anyone can access your site using `http://localhost:43110/13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2` -Next steps: [ZeroNet Developer Documentation](https://github.com/HelloZeroNet/ZeroNet/wiki/ZeroNet-Developer-Documentation) +Next steps: [ZeroNet Developer Documentation](http://zeronet.readthedocs.org/en/latest/site_development/debug_mode/) ## How can I modify a ZeroNet site? diff --git a/src/Connection/Connection.py b/src/Connection/Connection.py index 2d692020..c7d864f7 100644 --- a/src/Connection/Connection.py +++ b/src/Connection/Connection.py @@ -264,6 +264,8 @@ class Connection: def close(self): if self.closed: return False # Already closed self.closed = True + self.event_connected.set(False) + if config.debug_socket: self.log.debug("Closing connection, waiting_requests: %s, buff: %s..." % (len(self.waiting_requests), self.incomplete_buff_recv)) for request in self.waiting_requests.values(): # Mark pending requests failed request.set(False) diff --git a/src/Connection/ConnectionServer.py b/src/Connection/ConnectionServer.py index c3b8f7cd..152fe17e 100644 --- a/src/Connection/ConnectionServer.py +++ b/src/Connection/ConnectionServer.py @@ -62,17 +62,22 @@ class ConnectionServer: def getConnection(self, ip=None, port=None, peer_id=None): if peer_id and peer_id in self.peer_ids: # Find connection by peer id connection = self.peer_ids.get(peer_id) - if not connection.connected: connection.event_connected.get() # Wait for connection + if not connection.connected: + succ = connection.event_connected.get() # Wait for connection + if not succ: raise Exception("Connection event return error") return connection if ip in self.ips: # Find connection by ip connection = self.ips[ip] - if not connection.connected: connection.event_connected.get() # Wait for connection + if not connection.connected: + succ = connection.event_connected.get() # Wait for connection + if not succ: raise Exception("Connection event return error") return connection - # Recover from connection pool for connection in self.connections: if connection.ip == ip: - if not connection.connected: connection.event_connected.get() # Wait for connection + if not connection.connected: + succ = connection.event_connected.get() # Wait for connection + if not succ: raise Exception("Connection event return error") return connection # No connection found @@ -80,7 +85,9 @@ class ConnectionServer: connection = Connection(self, ip, port) self.ips[ip] = connection self.connections.append(connection) - connection.connect() + succ = connection.connect() + if not succ: + raise Exception("Connection event return error") except Exception, err: self.log.debug("%s Connect error: %s" % (ip, Debug.formatException(err))) connection.close() @@ -103,26 +110,32 @@ class ConnectionServer: while self.running: time.sleep(60) # Sleep 1 min for connection in self.connections[:]: # Make a copy - if connection.protocol == "zeromq": continue # No stat on ZeroMQ sockets - idle = time.time() - max(connection.last_recv_time, connection.start_time) + idle = time.time() - max(connection.last_recv_time, connection.start_time, connection.last_message_time) if idle > 60*60: # Wake up after 1h + connection.log.debug("[Cleanup] After wakeup: %s" % connection.read_bytes(1024)) connection.close() elif idle > 20*60 and connection.last_send_time < time.time()-10: # Idle more than 20 min and we not send request in last 10 sec - if connection.protocol == "?": connection.close() # Got no handshake response, close it + if connection.protocol == "zeromq": + if idle > 50*60 and not connection.ping(): # Only ping every 50 sec + connection.close() else: if not connection.ping(): # send ping request connection.close() elif idle > 10 and connection.incomplete_buff_recv > 0: # Incompelte data with more than 10 sec idle - connection.log.debug("[Cleanup] Connection buff stalled, content: %s" % connection.u.read_bytes(1024)) + connection.log.debug("[Cleanup] Connection buff stalled, content: %s" % connection.read_bytes(1024)) connection.close() elif idle > 10 and connection.waiting_requests and time.time() - connection.last_send_time > 10: # Sent command and no response in 10 sec connection.log.debug("[Cleanup] Command %s timeout: %s" % (connection.last_cmd, time.time() - connection.last_send_time)) connection.close() + elif idle > 60 and connection.protocol == "?": # No connection after 1 min + connection.log.debug("[Cleanup] Connect timeout: %s" % idle) + connection.close() + def zmqServer(self): diff --git a/src/Debug/DebugHook.py b/src/Debug/DebugHook.py index 9c6d3b64..8146d299 100644 --- a/src/Debug/DebugHook.py +++ b/src/Debug/DebugHook.py @@ -1,4 +1,4 @@ -import gevent, sys +import gevent, sys, logging from Config import config last_error = None @@ -13,6 +13,7 @@ def handleError(*args): silent = False if args[0].__name__ != "Notify": last_error = args if not silent and args[0].__name__ != "Notify": + logging.exception("Unhandled exception") sys.__excepthook__(*args) diff --git a/src/Debug/DebugMedia.py b/src/Debug/DebugMedia.py index d02891e8..f0a23430 100644 --- a/src/Debug/DebugMedia.py +++ b/src/Debug/DebugMedia.py @@ -58,7 +58,7 @@ def merge(merged_path): parts.append(out) else: error = out - logging.error("%s Compile error %s:" % (file_path, error)) + logging.error("%s Compile error: %s" % (file_path, error)) parts.append("alert('%s compile error: %s');" % (file_path, re.escape(error).replace("\n", "\\n").replace(r"\\n", r"\n") ) ) else: # Not changed use the old_part parts.append(old_parts[file_path]) @@ -78,4 +78,4 @@ if __name__ == "__main__": logging.getLogger().setLevel(logging.DEBUG) os.chdir("..") config.coffeescript_compiler = r'type "%s" | tools\coffee-node\bin\node.exe tools\coffee-node\bin\coffee --no-header -s -p' - merge("data/1TaLk3zM7ZRskJvrh3ZNCDVGXvkJusPKQ/js/all.js") \ No newline at end of file + merge("data/12Hw8rTgzrNo4DSh2AkqwPRqDyTticwJyH/js/all.js") diff --git a/src/Peer/Peer.py b/src/Peer/Peer.py index bf10152b..d5b11d42 100644 --- a/src/Peer/Peer.py +++ b/src/Peer/Peer.py @@ -40,8 +40,7 @@ class Peer: try: self.connection = self.connection_server.getConnection(self.ip, self.port) except Exception, err: - self.log.debug("Getting connection error: %s" % Debug.formatException(err)) - self.onConnectionError() + self.log.debug("Getting connection error: %s (connection_error: %s, hash_failed: %s)" % (Debug.formatException(err), self.connection_error, self.hash_failed)) def __str__(self): return "Peer %-12s" % self.ip @@ -58,7 +57,9 @@ class Peer: def request(self, cmd, params = {}): if not self.connection or self.connection.closed: self.connect() - if not self.connection: return None # Connection failed + if not self.connection: + self.onConnectionError() + return None # Connection failed #if cmd != "ping" and self.last_response and time.time() - self.last_response > 20*60: # If last response if older than 20 minute, ping first to see if still alive # if not self.ping(): return None diff --git a/src/Site/Site.py b/src/Site/Site.py index 03e772a5..654cb214 100644 --- a/src/Site/Site.py +++ b/src/Site/Site.py @@ -51,6 +51,15 @@ class Site: self.addEventListeners() + + def __str__(self): + return "Site %s" % self.address_short + + + def __repr__(self): + return "<%s>" % self.__str__() + + # Load site settings from data/sites.json def loadSettings(self): sites_settings = json.load(open("data/sites.json")) diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py index 97ab7fd8..cc9990f1 100644 --- a/src/Ui/UiRequest.py +++ b/src/Ui/UiRequest.py @@ -291,11 +291,29 @@ class UiRequest: back.append("%s" % formatted) return "%s" % "".join(back) + + def getObjSize(self, obj, hpy = None): + if hpy: + return float(hpy.iso(obj).domisize)/1024 + else: + return 0 + + + def actionStats(self): import gc, sys + hpy = None + if self.get.get("size") == "1": # Calc obj size + try: + import guppy + hpy = guppy.hpy() + except: + pass self.sendHeader() s = time.time() main = sys.modules["src.main"] + + # Style yield """