aboutsummaryrefslogtreecommitdiff
path: root/src/balutil/balretry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/balutil/balretry.cpp')
-rw-r--r--src/balutil/balretry.cpp223
1 files changed, 139 insertions, 84 deletions
diff --git a/src/balutil/balretry.cpp b/src/balutil/balretry.cpp
index d95d86b2..9d8abd6d 100644
--- a/src/balutil/balretry.cpp
+++ b/src/balutil/balretry.cpp
@@ -2,23 +2,33 @@
2 2
3#include "precomp.h" 3#include "precomp.h"
4 4
5typedef enum BALRETRY_TYPE
6{
7 BALRETRY_TYPE_CACHE_CONTAINER,
8 BALRETRY_TYPE_CACHE_PAYLOAD,
9 BALRETRY_TYPE_EXECUTE,
10} BALRETRY_TYPE;
11
5struct BALRETRY_INFO 12struct BALRETRY_INFO
6{ 13{
7 LPWSTR sczId; // package or container id. 14 LPWSTR sczId;
8 LPWSTR sczPayloadId; // optional payload id.
9 DWORD cRetries; 15 DWORD cRetries;
10 DWORD dwLastError; 16 DWORD dwLastError;
11}; 17};
12 18
13static DWORD vdwMaxRetries = 0; 19static DWORD vdwMaxRetries = 0;
14static DWORD vdwTimeout = 0; 20static DWORD vdwTimeout = 0;
15static BALRETRY_INFO vrgRetryInfo[2]; 21static BALRETRY_INFO vrgRetryInfo[3];
16 22
17// prototypes 23// prototypes
18static BOOL IsActiveRetryEntry( 24static BOOL IsActiveRetryEntry(
19 __in BALRETRY_TYPE type, 25 __in BALRETRY_TYPE type,
20 __in_z LPCWSTR wzPackageId, 26 __in_z LPCWSTR sczId
21 __in_z_opt LPCWSTR wzPayloadId 27 );
28
29static HRESULT StartActiveRetryEntry(
30 __in BALRETRY_TYPE type,
31 __in_z LPCWSTR sczId
22 ); 32 );
23 33
24 34
@@ -39,7 +49,6 @@ DAPI_(void) BalRetryUninitialize()
39 for (DWORD i = 0; i < countof(vrgRetryInfo); ++i) 49 for (DWORD i = 0; i < countof(vrgRetryInfo); ++i)
40 { 50 {
41 ReleaseStr(vrgRetryInfo[i].sczId); 51 ReleaseStr(vrgRetryInfo[i].sczId);
42 ReleaseStr(vrgRetryInfo[i].sczPayloadId);
43 memset(vrgRetryInfo + i, 0, sizeof(BALRETRY_INFO)); 52 memset(vrgRetryInfo + i, 0, sizeof(BALRETRY_INFO));
44 } 53 }
45 54
@@ -48,34 +57,32 @@ DAPI_(void) BalRetryUninitialize()
48} 57}
49 58
50 59
51DAPI_(void) BalRetryStartPackage( 60DAPI_(void) BalRetryStartContainerOrPayload(
52 __in BALRETRY_TYPE type, 61 __in_z_opt LPCWSTR wzContainerOrPackageId,
53 __in_z_opt LPCWSTR wzPackageId,
54 __in_z_opt LPCWSTR wzPayloadId 62 __in_z_opt LPCWSTR wzPayloadId
55 ) 63 )
56{ 64{
57 if (!wzPackageId || !*wzPackageId) 65 if (!wzContainerOrPackageId && !wzPayloadId)
58 { 66 {
59 ReleaseNullStr(vrgRetryInfo[type].sczId); 67 ReleaseNullStr(vrgRetryInfo[BALRETRY_TYPE_CACHE_CONTAINER].sczId);
60 ReleaseNullStr(vrgRetryInfo[type].sczPayloadId); 68 ReleaseNullStr(vrgRetryInfo[BALRETRY_TYPE_CACHE_PAYLOAD].sczId);
61 } 69 }
62 else if (IsActiveRetryEntry(type, wzPackageId, wzPayloadId)) 70 else if (wzPayloadId)
63 { 71 {
64 ++vrgRetryInfo[type].cRetries; 72 StartActiveRetryEntry(BALRETRY_TYPE_CACHE_PAYLOAD, wzPayloadId);
65 ::Sleep(vdwTimeout);
66 } 73 }
67 else 74 else
68 { 75 {
69 StrAllocString(&vrgRetryInfo[type].sczId, wzPackageId, 0); 76 StartActiveRetryEntry(BALRETRY_TYPE_CACHE_CONTAINER, wzContainerOrPackageId);
70 if (wzPayloadId)
71 {
72 StrAllocString(&vrgRetryInfo[type].sczPayloadId, wzPayloadId, 0);
73 }
74
75 vrgRetryInfo[type].cRetries = 0;
76 } 77 }
78}
77 79
78 vrgRetryInfo[type].dwLastError = ERROR_SUCCESS; 80
81DAPI_(void) BalRetryStartPackage(
82 __in_z LPCWSTR wzPackageId
83 )
84{
85 StartActiveRetryEntry(BALRETRY_TYPE_EXECUTE, wzPackageId);
79} 86}
80 87
81 88
@@ -84,87 +91,112 @@ DAPI_(void) BalRetryErrorOccurred(
84 __in DWORD dwError 91 __in DWORD dwError
85 ) 92 )
86{ 93{
87 if (IsActiveRetryEntry(BALRETRY_TYPE_CACHE, wzPackageId, NULL)) 94 if (IsActiveRetryEntry(BALRETRY_TYPE_EXECUTE, wzPackageId))
88 { 95 {
89 vrgRetryInfo[BALRETRY_TYPE_CACHE].dwLastError = dwError; 96 vrgRetryInfo[BALRETRY_TYPE_EXECUTE].dwLastError = dwError;
90 } 97 }
91 else if (IsActiveRetryEntry(BALRETRY_TYPE_EXECUTE, wzPackageId, NULL)) 98}
99
100
101DAPI_(HRESULT) BalRetryEndContainerOrPayload(
102 __in_z_opt LPCWSTR wzContainerOrPackageId,
103 __in_z_opt LPCWSTR wzPayloadId,
104 __in HRESULT hrError,
105 __inout BOOL* pfRetry
106 )
107{
108 HRESULT hr = S_OK;
109 BALRETRY_TYPE type = BALRETRY_TYPE_CACHE_PAYLOAD;
110 LPCWSTR wzId = NULL;
111
112 if (!wzContainerOrPackageId && !wzPayloadId)
92 { 113 {
93 vrgRetryInfo[BALRETRY_TYPE_EXECUTE].dwLastError = dwError; 114 ReleaseNullStr(vrgRetryInfo[BALRETRY_TYPE_CACHE_CONTAINER].sczId);
115 ReleaseNullStr(vrgRetryInfo[BALRETRY_TYPE_CACHE_PAYLOAD].sczId);
116 ExitFunction();
117 }
118 else if (wzPayloadId)
119 {
120 type = BALRETRY_TYPE_CACHE_PAYLOAD;
121 wzId = wzPayloadId;
122 }
123 else
124 {
125 type = BALRETRY_TYPE_CACHE_CONTAINER;
126 wzId = wzContainerOrPackageId;
94 } 127 }
128
129 if (FAILED(hrError) && vrgRetryInfo[type].cRetries < vdwMaxRetries && IsActiveRetryEntry(type, wzId))
130 {
131 // Retry on all errors except the following.
132 if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) != hrError &&
133 BG_E_NETWORK_DISCONNECTED != hrError &&
134 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrError &&
135 HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED) != hrError)
136 {
137 *pfRetry = TRUE;
138 }
139 }
140
141LExit:
142 return hr;
95} 143}
96 144
97 145
98DAPI_(HRESULT) BalRetryEndPackage( 146DAPI_(HRESULT) BalRetryEndPackage(
99 __in BALRETRY_TYPE type, 147 __in_z LPCWSTR wzPackageId,
100 __in_z_opt LPCWSTR wzPackageId,
101 __in_z_opt LPCWSTR wzPayloadId,
102 __in HRESULT hrError, 148 __in HRESULT hrError,
103 __inout BOOL* pfRetry 149 __inout BOOL* pfRetry
104 ) 150 )
105{ 151{
106 HRESULT hr = S_OK; 152 HRESULT hr = S_OK;
153 BALRETRY_TYPE type = BALRETRY_TYPE_EXECUTE;
107 154
108 if (!wzPackageId || !*wzPackageId) 155 if (!wzPackageId || !*wzPackageId)
109 { 156 {
110 ReleaseNullStr(vrgRetryInfo[type].sczId); 157 ReleaseNullStr(vrgRetryInfo[type].sczId);
111 ReleaseNullStr(vrgRetryInfo[type].sczPayloadId);
112 } 158 }
113 else if (FAILED(hrError) && vrgRetryInfo[type].cRetries < vdwMaxRetries && IsActiveRetryEntry(type, wzPackageId, wzPayloadId)) 159 else if (FAILED(hrError) && vrgRetryInfo[type].cRetries < vdwMaxRetries && IsActiveRetryEntry(type, wzPackageId))
114 { 160 {
115 if (BALRETRY_TYPE_CACHE == type) 161 // If the service is out of whack, just try again.
162 if (HRESULT_FROM_WIN32(ERROR_INSTALL_SERVICE_FAILURE) == hrError)
116 { 163 {
117 // Retry on all errors except the following. 164 *pfRetry = TRUE;
118 if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) != hrError &&
119 BG_E_NETWORK_DISCONNECTED != hrError &&
120 HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrError &&
121 HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED) != hrError)
122 {
123 *pfRetry = TRUE;
124 }
125 } 165 }
126 else if (BALRETRY_TYPE_EXECUTE == type) 166 else if (HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE) == hrError)
127 { 167 {
128 // If the service is out of whack, just try again. 168 DWORD dwError = vrgRetryInfo[type].dwLastError;
129 if (HRESULT_FROM_WIN32(ERROR_INSTALL_SERVICE_FAILURE) == hrError) 169
130 { 170 // If we failed with one of these specific error codes, then retry since
131 *pfRetry = TRUE; 171 // we've seen these have a high success of succeeding on retry.
132 } 172 if (1303 == dwError ||
133 else if (HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE) == hrError) 173 1304 == dwError ||
134 { 174 1306 == dwError ||
135 DWORD dwError = vrgRetryInfo[type].dwLastError; 175 1307 == dwError ||
136 176 1309 == dwError ||
137 // If we failed with one of these specific error codes, then retry since 177 1310 == dwError ||
138 // we've seen these have a high success of succeeding on retry. 178 1311 == dwError ||
139 if (1303 == dwError || 179 1312 == dwError ||
140 1304 == dwError || 180 1316 == dwError ||
141 1306 == dwError || 181 1317 == dwError ||
142 1307 == dwError || 182 1321 == dwError ||
143 1309 == dwError || 183 1335 == dwError ||
144 1310 == dwError || 184 1402 == dwError ||
145 1311 == dwError || 185 1406 == dwError ||
146 1312 == dwError || 186 1606 == dwError ||
147 1316 == dwError || 187 1706 == dwError ||
148 1317 == dwError || 188 1719 == dwError ||
149 1321 == dwError || 189 1723 == dwError ||
150 1335 == dwError || 190 1923 == dwError ||
151 1402 == dwError || 191 1931 == dwError)
152 1406 == dwError ||
153 1606 == dwError ||
154 1706 == dwError ||
155 1719 == dwError ||
156 1723 == dwError ||
157 1923 == dwError ||
158 1931 == dwError)
159 {
160 *pfRetry = TRUE;
161 }
162 }
163 else if (HRESULT_FROM_WIN32(ERROR_INSTALL_ALREADY_RUNNING) == hrError)
164 { 192 {
165 *pfRetry = TRUE; 193 *pfRetry = TRUE;
166 } 194 }
167 } 195 }
196 else if (HRESULT_FROM_WIN32(ERROR_INSTALL_ALREADY_RUNNING) == hrError)
197 {
198 *pfRetry = TRUE;
199 }
168 } 200 }
169 201
170 return hr; 202 return hr;
@@ -175,17 +207,40 @@ DAPI_(HRESULT) BalRetryEndPackage(
175 207
176static BOOL IsActiveRetryEntry( 208static BOOL IsActiveRetryEntry(
177 __in BALRETRY_TYPE type, 209 __in BALRETRY_TYPE type,
178 __in_z LPCWSTR wzPackageId, 210 __in_z LPCWSTR sczId
179 __in_z_opt LPCWSTR wzPayloadId
180 ) 211 )
181{ 212{
182 BOOL fActive = FALSE; 213 BOOL fActive = FALSE;
183 214
184 fActive = vrgRetryInfo[type].sczId && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, vrgRetryInfo[type].sczId, -1); 215 fActive = vrgRetryInfo[type].sczId && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczId, -1, vrgRetryInfo[type].sczId, -1);
185 if (fActive && wzPayloadId) // if a payload id was provided ensure it matches. 216
217 return fActive;
218}
219
220static HRESULT StartActiveRetryEntry(
221 __in BALRETRY_TYPE type,
222 __in_z LPCWSTR sczId
223 )
224{
225 HRESULT hr = S_OK;
226
227 if (!sczId || !*sczId)
186 { 228 {
187 fActive = vrgRetryInfo[type].sczPayloadId && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPayloadId, -1, vrgRetryInfo[type].sczPayloadId, -1); 229 ReleaseNullStr(vrgRetryInfo[type].sczId);
188 } 230 }
231 else if (IsActiveRetryEntry(type, sczId))
232 {
233 ++vrgRetryInfo[type].cRetries;
234 ::Sleep(vdwTimeout);
235 }
236 else
237 {
238 hr = StrAllocString(&vrgRetryInfo[type].sczId, sczId, 0);
189 239
190 return fActive; 240 vrgRetryInfo[type].cRetries = 0;
241 }
242
243 vrgRetryInfo[type].dwLastError = ERROR_SUCCESS;
244
245 return hr;
191} 246}