diff options
Diffstat (limited to 'src/balutil/balretry.cpp')
-rw-r--r-- | src/balutil/balretry.cpp | 223 |
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 | ||
5 | typedef enum BALRETRY_TYPE | ||
6 | { | ||
7 | BALRETRY_TYPE_CACHE_CONTAINER, | ||
8 | BALRETRY_TYPE_CACHE_PAYLOAD, | ||
9 | BALRETRY_TYPE_EXECUTE, | ||
10 | } BALRETRY_TYPE; | ||
11 | |||
5 | struct BALRETRY_INFO | 12 | struct 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 | ||
13 | static DWORD vdwMaxRetries = 0; | 19 | static DWORD vdwMaxRetries = 0; |
14 | static DWORD vdwTimeout = 0; | 20 | static DWORD vdwTimeout = 0; |
15 | static BALRETRY_INFO vrgRetryInfo[2]; | 21 | static BALRETRY_INFO vrgRetryInfo[3]; |
16 | 22 | ||
17 | // prototypes | 23 | // prototypes |
18 | static BOOL IsActiveRetryEntry( | 24 | static 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 | |||
29 | static 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 | ||
51 | DAPI_(void) BalRetryStartPackage( | 60 | DAPI_(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 | |
81 | DAPI_(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 | |||
101 | DAPI_(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 | |||
141 | LExit: | ||
142 | return hr; | ||
95 | } | 143 | } |
96 | 144 | ||
97 | 145 | ||
98 | DAPI_(HRESULT) BalRetryEndPackage( | 146 | DAPI_(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 | ||
176 | static BOOL IsActiveRetryEntry( | 208 | static 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 | |||
220 | static 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 | } |