| 854 | |
| 855 | // Write item to the next position in the current page or, if it won't fit, add a new page and write it there. |
| 856 | ACTOR static Future<Void> write_impl(Cursor* self, T item) { |
| 857 | ASSERT(self->mode == WRITE); |
| 858 | |
| 859 | state FlowMutex::Lock lock; |
| 860 | state bool mustWait = self->isBusy(); |
| 861 | state int bytesNeeded = Codec::bytesNeeded(item); |
| 862 | state bool needNewPage = |
| 863 | self->pageID == invalidPhysicalPageID || self->offset + bytesNeeded > self->header()->itemSpace; |
| 864 | |
| 865 | if (g_network->isSimulated()) { |
| 866 | // Sometimes (1% probability) decide a new page is needed as long as at least 1 item has been |
| 867 | // written (indicated by non-zero offset) to the current page. |
| 868 | if ((self->offset > 0) && deterministicRandom()->random01() < 0.01) { |
| 869 | needNewPage = true; |
| 870 | } |
| 871 | } |
| 872 | |
| 873 | debug_printf("FIFOQueue::Cursor(%s) write(%s) mustWait=%d needNewPage=%d\n", |
| 874 | self->toString().c_str(), |
| 875 | ::toString(item).c_str(), |
| 876 | mustWait, |
| 877 | needNewPage); |
| 878 | |
| 879 | // If we have to wait for the mutex because it's busy, or we need a new page, then wait for the mutex. |
| 880 | if (mustWait || needNewPage) { |
| 881 | FlowMutex::Lock _lock = wait(self->mutex.take()); |
| 882 | lock = _lock; |
| 883 | |
| 884 | // If we had to wait because the mutex was busy, then update needNewPage as another writer |
| 885 | // would have changed the cursor state |
| 886 | // Otherwise, taking the mutex would be immediate so no other writer could have run |
| 887 | if (mustWait) { |
| 888 | needNewPage = |
| 889 | self->pageID == invalidPhysicalPageID || self->offset + bytesNeeded > self->header()->itemSpace; |
| 890 | if (g_network->isSimulated()) { |
| 891 | // Sometimes (1% probability) decide a new page is needed as long as at least 1 item has been |
| 892 | // written (indicated by non-zero offset) to the current page. |
| 893 | if ((self->offset > 0) && deterministicRandom()->random01() < 0.01) { |
| 894 | needNewPage = true; |
| 895 | } |
| 896 | } |
| 897 | } |
| 898 | } |
| 899 | |
| 900 | // If we need a new page, add one. |
| 901 | if (needNewPage) { |
| 902 | debug_printf("FIFOQueue::Cursor(%s) write(%s) page is full, adding new page\n", |
| 903 | self->toString().c_str(), |
| 904 | ::toString(item).c_str()); |
| 905 | state PhysicalPageID newPageID; |
| 906 | // If this is an extent based queue, check if there is an available page in current extent |
| 907 | if (self->queue->usesExtents) { |
| 908 | bool allocateNewExtent = false; |
| 909 | if (self->pageID != invalidPhysicalPageID) { |
| 910 | auto praw = self->header(); |
| 911 | if (praw->extentCurPageID < praw->extentEndPageID) { |
| 912 | newPageID = praw->extentCurPageID + 1; |
| 913 | } else { |
nothing calls this directly
no test coverage detected