| 1269 | } |
| 1270 | |
| 1271 | bool CryptoManager::write(thread_db* tdbb, FbStatusVector* sv, Ods::pag* page, IOCallback* io) |
| 1272 | { |
| 1273 | // Code calling us is not ready to process exceptions correctly |
| 1274 | // Therefore use old (status vector based) method |
| 1275 | try |
| 1276 | { |
| 1277 | // Sanity check |
| 1278 | if (page->pag_type > pag_max) |
| 1279 | Arg::Gds(isc_page_type_err).raise(); |
| 1280 | |
| 1281 | // Page is never going to be encrypted. No locks needed. |
| 1282 | if (!Ods::pag_crypt_page[page->pag_type]) |
| 1283 | return internalWrite(tdbb, sv, page, io) == SUCCESS_ALL; |
| 1284 | |
| 1285 | // Normal case (almost always get here) |
| 1286 | // Take shared lock on crypto manager and write data |
| 1287 | if (!slowIO) |
| 1288 | { |
| 1289 | BarSync::IoGuard ioGuard(tdbb, sync); |
| 1290 | if (!slowIO) |
| 1291 | return internalWrite(tdbb, sv, page, io) == SUCCESS_ALL; |
| 1292 | } |
| 1293 | |
| 1294 | // Have to use slow method - see full comments in read() function |
| 1295 | BarSync::LockGuard lockGuard(tdbb, sync); |
| 1296 | lockGuard.lock(); |
| 1297 | for (SINT64 previous = slowIO; ; previous = slowIO) |
| 1298 | { |
| 1299 | switch (internalWrite(tdbb, sv, page, io)) |
| 1300 | { |
| 1301 | case SUCCESS_ALL: |
| 1302 | if (!slowIO) |
| 1303 | return true; |
| 1304 | |
| 1305 | lockAndReadHeader(tdbb, CRYPT_HDR_NOWAIT); |
| 1306 | if (slowIO == previous) |
| 1307 | return true; |
| 1308 | break; |
| 1309 | |
| 1310 | case FAILED_IO: |
| 1311 | return false; |
| 1312 | |
| 1313 | case FAILED_CRYPT: |
| 1314 | if (!slowIO) |
| 1315 | return false; |
| 1316 | |
| 1317 | lockAndReadHeader(tdbb, CRYPT_HDR_NOWAIT); |
| 1318 | if (slowIO == previous) |
| 1319 | return false; |
| 1320 | break; |
| 1321 | } |
| 1322 | } |
| 1323 | } |
| 1324 | catch (const Exception& ex) |
| 1325 | { |
| 1326 | ex.stuffException(sv); |
| 1327 | } |
| 1328 | return false; |
no test coverage detected