Commit b54d2f75d611f67ef449fc6ce292e01e96ca08a0
Merge pull request #334 from biometrics/bytearray_serialization
Explicit bytearray serialization
Showing
2 changed files
with
79 additions
and
28 deletions
openbr/core/qtutils.cpp
| @@ -500,14 +500,15 @@ QString getAbsolutePath(const QString &filename) | @@ -500,14 +500,15 @@ QString getAbsolutePath(const QString &filename) | ||
| 500 | return QFileInfo(filename).absoluteFilePath(); | 500 | return QFileInfo(filename).absoluteFilePath(); |
| 501 | } | 501 | } |
| 502 | 502 | ||
| 503 | +const int base_block = 100000000; | ||
| 504 | + | ||
| 503 | BlockCompression::BlockCompression(QIODevice *_basis) | 505 | BlockCompression::BlockCompression(QIODevice *_basis) |
| 504 | { | 506 | { |
| 505 | - blockSize = 100000000; | 507 | + blockSize = base_block; |
| 506 | setBasis(_basis); | 508 | setBasis(_basis); |
| 507 | } | 509 | } |
| 508 | 510 | ||
| 509 | -BlockCompression::BlockCompression() { blockSize = 100000000; }; | ||
| 510 | - | 511 | +BlockCompression::BlockCompression() { blockSize = base_block;}; |
| 511 | 512 | ||
| 512 | bool BlockCompression::open(QIODevice::OpenMode mode) | 513 | bool BlockCompression::open(QIODevice::OpenMode mode) |
| 513 | { | 514 | { |
| @@ -521,14 +522,22 @@ bool BlockCompression::open(QIODevice::OpenMode mode) | @@ -521,14 +522,22 @@ bool BlockCompression::open(QIODevice::OpenMode mode) | ||
| 521 | blockWriter.setDevice(basis); | 522 | blockWriter.setDevice(basis); |
| 522 | 523 | ||
| 523 | if (mode & QIODevice::WriteOnly) { | 524 | if (mode & QIODevice::WriteOnly) { |
| 524 | - precompressedBlockWriter = new QBuffer; | ||
| 525 | - precompressedBlockWriter->open(QIODevice::ReadWrite); | 525 | + precompressedBlockWriter.open(QIODevice::WriteOnly); |
| 526 | } | 526 | } |
| 527 | else if (mode & QIODevice::ReadOnly) { | 527 | else if (mode & QIODevice::ReadOnly) { |
| 528 | + | ||
| 529 | + // Read an initial compressed block from the underlying QIODevice, | ||
| 530 | + // decompress, and set up a reader on it | ||
| 528 | QByteArray compressedBlock; | 531 | QByteArray compressedBlock; |
| 529 | - blockReader >> compressedBlock; | 532 | + quint32 block_size; |
| 533 | + blockReader >> block_size; | ||
| 534 | + compressedBlock.resize(block_size); | ||
| 535 | + int read_count = blockReader.readRawData(compressedBlock.data(), block_size); | ||
| 536 | + if (read_count != block_size) | ||
| 537 | + qFatal("Failed to read initial block"); | ||
| 530 | 538 | ||
| 531 | decompressedBlock = qUncompress(compressedBlock); | 539 | decompressedBlock = qUncompress(compressedBlock); |
| 540 | + | ||
| 532 | decompressedBlockReader.setBuffer(&decompressedBlock); | 541 | decompressedBlockReader.setBuffer(&decompressedBlock); |
| 533 | decompressedBlockReader.open(QIODevice::ReadOnly); | 542 | decompressedBlockReader.open(QIODevice::ReadOnly); |
| 534 | } | 543 | } |
| @@ -538,11 +547,17 @@ bool BlockCompression::open(QIODevice::OpenMode mode) | @@ -538,11 +547,17 @@ bool BlockCompression::open(QIODevice::OpenMode mode) | ||
| 538 | 547 | ||
| 539 | void BlockCompression::close() | 548 | void BlockCompression::close() |
| 540 | { | 549 | { |
| 541 | - // flush output buffer | ||
| 542 | - if ((openMode() & QIODevice::WriteOnly) && precompressedBlockWriter) { | ||
| 543 | - QByteArray compressedBlock = qCompress(precompressedBlockWriter->buffer(), -1); | ||
| 544 | - blockWriter << compressedBlock; | 550 | + // flush output buffer, since we may have a partial block which hasn't been |
| 551 | + // written to disk yet. | ||
| 552 | + if ((openMode() & QIODevice::WriteOnly) && precompressedBlockWriter.isOpen()) { | ||
| 553 | + QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer()); | ||
| 554 | + precompressedBlockWriter.close(); | ||
| 555 | + | ||
| 556 | + quint32 bsize= compressedBlock.size(); | ||
| 557 | + blockWriter << bsize; | ||
| 558 | + blockWriter.writeRawData(compressedBlock.data(), compressedBlock.size()); | ||
| 545 | } | 559 | } |
| 560 | + // close the underlying device. | ||
| 546 | basis->close(); | 561 | basis->close(); |
| 547 | } | 562 | } |
| 548 | 563 | ||
| @@ -557,8 +572,10 @@ void BlockCompression::setBasis(QIODevice *_basis) | @@ -557,8 +572,10 @@ void BlockCompression::setBasis(QIODevice *_basis) | ||
| 557 | // block from basis | 572 | // block from basis |
| 558 | qint64 BlockCompression::readData(char *data, qint64 remaining) | 573 | qint64 BlockCompression::readData(char *data, qint64 remaining) |
| 559 | { | 574 | { |
| 575 | + qint64 initial = remaining; | ||
| 560 | qint64 read = 0; | 576 | qint64 read = 0; |
| 561 | while (remaining > 0) { | 577 | while (remaining > 0) { |
| 578 | + // attempt to read the target amount of data | ||
| 562 | qint64 single_read = decompressedBlockReader.read(data, remaining); | 579 | qint64 single_read = decompressedBlockReader.read(data, remaining); |
| 563 | if (single_read == -1) | 580 | if (single_read == -1) |
| 564 | qFatal("miss read"); | 581 | qFatal("miss read"); |
| @@ -567,13 +584,21 @@ qint64 BlockCompression::readData(char *data, qint64 remaining) | @@ -567,13 +584,21 @@ qint64 BlockCompression::readData(char *data, qint64 remaining) | ||
| 567 | read += single_read; | 584 | read += single_read; |
| 568 | data += single_read; | 585 | data += single_read; |
| 569 | 586 | ||
| 570 | - // need a new block | 587 | + // need a new block if we didn't get enough bytes from the previous read |
| 571 | if (remaining > 0) { | 588 | if (remaining > 0) { |
| 572 | QByteArray compressedBlock; | 589 | QByteArray compressedBlock; |
| 573 | - blockReader >> compressedBlock; | ||
| 574 | - if (compressedBlock.size() == 0) { | ||
| 575 | - return read; | ||
| 576 | - } | 590 | + |
| 591 | + // read the size of the next block | ||
| 592 | + quint32 block_size; | ||
| 593 | + blockReader >> block_size; | ||
| 594 | + if (block_size == 0) | ||
| 595 | + break; | ||
| 596 | + | ||
| 597 | + compressedBlock.resize(block_size); | ||
| 598 | + int actualRead = blockReader.readRawData(compressedBlock.data(), block_size); | ||
| 599 | + if (actualRead != block_size) | ||
| 600 | + qFatal("Bad read on nominal block size: %d, only got %d", block_size, remaining); | ||
| 601 | + | ||
| 577 | decompressedBlock = qUncompress(compressedBlock); | 602 | decompressedBlock = qUncompress(compressedBlock); |
| 578 | 603 | ||
| 579 | decompressedBlockReader.close(); | 604 | decompressedBlockReader.close(); |
| @@ -581,7 +606,12 @@ qint64 BlockCompression::readData(char *data, qint64 remaining) | @@ -581,7 +606,12 @@ qint64 BlockCompression::readData(char *data, qint64 remaining) | ||
| 581 | decompressedBlockReader.open(QIODevice::ReadOnly); | 606 | decompressedBlockReader.open(QIODevice::ReadOnly); |
| 582 | } | 607 | } |
| 583 | } | 608 | } |
| 584 | - return blockReader.atEnd() && !basis->isReadable() ? -1 : read; | 609 | + |
| 610 | + bool condition = blockReader.atEnd() && !basis->isReadable() ; | ||
| 611 | + if (condition) | ||
| 612 | + qWarning("Returning -1 from read"); | ||
| 613 | + | ||
| 614 | + return condition ? -1 : read; | ||
| 585 | } | 615 | } |
| 586 | 616 | ||
| 587 | bool BlockCompression::isSequential() const | 617 | bool BlockCompression::isSequential() const |
| @@ -591,36 +621,57 @@ bool BlockCompression::isSequential() const | @@ -591,36 +621,57 @@ bool BlockCompression::isSequential() const | ||
| 591 | 621 | ||
| 592 | qint64 BlockCompression::writeData(const char *data, qint64 remaining) | 622 | qint64 BlockCompression::writeData(const char *data, qint64 remaining) |
| 593 | { | 623 | { |
| 624 | + const char * endPoint = data + remaining; | ||
| 625 | + qint64 initial = remaining; | ||
| 626 | + | ||
| 594 | qint64 written = 0; | 627 | qint64 written = 0; |
| 595 | 628 | ||
| 596 | while (remaining > 0) { | 629 | while (remaining > 0) { |
| 597 | // how much more can be put in this buffer? | 630 | // how much more can be put in this buffer? |
| 598 | - qint64 capacity = blockSize - precompressedBlockWriter->pos(); | 631 | + qint64 capacity = blockSize - precompressedBlockWriter.pos(); |
| 632 | + if (capacity < 0) | ||
| 633 | + qFatal("Negative capacity!!!"); | ||
| 599 | 634 | ||
| 600 | // don't try to write beyond capacity | 635 | // don't try to write beyond capacity |
| 601 | qint64 write_size = qMin(capacity, remaining); | 636 | qint64 write_size = qMin(capacity, remaining); |
| 602 | 637 | ||
| 603 | - qint64 singleWrite = precompressedBlockWriter->write(data, write_size); | ||
| 604 | - // ignore the error case here, we consdier basis's failure mode the real | ||
| 605 | - // end case | 638 | + qint64 singleWrite = precompressedBlockWriter.write(data, write_size); |
| 639 | + | ||
| 606 | if (singleWrite == -1) | 640 | if (singleWrite == -1) |
| 607 | - singleWrite = 0; | 641 | + qFatal("matrix write failure?"); |
| 608 | 642 | ||
| 609 | remaining -= singleWrite; | 643 | remaining -= singleWrite; |
| 610 | data += singleWrite; | 644 | data += singleWrite; |
| 611 | written += singleWrite; | 645 | written += singleWrite; |
| 646 | + if (data > endPoint) | ||
| 647 | + qFatal("Wrote past the end"); | ||
| 612 | 648 | ||
| 613 | if (remaining > 0) { | 649 | if (remaining > 0) { |
| 614 | - QByteArray compressedBlock = qCompress(precompressedBlockWriter->buffer(), -1); | 650 | + QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer(), -1); |
| 615 | 651 | ||
| 616 | - if (compressedBlock.size() != 0) | ||
| 617 | - blockWriter << compressedBlock; | 652 | + if (precompressedBlockWriter.buffer().size() != 0) { |
| 653 | + quint32 block_size = compressedBlock.size(); | ||
| 654 | + blockWriter << block_size; | ||
| 618 | 655 | ||
| 619 | - delete precompressedBlockWriter; | ||
| 620 | - precompressedBlockWriter = new QBuffer; | ||
| 621 | - precompressedBlockWriter->open(QIODevice::ReadWrite); | 656 | + int write_count = blockWriter.writeRawData(compressedBlock.data(), block_size); |
| 657 | + if (write_count != block_size) | ||
| 658 | + qFatal("Didn't write enough data"); | ||
| 659 | + } | ||
| 660 | + else | ||
| 661 | + qFatal("serialized empty compressed block (?)"); | ||
| 662 | + | ||
| 663 | + precompressedBlockWriter.close(); | ||
| 664 | + precompressedBlockWriter.open(QIODevice::WriteOnly); | ||
| 622 | } | 665 | } |
| 623 | } | 666 | } |
| 667 | + | ||
| 668 | + if (written != initial) | ||
| 669 | + qFatal("didn't write enough bytes"); | ||
| 670 | + | ||
| 671 | + bool condition = basis->isWritable(); | ||
| 672 | + if (!condition) | ||
| 673 | + qWarning("Returning -1 from write"); | ||
| 674 | + | ||
| 624 | return basis->isWritable() ? written : -1; | 675 | return basis->isWritable() ? written : -1; |
| 625 | } | 676 | } |
| 626 | 677 |
openbr/core/qtutils.h
| @@ -122,7 +122,7 @@ namespace QtUtils | @@ -122,7 +122,7 @@ namespace QtUtils | ||
| 122 | 122 | ||
| 123 | // write to a QByteArray, when max block sized is reached, compress and write | 123 | // write to a QByteArray, when max block sized is reached, compress and write |
| 124 | // it to basis | 124 | // it to basis |
| 125 | - QBuffer * precompressedBlockWriter; | 125 | + QBuffer precompressedBlockWriter; |
| 126 | QDataStream blockWriter; | 126 | QDataStream blockWriter; |
| 127 | qint64 writeData(const char *data, qint64 remaining); | 127 | qint64 writeData(const char *data, qint64 remaining); |
| 128 | }; | 128 | }; |