瀏覽代碼

Z991239-385 #comment 1.添加了错误码Error_Busy;2.添加了框架状态枚举变量;3.shell.ini添加对测试实体的读取;4. 添加了spshell --kill强制杀死框架相关进程的操作

gifur 5 年之前
父節點
當前提交
e94f8553fa

+ 12 - 11
Common/ErrorCode.h

@@ -34,22 +34,23 @@ enum ErrorCodeEnum
 
 	//Entity state's category
 	Error_InvalidState=0x300,	//state is not valid for current call
-	Error_NotInit,				   //The target is not be initial
-	Error_Paused,				   //the access object is in Pause state
-	Error_Stoped,				   //the access object is in Stop state
-	Error_Losted,				   //the access object is in Lost state 
-	Error_Closed,				  //opposite side in close state
-	Error_Accept,                 //test mode: pass the test
-	Error_Failed,                  //test mode: fail to pass the test.
+	Error_NotInit,				        //The target is not be initial
+	Error_Paused,				        //the access object is in Pause state
+	Error_Stoped,				       //the access object is in Stop state
+	Error_Losted,				       //the access object is in Lost state 
+	Error_Closed,				       //opposite side in close state
+	Error_Accept,                     //test mode: pass the test
+	Error_Failed,                      //test mode: fail to pass the test.
+	Error_Busy,                        //the access object is busy doing
 
 	//Framework Task control's category
 	Error_TaskControl=0x400,
-	Error_Pending,				//The request in not finish
-	Error_Cancel,				//The process is be cancel by framework
-	Error_Break,				    //The task has interrupt
+	Error_Pending,				             //The request in not finish
+	Error_Cancel,				             //The process is be cancel by framework
+	Error_Break,				                 //The task has interrupt
 	Error_NotMeetCondition,		 //not meat run condition,run cancel
 	Error_NoPrivilege,			         //no privilege
-	Error_MethodSignatureFailed,//method signature failed
+	Error_MethodSignatureFailed, //method signature failed
 
 	//opposite side action's category 
 	Error_PeerAction=0x500,

+ 17 - 0
Common/SpBase.h

@@ -94,6 +94,19 @@ enum InstallStateEnum
 	Install_Installed,			// D, only used to LightPack
 };
 
+/** framework state*/
+enum FrameworkStateEnum
+{
+	FrameworkState_NotInit = 0,   /** the begin state*/
+	FrameworkState_Booting,        /** the entity is starting*/
+	FrameworkState_Running,       /** the machine is providing service*/
+	FrameworkState_Breakdown,   /** the machine is sick*/
+	FrameworkState_Repairing,     /** the machine is being maintained*/
+	FrameworkState_Upgrading,   /** the software is upgrading*/
+	FrameworkState_Rollbacking, /** the software is rollback for some reason*/
+	FrameworkState_Recoving     /** the machine is reaching running state from other state*/
+};
+
 /** entity state */
 enum EntityStateEnum
 {
@@ -352,6 +365,7 @@ struct CSystemRunInfo
 {
 	CSmallDateTime tmStart;
 	DebugLevelEnum eDebugLevel;
+	FrameworkStateEnum eState;
 	CAutoArray<CSimpleStringA> strRunningEntityNames;
 };
 
@@ -792,6 +806,9 @@ struct IEntityFunctionPrivilege
 	/** if persist=true,the DebugLevel will be keep after restart */
 	virtual ErrorCodeEnum SetSysDebugLevel(const char *pszEntityName,DebugLevelEnum eDebugLevel,bool bPersist=false)=0;
 
+	/*upate terminal current state*/
+	virtual ErrorCodeEnum RefreshFrameworkState(FrameworkStateEnum eState) = 0;
+
 	/** get %SysRoot%\Ver\<version> 's config info */
 	virtual ErrorCodeEnum GetSystemStaticInfoForVersion(CVersion verSoftware,CSystemStaticInfo &StaticInfo)=0;
 

+ 4 - 0
Common/SpHelper.h

@@ -337,6 +337,10 @@ SPBASE_API LPCTSTR SpStrCloseCause(const EntityCloseCauseEnum cause);
 
 SPBASE_API LPCTSTR SpStrRebootTrigger(const RebootTriggerEnum trigger);
 
+SPBASE_API LPCTSTR SpStrRebootWay(const RebootWayEnum way);
+
+SPBASE_API LPCTSTR SpStrFrameworkState(const FrameworkStateEnum state);
+
 #define IS_SUCCEED(hr)	((hr) == Error_Succeed)
 
 #define IS_FAILURED(hr) (!(IS_SUCCEED(hr)))

+ 6 - 1
README.md

@@ -13,7 +13,12 @@
 ## 更新记录
 * 2020-04-23: SpHelper.h 新增 `IFFAILRET`,`REQUIRE`,`REQUIRE_FALSE` 宏用于测试案例编写
 * 2020-04-22: Spbase.h 新增 `SpStrError` 接口用于将 ErrorCodeEnum 转成 字符串描述
-* 
+* 2020-05-13: SpShell 添加带参启动
+--entity {entityName}               -- 启动指定的实体
+--guardian                                -- 以后台监控形式运行程序
+--test                                        -- 以测试模式运行程序
+--debug                                   -- 以Debug的模式运行程序
+--ipc <pipe,tcp>                     -- pipe: 实体间以管道的方式通信;tcp: 实体间以socket的方式通信
 
 ## 依赖情况
 

+ 7 - 0
addin/cfg/TestDeamon.ini

@@ -0,0 +1,7 @@
+[Entity]
+Number=0
+1=TestSubscribe
+2=SampleEntity
+3=TestLogSender
+4=TestNormalEntity
+5=TestPrivilegeEntity

+ 12 - 9
addin/cfg/shell.ini.in

@@ -16,20 +16,23 @@ TestPassiveThirdEntity=0,@LIB_PREFIX@mod_testPassiveEntity@LIB_SUFFIX@,0x10A
 TestLogSender=0,@LIB_PREFIX@mod_testSendLog@LIB_SUFFIX@,0x10B
 
 [Startup]
-Number=8
-1=TestDeamon TestMode=ON Level=3 Entity=BlackSheep -D
-2=HelloService
-3=HelloClient
-4=TestSubscribe
-5=SampleEntity
-6=TestLogSender
-7=TestNormalEntity
-8=TestPrivilegeEntity
+Number=2
+1=HelloService
+2=HelloClient
 
 [SysEvent]
 SampleState=SampleEntity;TestDeamon;HelloClient HelloService,"0"
 PrivilegeState=TestPrivilegeEntity	TestNormalEntity,"the max length of this system value cannot exceed to 260 include end char"
 
+[Test]
+Number=6
+1=TestDeamon TestMode=ON Level=3 Entity=BlackSheep -D
+2=TestSubscribe
+3=SampleEntity
+4=TestLogSender
+5=TestNormalEntity
+6=TestPrivilegeEntity
+
 [Debug]
 TestDeamon=1
 HelloClient=1

+ 0 - 3
libtoolkit/memutil.c

@@ -124,9 +124,6 @@ TOOLKIT_API int GetSystemErrorDesc(int error_code, char *buf, int n)
 }
 
 
-
-
-
 TOOLKIT_API void toolkit_free(void *p)
 {
 	free(p);

+ 42 - 1
libtoolkit/osutil.c

@@ -40,7 +40,6 @@ TOOLKIT_API int osutil_detect_unique_app(char** pNames, int nNum)
 	return rc;
 }
 
-
 TOOLKIT_API int osutil_restart_system()
 {
 	HANDLE hToken;
@@ -84,6 +83,43 @@ TOOLKIT_API int osutil_restart_system()
 	return 0;
 }
 
+TOOLKIT_API void osutil_terminate_related_process(char** process_array, const int array_size)
+{
+	const DWORD dwCurProcessID = GetCurrentProcessId();
+	DWORD relateProcessIDs[256];
+	DWORD dwIdx = 0;
+	char szCmd[256];
+	DWORD relateProcessNum = 0;
+
+	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+	memset(relateProcessIDs, 0, sizeof(relateProcessIDs));
+
+	if (hSnapshot)
+	{
+		PROCESSENTRY32 pe;
+		pe.dwSize = sizeof(pe);
+
+		if (Process32First(hSnapshot, &pe)) {
+			do {
+				int i;
+				for (i = 0; i < array_size; i++) {
+					if (stricmp(&pe.szExeFile[0], process_array[i]) == 0 && pe.th32ProcessID != dwCurProcessID) {
+						relateProcessIDs[relateProcessNum++] = pe.th32ProcessID;
+						break;
+					}
+				}
+			} while (Process32Next(hSnapshot, &pe));
+		}
+		CloseHandle(hSnapshot);
+	}
+	
+	for (dwIdx = 0; dwIdx < relateProcessNum; ++dwIdx) {
+		sprintf_s(szCmd, 256, "TASKKILL /PID %d /F", relateProcessIDs[dwIdx]);
+		WinExec(szCmd, SW_HIDE);
+	}
+}
+
 #else
 
 #include <dirent.h>
@@ -158,6 +194,11 @@ TOOLKIT_API int osutil_restart_system()
 	return 0;
 }
 
+TOOLKIT_API void osutil_terminate_related_process(char** process_array, const int array_size)
+{
+	
+}
+
 #endif
 
 

+ 2 - 0
libtoolkit/osutil.h

@@ -22,6 +22,8 @@ extern "C" {
 TOOLKIT_API int osutil_detect_unique_app(char **pNames, int nNum);
 TOOLKIT_API int osutil_restart_system();
 
+TOOLKIT_API void osutil_terminate_related_process(char** process_array, const int array_size);
+
 #ifdef __cplusplus
 } // extern "C" {
 #endif

+ 3 - 3
libtoolkit/win/bus.c

@@ -633,7 +633,7 @@ static int bus_endpt_poll_internal(bus_endpt_t* endpt, int* result, int timeout)
 		iobuffer_restore_read_state(pkt, read_state);
 		*result = to_result(pkt_type);
 		if (*result == BUS_RESULT_UNKNOWN) {
-			OutputDebugStringA("bug: unknown pkt type!\n");
+			WLog_ERR(TAG, "bug: unknown pkt type!");
 			return -1;
 		}
 		return 1;
@@ -645,7 +645,7 @@ static int bus_endpt_poll_internal(bus_endpt_t* endpt, int* result, int timeout)
 		if (rc < 0)
 			return rc;
 		if (pkt) {
-			OutputDebugStringA("pkt has read\n");
+			WLog_DBG(TAG, "pkt has read");
 			rc = append_rx_pkt(endpt, pkt);
 			if (rc < 0) {
 				iobuffer_destroy(pkt);
@@ -653,7 +653,7 @@ static int bus_endpt_poll_internal(bus_endpt_t* endpt, int* result, int timeout)
 			}
 		}
 		else {
-			OutputDebugStringA("pending\n");
+			WLog_DBG(TAG, "pending");
 		}
 	}
 

+ 7 - 0
module/mod_testNormalEntity/mod_testNormalEntity.cpp

@@ -145,15 +145,22 @@ ErrorCodeEnum CNormalEntityTest::__onTest()
 	REQUIRE(strStartedEntityNames.GetCount() == strEntityInstanceIDs.GetCount());
 	for (int i = 0; i < strStartedEntityNames.GetCount(); ++i) {
 		Dbg("started entity name: %s", strStartedEntityNames[i].GetData());
+
+		Dbg("get entity run info...");
 		CEntityRunInfo curRunInfo;
 		IFFAILRET(func->GetEntityRunInfo(strStartedEntityNames[i], curRunInfo));
+
+		Dbg("get entity session info...");
 		CAutoArray<CEntitySessionInfo> sesInfos;
 		IFFAILRET(func->GetEntitySessionInfo(strStartedEntityNames[i], sesInfos));
+
+		Dbg("get entity name...");
 		CSimpleStringA strEntityName;
 		IFFAILRET(func->GetEntityName(strEntityInstanceIDs[i], strEntityName));
 		REQUIRE(strEntityName.Compare(strStartedEntityNames[i]) == 0);
 	}
 
+	Dbg("get self entity info...");
 	CEntityRunInfo entRunInfo;
 	IFFAILRET(func->GetSelfEntityRunInfo(entRunInfo));
 

+ 1 - 0
module/mod_testPrivilegeEntity/mod_testPrivilegeEntity.cpp

@@ -46,6 +46,7 @@ ErrorCodeEnum CPrivilegeEntityTest::_onTest()
 	REQUIRE(Error_Param == privilegeFunc->PauseEntity("", spWait));
 	REQUIRE(Error_NotExist == privilegeFunc->PauseEntity("NoExistedEntity", spWait));
 
+	Dbg("Try to start %s entity", CHILD_TEST_ENTITY_NAME);
 	IFFAILRET(privilegeFunc->StartEntity(CHILD_TEST_ENTITY_NAME, "param1 2 \"I am a bank\" -mode test", spWait));
 	REQUIRE(spWait != NULL);
 	IFFAILRET(spWait->WaitAnswer(10000));

+ 127 - 2
module/mod_validityVertifier/mod_validityVertifier.cpp

@@ -4,6 +4,9 @@
 
 /*Integrated test deamon*/
 
+#define OP_START  1
+#define OP_TEST     2
+
 struct TestModeInfo {
 	TestModeInfo() :isTestMode(false), nLevel(0) {
 	}
@@ -11,10 +14,15 @@ struct TestModeInfo {
 	int nLevel;
 };
 
-class CTestDeamon : public CEntityBase, public IEntityLifeListener, public IEntityStateListener, public ILogListener
+class CTestDeamon
+	: public CEntityBase
+	, public IEntityLifeListener
+	, public IEntityStateListener
+	, public ILogListener
+	, public ICallbackListener
 {
 public:
-	CTestDeamon() {}
+	CTestDeamon() : _dwStartedTestEntities(0) { _arrTestEntities.Clear(); }
 	virtual ~CTestDeamon() {
 		GetFunction()->UnsubscribeLog(m_subUUID);
 		GetFunction()->GetPrivilegeFunction()->UnregistLiftEvent();
@@ -46,9 +54,64 @@ public:
 		pTransactionContext->SendAnswer(Error_Succeed);
 	}
 
+	BOOL IsExcludeEntity(const CSimpleStringA& name)
+	{
+		if (name.Compare(GetEntityName()) == 0)
+			return TRUE;
+
+		for (int i = 0; i < _arrTestEntities.GetCount(); ++i) {
+			if (name.Compare(_arrTestEntities[i]) == 0)
+				return TRUE;
+		}
+		
+		return FALSE;
+	}
+
+	void TestAllRegistedEntity()
+	{
+		CAutoArray<CSimpleStringA> arrStartEntities;
+		CAutoArray< DWORD> arrEntitityID;
+		IFFAILBREAK(GetFunction()->GetAllStartedEntity(arrStartEntities, arrEntitityID));
+		for (int i = 0; i < arrStartEntities.GetCount(); ++i) {
+			if(!IsExcludeEntity(arrStartEntities[i]))
+				TestEntity(arrStartEntities[i]);
+		}
+	}
+
+	ErrorCodeEnum StartTestEntity()
+	{
+		CSmartPointer<IConfigInfo> spConfig;
+		IFFAILRET(GetFunction()->OpenConfig(Config_Software, spConfig));
+		auto privilegeFunc = GetFunction()->GetPrivilegeFunction();
+		REQUIRE(privilegeFunc != NULL);
+		int entityCount = 0;
+		IFFAILRET(spConfig->ReadConfigValueInt("Entity", "Number", entityCount));
+		_arrTestEntities.Init(entityCount);
+		for (int i = 1; i <= entityCount; ++i) {
+			char szNumber[4];
+			sprintf(szNumber, "%d", i);
+			CSimpleStringA strCurEntityName;
+			IFFAILRET(spConfig->ReadConfigValue("Entity", szNumber, strCurEntityName));
+			REQUIRE_FALSE(strCurEntityName.IsNullOrEmpty());
+			Dbg("Try to start entity: %s", (LPCTSTR)strCurEntityName);
+			CSmartPointer<IAsynWaitSp> spWait;
+			IFFAILRET(privilegeFunc->StartEntity(strCurEntityName, NULL, spWait));
+			REQUIRE(spWait != NULL);
+			SetOPCallback(spWait, strCurEntityName, OP_START);
+			//_arrTestEntities[i - 1] = strCurEntityName;
+		}
+		return Error_Succeed;
+	}
+
 	virtual void OnStarted()
 	{
 		LOG_FUNCTION();
+
+		if (_testInfo.isTestMode) {
+			if (IS_SUCCEED(StartTestEntity())) {
+				//TestAllRegistedEntity();
+			}
+		}
 	}
 
 	virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer<ITransactionContext> pTransactionContext) 
@@ -90,6 +153,10 @@ public:
 		if (eState == EntityState_Failed || eState == EntityState_Lost) {
 			RequireTerminalExit();
 		}
+		else if (eLastState == EntityState_Starting && eState == EntityState_Idle) {
+			/** if meet multi-entities at one mod, do test maybe failed beacause mod is busy at starting other brother entity.*/
+			//TestEntity(pszEntityName);
+		}
 	}
 
 	void OnUserStateHook(const char* pszEntityName, DWORD dwState, DWORD dwLastState)
@@ -132,6 +199,40 @@ public:
 		}
 	}
 
+	struct TestCallbackResult : public IReleasable
+	{
+		TestCallbackResult() :strEntityName(true), op(0) {}
+		virtual ~TestCallbackResult() {}
+		CSimpleStringA strEntityName;
+		int op;
+	};
+
+	/*ICallbackListener*/
+	void OnAnswer(CSmartPointer<IAsynWaitSp> pAsynWaitSp)
+	{
+		CSmartPointer<ICallbackListener> listener;
+		CSmartPointer<IReleasable> context;
+		CHECK(pAsynWaitSp->GetCallback(listener, context));
+		TestCallbackResult* result = static_cast<TestCallbackResult*>(context.GetRawPointer());
+		CHECK(result != NULL);
+		const auto ec = pAsynWaitSp->AsyncGetAnswer();
+		if (result->op == OP_START) {
+			if (IS_FAILURED(ec)) {
+				THROW_ERROR("Start %s failed return %s!", result->strEntityName.GetData(), SpStrError(ec));
+			}
+			else {
+				Dbg("Start entity %s succ.", result->strEntityName.GetData());
+				_arrTestEntities[_dwStartedTestEntities++] = result->strEntityName;
+			}
+		}
+		else if(result->op == OP_TEST) {
+			if (IS_FAILURED(ec)) {
+				THROW_ERROR("Test for %s failed return %s!", result->strEntityName.GetData(), SpStrError(ec));
+			}
+			Dbg("Test %s succ.", result->strEntityName.GetData());
+		}
+	}
+
 
 private:
 	void RequireTerminalExit()
@@ -143,9 +244,33 @@ private:
 		}
 	}
 
+	void SetOPCallback(CSmartPointer<IAsynWaitSp>& spWait, const char* pcszName, int op)
+	{
+		TestCallbackResult* result = new TestCallbackResult();
+		result->strEntityName = pcszName;
+		result->op = op;
+		spWait->SetCallback(this, result);
+	}
+
+	ErrorCodeEnum TestEntity(const char* lcpszEntityName)
+	{
+		Dbg("Test specified entity: %s", lcpszEntityName);
+		auto pPriviFunc = GetFunction()->GetPrivilegeFunction();
+		CSmartPointer<IAsynWaitSp> waitSp;
+		auto ec = pPriviFunc->TestEntity(lcpszEntityName, Test_Examine, waitSp);
+		if (IS_FAILURED(ec)) {
+			THROW_ERROR("Try to test for %s failed return %s!", lcpszEntityName, SpStrError(ec));
+			return Error_Failed;
+		}
+		SetOPCallback(waitSp, lcpszEntityName, OP_TEST);
+		return Error_Succeed;
+	}
+
 private:
 	TestModeInfo _testInfo;
 	CUUID m_subUUID;
+	CAutoArray<CSimpleStringA> _arrTestEntities;
+	DWORD _dwStartedTestEntities;
 };
 
 SP_BEGIN_ENTITY_MAP()

+ 1 - 0
spbase/SpBase.cpp

@@ -466,6 +466,7 @@ on_error:
 	MAP(Error_Closed, "Error_Closed")	\
 	MAP(Error_Accept, "Error_Accept")	\
 	MAP(Error_Failed, "Error_Failed")	\
+	MAP(Error_Busy, "Error_Busy")	\
 	MAP(Error_TaskControl, "Error_TaskControl")	\
 	MAP(Error_Pending, "Error_Pending")	\
 	MAP(Error_Cancel, "Error_Cancel")	\

+ 0 - 2
spbase/SpEntity.cpp

@@ -1392,8 +1392,6 @@ ErrorCodeEnum SpEntity::GetAllRegistSpFile(CAutoArray<CSimpleStringA> &Names)
 	for (int i = 0; i < arr_module->nelts; ++i) {
 		sp_cfg_shell_module_t* mod = ARRAY_IDX(arr_module, i, sp_cfg_shell_module_t*);
 		Names[i] = mod->name;
-		// BugFix [Gifur@2020422]
-		//Names[i] = ARRAY_IDX(arr_module, i, char*);
 	}
 
 	return Error_Succeed;

+ 8 - 0
spbase/SpEntityPrivilege.cpp

@@ -1993,6 +1993,14 @@ ErrorCodeEnum SpEntityPrivilege::SetSysDebugLevel(const char *pszEntityName,Debu
 	return Error_Succeed;
 }
 
+ErrorCodeEnum SpEntityPrivilege::RefreshFrameworkState(FrameworkStateEnum eState)
+{
+	sp_env_t* env = sp_get_env();
+	env->cfg->shell_ini->shell_state = (int)eState;
+	//TODO: broadcast
+	return Error_Succeed;
+}
+
 ErrorCodeEnum SpEntityPrivilege::ShowOuputConsole()
 {
 	ErrorCodeEnum Error;

+ 1 - 0
spbase/SpEntityPrivilege.h

@@ -60,6 +60,7 @@ public:
 	// debug
 	virtual ErrorCodeEnum SetSysDebugLevel(const char *pszEntityName,DebugLevelEnum eDebugLevel,bool bPersist=false);
 
+	virtual ErrorCodeEnum RefreshFrameworkState(FrameworkStateEnum eState);
 private:
 
 	void on_entity_create(int entity_id, int trigger_entity_id);

+ 36 - 1
spbase/SpHelper.cpp

@@ -754,7 +754,6 @@ SPBASE_API LPCTSTR SpStrCloseCause(const EntityCloseCauseEnum cause)
 	return "Unknown";
 }
 
-
 #undef ENT_ENUM_MAP
 #define ENT_ENUM_MAP(name) case RebootTrigger_##name: return #name; break;
 
@@ -784,4 +783,40 @@ SPBASE_API LPCTSTR SpStrRebootTrigger(const RebootTriggerEnum trigger)
 }
 
 #undef ENT_ENUM_MAP
+#define ENT_ENUM_MAP(name) case RebootWay_##name: return #name; break;
+
+SPBASE_API LPCTSTR SpStrRebootWay(const RebootWayEnum way)
+{
+	switch (way) {
+		ENT_ENUM_MAP(Unknown)
+			ENT_ENUM_MAP(Framework)
+			ENT_ENUM_MAP(OS)
+			ENT_ENUM_MAP(Power)
+	default:
+		break;
+	}
+	return "UnRecorded";
+}
+
+#undef ENT_ENUM_MAP
+#define ENT_ENUM_MAP(name) case FrameworkState_##name: return #name; break;
+
+SPBASE_API LPCTSTR SpStrFrameworkState(const FrameworkStateEnum state)
+{
+	switch (state) {
+		ENT_ENUM_MAP(NotInit)
+		ENT_ENUM_MAP(Booting)
+		ENT_ENUM_MAP(Running)
+		ENT_ENUM_MAP(Breakdown)
+		ENT_ENUM_MAP(Repairing)
+		ENT_ENUM_MAP(Upgrading)
+		ENT_ENUM_MAP(Rollbacking)
+		ENT_ENUM_MAP(Recoving)
+	default:
+		break;
+	}
+	return "UnRecorded";
+}
+
+#undef ENT_ENUM_MAP
 

+ 2 - 6
spbase/sp_btr.c

@@ -230,17 +230,13 @@ int sp_btr_write_on_shutdown(const char *bootrec_path, sp_btr_context_t *ctx, in
 		reason_way_count = ctx->last_boot_info.shutdown_way_cnt + 1;
 	
 	y2k_to_localtime(ctx->cur_start_time, &st);
-#ifdef _WIN32
-	sprintf(szCurLog, "%s\\%04d%02d.log", bootrec_path, st.wYear, st.wMonth);
-#else
-	sprintf(szCurLog, "%s/%04d%02d.log", bootrec_path, st.wYear, st.wMonth);
-#endif
+	sprintf(szCurLog, "%s" SPLIT_SLASH_STR "%04d%02d.log", bootrec_path, st.wYear, st.wMonth);
 
 	bWriteBootInfo = !ExistsFileA(szCurLog);
 	hFile = CreateFileA(szCurLog, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 	if (hFile == INVALID_HANDLE_VALUE)
 	{
-		sp_dbg_error("open boot file fail");
+		sp_dbg_error("open boot file %s fail: %d", szCurLog, GetLastError());
 		return -1;
 	}
 

+ 114 - 10
spbase/sp_cfg.cpp

@@ -631,7 +631,7 @@ static int shell_ini__load_entities_list(sp_dir_t* dir, sp_cfg_shell_ini_t* shel
 	return rc;
 }
 
-static int shell_ini__load_mod_entity(sp_dir_t* dir, sp_cfg_shell_ini_t* shell, const  const char* shell_ini_path, const sp_cfg_start_args_t* args, const CVersionInfo* ver)
+static int shell_ini__load_mod_entity(sp_dir_t* dir, sp_cfg_shell_ini_t* shell, const char* shell_ini_path, const sp_cfg_start_args_t* args, const CVersionInfo* ver)
 {
 	shell->arr_entity = shm_array_make(0, sizeof(sp_cfg_shell_entity_t*));
 	// BugFix: replace char* with sp_cfg_shell_module_t* [Gifur@2020422]
@@ -706,12 +706,96 @@ static int shell_ini__load_sysevent(sp_cfg_shell_ini_t* shell, const char* shell
 	return rc;
 }
 
-static int shell_init__load_startup_list(sp_cfg_shell_ini_t* shell, const char* shell_ini_path)
+
+static int shell_ini__load_entity_list(sp_cfg_shell_ini_t* shell, array_header_t** arr, const char* shell_ini_path, int test_mode)
 {
 	int i;
 	int rc = 0;
+	char section_name[128] = { "Startup" };
+	if (test_mode) {
+		sp_dbg_debug("test mode: override startup list");
+		strcpy(section_name, "Test");
+	}
+	assert(arr);
+	assert(*arr == NULL);
 
-	i = inifile_read_int(shell_ini_path, "Startup", "Number", 0);
+	i = inifile_read_int(shell_ini_path, section_name, "Number", 0);
+	if (i >= 0) {
+		int n = i;
+		*arr = shm_array_make(i, sizeof(char*));
+		assert(*arr);
+		for (i = 1; i <= n; ++i) {
+			char key[512];
+			char* s;
+			_itoa(i, key, 10);
+			s = inifile_read_str(shell_ini_path, section_name, key, "");
+			if (s) {
+				if (strlen(s)) {
+					int numargs, numchars;
+					char** argv = NULL;
+					char* p;
+					sp_cfg_shell_entity_t* ent;
+					char* cmdline = strchr(s, ' ');
+					if (cmdline) {
+						*cmdline = 0;
+						cmdline++;
+						str_parse_cmdline(cmdline, NULL, NULL, &numargs, &numchars);
+						p = (char*)shm_malloc(numargs * sizeof(char*) + numchars);
+						argv = (char**)p;
+						str_parse_cmdline(cmdline, (char**)p, p + numargs * sizeof(char*), &numargs, &numchars);
+					}
+					ent = find_entity(shell, s);
+					if (ent) {
+						if (cmdline) {
+							//TODO: detect only use entity::cmdline, never seem use of argc and argv  [Gifur@2020426]
+							ent->argc = numargs;
+							ent->argv = argv;
+							if (numargs) {
+								ent->cmdline = shm_strdup(cmdline);
+							}
+						}
+						SHM_ARRAY_PUSH(*arr, sp_cfg_shell_entity_t*) = ent;
+					}
+					else {
+						sp_dbg_warn("read %s failed! find startup list [%s] defined entity [%s] fail!", section_name, key, s);
+						rc = Error_Param;
+					}
+				}
+				else {
+					sp_dbg_warn("read %s failed! startup list [%s] define invalid!", section_name, key);
+					rc = Error_Param;
+				}
+				toolkit_free(s);
+			}
+			else {
+				sp_dbg_warn("read %s failed! startup list [%s] define invalid!", section_name, key);
+				rc = Error_Param;
+			}
+
+			if (rc != 0)
+				break;
+		}
+	}
+	else {
+		sp_dbg_warn("read %s failed! startup number invalid!", section_name);
+		rc = Error_Param;
+	}
+
+	return rc;
+}
+
+/*
+static int shell_ini__load_bootup_entities(sp_cfg_shell_ini_t* shell, const char* shell_ini_path, int test_mode)
+{
+	int i;
+	int rc = 0;
+	char section_name[128] = { "Startup" };
+	if (test_mode) {
+		sp_dbg_debug("test mode: override startup list");
+		strcpy(section_name, "Test");
+	}
+
+	i = inifile_read_int(shell_ini_path, section_name, "Number", 0);
 	if (i >= 0) {
 		int n = i;
 		shell->arr_startlist = shm_array_make(i, sizeof(char*));
@@ -719,7 +803,7 @@ static int shell_init__load_startup_list(sp_cfg_shell_ini_t* shell, const char*
 			char key[512];
 			char* s;
 			_itoa(i, key, 10);
-			s = inifile_read_str(shell_ini_path, "Startup", key, "");
+			s = inifile_read_str(shell_ini_path, section_name, key, "");
 			if (s) {
 				if (strlen(s)) {
 					int numargs, numchars;
@@ -748,18 +832,18 @@ static int shell_init__load_startup_list(sp_cfg_shell_ini_t* shell, const char*
 						SHM_ARRAY_PUSH(shell->arr_startlist, sp_cfg_shell_entity_t*) = ent;
 					}
 					else {
-						sp_dbg_warn("read Startup failed! find startup list [%s] defined entity [%s] fail!", key, s);
+						sp_dbg_warn("read %s failed! find startup list [%s] defined entity [%s] fail!", section_name, key, s);
 						rc = Error_Param;
 					}
 				}
 				else {
-					sp_dbg_warn("read Startup failed! startup list [%s] define invalid!", key);
+					sp_dbg_warn("read %s failed! startup list [%s] define invalid!", section_name, key);
 					rc = Error_Param;
 				}
 				toolkit_free(s);
 			}
 			else {
-				sp_dbg_warn("read Startup failed! startup list [%s] define invalid!", key);
+				sp_dbg_warn("read %s failed! startup list [%s] define invalid!", section_name, key);
 				rc = Error_Param;
 			}
 
@@ -768,12 +852,18 @@ static int shell_init__load_startup_list(sp_cfg_shell_ini_t* shell, const char*
 		}
 	}
 	else {
-		sp_dbg_warn("read Startup failed! startup number invalid!");
+		sp_dbg_warn("read %s failed! startup number invalid!", section_name);
 		rc = Error_Param;
 	}
 
 	return rc;
 }
+*/
+
+static int shell_init__load_startup_list(sp_cfg_shell_ini_t* shell, const char* shell_ini_path)
+{
+	return shell_ini__load_entity_list(shell, &shell->arr_startlist, shell_ini_path, 0);
+}
 
 static inline int shell_ini__load_software_version(sp_cfg_shell_ini_t* shell, const char* shell_ini_path, const char* shell_runinfo_file)
 {
@@ -888,8 +978,20 @@ static int load_shell_ini(sp_dir_t *dir, sp_cfg_shell_ini_t *shell, const sp_cfg
 		if (rc != 0)
 			return rc;
 	}
-	else if ((rc = shell_init__load_startup_list(shell, shell_ini_path)) != 0) {
-		return rc;
+	else {
+		if ((rc = shell_init__load_startup_list(shell, shell_ini_path)) != 0) {
+			return rc;
+		}
+		if (args->test_mode) {
+			array_header_t* arr = NULL;
+			if ((rc = shell_ini__load_entity_list(shell, &arr, shell_ini_path, 1)) != 0)
+				return rc;
+			if (arr && arr->nelts > 0) {
+				sp_dbg_info("append additional test entity: %d", arr->nelts);
+				shm_array_cat(shell->arr_startlist, arr);
+			}
+			shm_array_free(arr);
+		}
 	}
 
 	shell->shell_debug_level = args->debug_mode ? 2 : shell_ini__load_debug_level(shell_ini_path, "SpShell");
@@ -937,6 +1039,8 @@ static int load_shell_ini(sp_dir_t *dir, sp_cfg_shell_ini_t *shell, const sp_cfg
 		}
 	}
 
+	shell->shell_state = (rc == 0) ? 1 /*booting*/: 3 /*breakdown*/;
+
 	return rc;
 }
 

+ 1 - 0
spbase/sp_cfg.h

@@ -128,6 +128,7 @@ struct sp_cfg_shell_ini_t {
 	array_header_t *arr_sysevent;
 	array_header_t *arr_startlist;
 	int shell_debug_level;
+	int shell_state;
 	int nConsolePort;		// console service port
 	char *spbase_sign_cert_hash;
 };

+ 1 - 1
spbase/sp_env.c

@@ -64,7 +64,7 @@ static __inline const char *new_url(char *buf, int tcp_type)
 	return buf;
 }
 
-int sp_env_create(void *hint_addr, int range, sp_cfg_start_args_t* args, sp_env_t **p_env)
+int sp_env_create(void *hint_addr, int range, const sp_cfg_start_args_t* args, sp_env_t **p_env)
 {
 	sp_env_t *env;
 	int rc = Error_Unexpect;

+ 1 - 1
spbase/sp_iom.c

@@ -473,7 +473,7 @@ int sp_iom_send(sp_iom_t *iom, int this_svc_id, int epid, int svc_id, int pkt_ty
 	if (rc != 0)
 		rc = Error_IO;
 
-	sp_dbg_debug("<== sp_iom_send: pkt type: %d, this_svc id: %d, epid:%d, svc id:%d, pkt_id: %d, rc=%d!",
+	sp_dbg_debug("<== sp_iom_send: pkt type: 0x%08X, this_svc id: %d, epid:%d, svc id:%d, pkt_id: %d, rc=%d!",
 		pkt_type, this_svc_id, epid, svc_id, pkt_id, rc);
 	return rc;
 }

+ 13 - 6
spbase/sp_mod.c

@@ -2393,7 +2393,8 @@ int sp_mod_mgr_start_entity2(sp_mod_mgr_t *mgr, sp_entity_t *ent, const char *cm
 
 		unlock_doing(mgr, ent->mod);
 	} else {
-		rc = Error_InvalidState;
+		sp_dbg_warn("mod %s is busy doing now! line: %d", ent->mod->cfg->name, __LINE__);
+		rc = Error_Busy;
 	}
 
 	return rc;
@@ -2425,7 +2426,8 @@ int sp_mod_mgr_stop_entity2(sp_mod_mgr_t *mgr, sp_entity_t *ent, int trigger_ent
 		}
 		unlock_doing(mgr, ent->mod);
 	} else {
-		rc = Error_Unexpect;
+		sp_dbg_warn("mod %s is busy doing now! line: %d", ent->mod->cfg->name, __LINE__);
+		rc = Error_Busy;
 	}
 
 	return rc;
@@ -2442,8 +2444,10 @@ int sp_mod_mgr_terminate_entity2(sp_mod_mgr_t *mgr, sp_entity_t *ent, int trigge
 		rc = terminate_module(mgr, ent->mod, trigger_entity_id);
 		unlock_doing(mgr, ent->mod);
 	} else {
-		rc = Error_InvalidState;
+		sp_dbg_warn("mod %s is busy doing now! line: %d", ent->mod->cfg->name, __LINE__);
+		rc = Error_Busy;
 	}
+
 	return rc;
 }
 
@@ -2458,7 +2462,8 @@ int sp_mod_mgr_pause_entity2(sp_mod_mgr_t *mgr, sp_entity_t *ent, int trigger_en
 		rc = pause_entity(mgr, ent, trigger_entity_id);
 		unlock_doing(mgr, ent->mod);
 	} else {
-		rc = Error_InvalidState;
+		sp_dbg_warn("mod %s is busy doing now! line: %d", ent->mod->cfg->name, __LINE__);
+		rc = Error_Busy;
 	}
 
 	return rc;
@@ -2475,7 +2480,8 @@ int sp_mod_mgr_continue_entity2(sp_mod_mgr_t *mgr, sp_entity_t *ent, int trigger
 		rc = continue_entity(mgr, ent, trigger_entity_id);
 		unlock_doing(mgr, ent->mod);
 	} else {
-		rc = Error_InvalidState;
+		sp_dbg_warn("mod %s is busy doing now! line: %d", ent->mod->cfg->name, __LINE__);
+		rc = Error_Busy;
 	}
 
 	return rc;
@@ -2492,7 +2498,8 @@ int sp_mod_mgr_test_entity2(sp_mod_mgr_t *mgr, sp_entity_t *ent, int trigger_ent
 		rc = test_entity(mgr, ent, test_type, trigger_entity_id);
 		unlock_doing(mgr, ent->mod);
 	} else {
-		rc = Error_InvalidState;
+		sp_dbg_warn("mod %s is busy doing now! line: %d", ent->mod->cfg->name, __LINE__);
+		rc = Error_Busy;
 	}
 
 	return rc;

+ 6 - 1
spshell/app.cpp

@@ -91,13 +91,19 @@ static unsigned int __stdcall __startlist_proc(void *param)
 		sp_dbg_error("======================================================");
 		sp_dbg_error("!!!!!! a few of entities started up failed! please get more detail from dbg\\spshell !!!!!!");
 		sp_dbg_error("======================================================");
+		env->cfg->shell_ini->shell_state = 3/*break down*/;
 		Sleep(10000);
 		app_t *app = get_app_instance();
 		sp_iom_post_quit(app->iom);
 	}
+	else {
+		sp_dbg_info("all boot up entities has been started succ.");
+		env->cfg->shell_ini->shell_state = 2/*running*/;
+	}
 	return 0;
 }
 
+/*! launch limited startup module processes */
 static int kickoff_startlist()
 {
 	HANDLE hTempThread;
@@ -355,7 +361,6 @@ int app_init(const sp_cfg_start_args_t* args)
 	sp_dbg_info("create and start silverlight policy server ok!");
 #endif //_WIN32
 
-	//launch limited startup module processes
 	rc = kickoff_startlist();
 	if (rc != 0) {
 		sp_dbg_error("kickoff startlist thread proc failed!");

+ 24 - 17
spshell/spshell.cpp

@@ -742,13 +742,20 @@ BeforeLeave:
 
 void DisplayUsage()
 {
-	sp_dbg_info("\n");
-	sp_dbg_info("Usage spshell [--entity <entityName>] [--guardian] [--test] [--debug] [--ipc <pipe|tcp>]");
-	sp_dbg_info("  --entity {entityName}               -- 启动指定的实体");
-	sp_dbg_info("  --guardian                              -- 以后台监控形式运行程序");
-	sp_dbg_info("  --test                                      -- 以测试模式运行程序");
-	sp_dbg_info("  --debug                                 -- 以Debug的模式运行程序");
-	sp_dbg_info("  --ipc <pipe,tcp>                     -- pipe: 实体间以管道的方式通信;tcp: 实体间以socket的方式通信\n");
+	char szHelp[1024] = { '\0' };
+	sprintf_s(szHelp, 1024, "\n"
+		"Usage spshell [--entity <entityName>] [--guardian] [--test] [--debug] [--ipc <pipe|tcp>]\n"
+		"  --entity {entityName}               -- 启动指定的实体\n"
+		"  --guardian                                -- 以后台监控形式运行程序\n"
+		"  --test                                        -- 以测试模式运行程序\n"
+		"  --debug                                    -- 以Debug的模式运行程序\n"
+		"  --kill                                          -- 直接杀死程序相关进程\n"
+		"  --ipc <pipe,tcp>                      -- pipe: 实体间以管道的方式通信;tcp: 实体间以socket的方式通信\n"
+	);
+	sp_dbg_info(szHelp);
+#ifdef _WIN32
+	MessageBoxA(NULL, szHelp, "Spshell Usage Tip", MB_OK);
+#endif //_WIN32
 }
 
 sp_cfg_start_args_t* DealWithArgs(int argc, char** argv)
@@ -766,14 +773,14 @@ sp_cfg_start_args_t* DealWithArgs(int argc, char** argv)
 		{"debug", no_argument, 0, 'D'},
 		{"ipc", required_argument, 0, 'I'},
 		{"shutdown", no_argument, 0, 'S'},
-		{"kill", required_argument, 0, 'K'},
+		{"kill", no_argument, 0, 'K'},
 		{"help", no_argument, 0, 'H'},
 		{0, 0, 0, 0}
 	};
 
 	int spshell_index = 0;
 	int c;
-	while ((c = getopt_long(argc, argv, "E:GTDI:", spshell_options, &spshell_index)) != EOF) {
+	while ((c = getopt_long(argc, argv, "E:GTDI:?", spshell_options, &spshell_index)) != EOF) {
 		switch (c) {
 		case 'E':
 		{
@@ -827,6 +834,14 @@ sp_cfg_start_args_t* DealWithArgs(int argc, char** argv)
 					args->ipc_type = 1;
 			}
 			break;
+		case 'K':
+		{
+			sp_dbg_info("terminate spshell!");
+			char* relate_processes[] = { "spshell.exe", "sphost.exe", "guardian.exe" };
+			osutil_terminate_related_process(relate_processes, sizeof(relate_processes) / sizeof(relate_processes[0]));
+			exit(0);
+		}
+		break;
 		case 'H':
 		case '?':
 		default:
@@ -897,20 +912,12 @@ int main(int argc, char** argv)
 
 #ifdef _WIN32
 
-	//卸载Dll驱动,加快启动速度
-	/*bool bRet = UnloadInterceptDllDriver(DRIVER_NAME);
-	if (!bRet)
-	{
-	sp_dbg_info("卸载Dll监控驱动失败!!!");
-	}*/
-
 	// 设置防火墙注册表配置
 	AddFirewallRulesEx();
 
 	// 自动隐藏状态栏
 	//AutoHideTaskBar(true);
 
-
 #endif //_WIN32
 	
 #ifdef _WIN32

+ 5 - 3
spshell/svc.cpp

@@ -5,6 +5,7 @@
 #include "app.h"
 
 #include "SpBase.h"
+#include "SpHelper.h"
 #include "sp_btr.h"
 #include "sp_gui.h"
 #include "sp_dbg_export.h"
@@ -124,14 +125,15 @@ void on_machine_reboot(sp_rpc_server_t *server, int epid, int svc_id, int call_t
 	sp_cfg_t *cfg = env->cfg;
 	iobuffer_read(*info_pkt, IOBUF_T_I4, &reason, 0);
 	iobuffer_read(*info_pkt, IOBUF_T_I4, &way, 0);
-	Dbg("now reboot: reason = %d, way = %d", reason, way);
+	const RebootWayEnum eRebootWay = (RebootWayEnum)way;
+	const RebootTriggerEnum eRebootTrigger = (RebootTriggerEnum)reason;
+
+	Dbg("now reboot: reason = %s, way = %s", SpStrRebootTrigger(eRebootTrigger), SpStrRebootWay(eRebootWay));
 
 	CSimpleStringA strPath = env->dir->root_runinfo_path;
 	strPath += SPLIT_SLASH_STR "BootLog";
 	sp_btr_write_on_shutdown(strPath, env->btr_ctx, reason, way);
 
-	const RebootWayEnum eRebootWay = (RebootWayEnum)way;
-	const RebootTriggerEnum eRebootTrigger = (RebootTriggerEnum)reason;
 	// 只处理框架重启及操作系统重启,电源重启由健康实体处理
 	if (eRebootWay == RebootWay_Framework && eRebootTrigger != RebootTrigger_DeadForever)
 	{