Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: genjix on February 13, 2011, 08:44:30 AM



Title: [PATCH] isinitialized RPC method
Post by: genjix on February 13, 2011, 08:44:30 AM
Why:
Currently it is hard for a GUI wrapping bitcoind by means of the RPC-server to detect when bitcoin is running but still initialising. This seeks to resolve that.

What does it do:
- Moves RPC server startup to very beginning.
- Adds isinitialized method.

Change made to bitcoin/bitcoin from github

http://pastebin.com/LYtBRXgk

Code:
diff --git a/init.cpp b/init.cpp
index 04bdd68..52cf7a1 100644
--- a/init.cpp
+++ b/init.cpp
@@ -115,6 +115,7 @@ bool AppInit(int argc, char* argv[])
     } catch (...) {
         PrintException(NULL, "AppInit()");
     }
+    fInitializationCompleted = true;
     if (!fRet)
         Shutdown(NULL);
     return fRet;
@@ -122,6 +123,9 @@ bool AppInit(int argc, char* argv[])
 
 bool AppInit2(int argc, char* argv[])
 {
+    if (GetBoolArg("-server") || fDaemon)
+        CreateThread(ThreadRPCServer, NULL);
+
 #ifdef _MSC_VER
     // Turn off microsoft heap dump noise
     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
@@ -443,9 +447,6 @@ bool AppInit2(int argc, char* argv[])
     if (!CreateThread(StartNode, NULL))
         wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
 
-    if (GetBoolArg("-server") || fDaemon)
-        CreateThread(ThreadRPCServer, NULL);
-
 #if defined(__WXMSW__) && defined(GUI)
     if (fFirstRun)
         SetStartOnSystemStartup(true);
diff --git a/rpc.cpp b/rpc.cpp
index 69b09bc..72fc9a8 100644
--- a/rpc.cpp
+++ b/rpc.cpp
@@ -28,6 +28,8 @@ void ThreadRPCServer2(void* parg);
 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
 extern map<string, rpcfn_type> mapCallTable;
 
+bool fInitializationCompleted = false;
+
 
 Object JSONRPCError(int code, const string& message)
 {
@@ -146,7 +148,6 @@ Value help(const Array& params, bool fHelp)
     return strRet;
 }
 
-
 Value stop(const Array& params, bool fHelp)
 {
     if (fHelp || params.size() != 0)
@@ -277,18 +278,22 @@ Value getinfo(const Array& params, bool fHelp)
 
     Object obj;
     obj.push_back(Pair("version",       (int)VERSION));
-    obj.push_back(Pair("balance",       (double)GetBalance() / (double)COIN));
-    obj.push_back(Pair("blocks",        (int)nBestHeight));
-    obj.push_back(Pair("connections",   (int)vNodes.size()));
-    obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
-    obj.push_back(Pair("generate",      (bool)fGenerateBitcoins));
-    obj.push_back(Pair("genproclimit",  (int)(fLimitProcessors ? nLimitProcessors : -1)));
-    obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
-    obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
-    obj.push_back(Pair("testnet",       fTestNet));
-    obj.push_back(Pair("keypoololdest", (boost::int64_t)GetOldestKeyPoolTime()));
-    obj.push_back(Pair("paytxfee",      (double)nTransactionFee / (double)COIN));
-    obj.push_back(Pair("errors",        GetWarnings("statusbar")));
+    obj.push_back(Pair("isinitialized", (bool)fInitializationCompleted));
+    if (fInitializationCompleted)
+    {
+        obj.push_back(Pair("balance",       (double)GetBalance() / (double)COIN));
+        obj.push_back(Pair("blocks",        (int)nBestHeight));
+        obj.push_back(Pair("connections",   (int)vNodes.size()));
+        obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
+        obj.push_back(Pair("generate",      (bool)fGenerateBitcoins));
+        obj.push_back(Pair("genproclimit",  (int)(fLimitProcessors ? nLimitProcessors : -1)));
+        obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
+        obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
+        obj.push_back(Pair("testnet",       fTestNet));
+        obj.push_back(Pair("keypoololdest", (boost::int64_t)GetOldestKeyPoolTime()));
+        obj.push_back(Pair("paytxfee",      (double)nTransactionFee / (double)COIN));
+        obj.push_back(Pair("errors",        GetWarnings("statusbar")));
+    }
     return obj;
 }
 
@@ -1806,6 +1811,8 @@ void ThreadRPCServer2(void* parg)
             if (valMethod.type() != str_type)
                 throw JSONRPCError(-32600, "Method must be a string");
             string strMethod = valMethod.get_str();
+            if (!fInitializationCompleted && strMethod != "help" && strMethod != "getinfo")
+                throw JSONRPCError(-42000, "Still initializing");
             if (strMethod != "getwork")
                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
 
diff --git a/rpc.h b/rpc.h
index 48a7b8a..85c3ef3 100644
--- a/rpc.h
+++ b/rpc.h
@@ -4,3 +4,4 @@
 
 void ThreadRPCServer(void* parg);
 int CommandLineRPC(int argc, char *argv[]);
+extern bool fInitializationCompleted;

PS plz add .patch to allowed attachments :D
PSS upload folder is full! i cannot upload the patch file.


Title: Re: [PATCH] isinitialized RPC method
Post by: jgarzik on February 13, 2011, 08:55:36 AM
Why:
Currently it is hard for a GUI wrapping bitcoind by means of the RPC-server to detect when bitcoin is running but still initialising. This seeks to resolve that.

Or you could just deduce same from getinfo's "blocks" and "connections" output...



Title: Re: [PATCH] isinitialized RPC method
Post by: genjix on February 13, 2011, 06:58:08 PM
Why:
Currently it is hard for a GUI wrapping bitcoind by means of the RPC-server to detect when bitcoin is running but still initialising. This seeks to resolve that.

Or you could just deduce same from getinfo's "blocks" and "connections" output...



I don't mean downloading the block chain, or finding connections, I mean the completion of AppInit(...)


Title: Re: [PATCH] isinitialized RPC method
Post by: genjix on February 13, 2011, 08:15:34 PM
I've updated the OP with a new version of the patch that adds an error message.

http://pastebin.com/W41J5K0M

in the few seconds before the rpc server has started and bitcoin is running, I need to know bitcoin is running but not initialised...
So I put the RPC server at the very beginning and add isinitialised (all other rpc methods except help/isinitialized will send an error when isinitialized is false)


Title: Re: [PATCH] isinitialized RPC method
Post by: jgarzik on February 13, 2011, 11:04:20 PM
Why:
Currently it is hard for a GUI wrapping bitcoind by means of the RPC-server to detect when bitcoin is running but still initialising. This seeks to resolve that.

Or you could just deduce same from getinfo's "blocks" and "connections" output...



I don't mean downloading the block chain, or finding connections, I mean the completion of AppInit(...)

The completion of AppInit is signalled by the availability of the RPC service -- that's why JSON-RPC is initialized last in AppInit.


Title: Re: [PATCH] isinitialized RPC method
Post by: genjix on February 14, 2011, 01:36:35 AM
Right but you don't know whether bitcoind is running or not.

You can start it but then you don't know if it crashed. Checking the PID's is unreliable too.

And periodically having to check whether bitcoind has finished initialisation by recreating new connections then querying an RPC method to see whether it throws an exception is bad.


Title: Re: [PATCH] isinitialized RPC method
Post by: jgarzik on February 14, 2011, 03:59:25 AM
Right but you don't know whether bitcoind is running or not.

You can look for it in the OS process list.


Title: Re: [PATCH] isinitialized RPC method
Post by: genjix on February 14, 2011, 07:00:02 AM
Right but you don't know whether bitcoind is running or not.

You can look for it in the OS process list.

As said... that's unreliable/undesirable.


Title: Re: [PATCH] isinitialized RPC method
Post by: genjix on February 15, 2011, 02:42:24 AM
updated OP as per gavinandresen's suggestions on IRC.