| | 46 | struct JournalHead* JournalAllocHeader() |
| | 47 | { |
| | 48 | return malloc(sizeof(struct JournalHead)); |
| | 49 | } |
| | 50 | |
| | 51 | struct JournalHead* JournalAddHeader(struct Buffer* buffer) |
| | 52 | { |
| | 53 | struct JournalHead* ret; |
| | 54 | |
| | 55 | if (BufferJournal(buffer)) |
| | 56 | { |
| | 57 | ret=BufferToJournHead(buffer); |
| | 58 | }else{ |
| | 59 | ret=JournalAllocHeader(); |
| | 60 | |
| | 61 | buffer->flags |= 1 << BUFFER_JOURNAL; |
| | 62 | buffer->privData=ret; |
| | 63 | ret->buffer=buffer; |
| | 64 | BufferGet(buffer); |
| | 65 | } |
| | 66 | |
| | 67 | return buffer->privData; |
| | 68 | } |
| | 69 | |
| | 70 | extern void SleepWakeup(void* data); |
| | 71 | |
| | 72 | void JournalCommitSetTimer(struct Timer* commitTimer, struct Journal* journal) |
| | 73 | { |
| | 74 | /* Set up timer. */ |
| | 75 | commitTimer->func=SleepWakeup; |
| | 76 | commitTimer->expires=journal->commitInterval*100000; |
| | 77 | commitTimer->data=currThread; |
| | 78 | |
| | 79 | TimerAdd(commitTimer); |
| | 80 | } |
| | 81 | |
| | 82 | /* Journal commit thread. */ |
| | 83 | |
| | 84 | /* TODO: Move to commit.c */ |
| | 85 | void JournalCommitter(void* arg) |
| | 86 | { |
| | 87 | struct Journal* journal=(struct Journal*)arg; |
| | 88 | struct Timer commitTimer; |
| | 89 | INIT_WAITQUEUE_ENTRY(commitWait); |
| | 90 | |
| | 91 | INIT_WAITQUEUE_HEAD(&journal->commitWait); |
| | 92 | INIT_WAITQUEUE_HEAD(&journal->commitWaitDone); |
| | 93 | |
| | 94 | KePrint(KERN_INFO "JournalCommitter: started journal with commit interval of %d" |
| | 95 | " seconds\n", journal->commitInterval); |
| | 96 | |
| | 97 | while (1) |
| | 98 | { |
| | 99 | /* There should be a transaction to commit. */ |
| | 100 | if (journal->commitSequence != journal->commitRequest) |
| | 101 | { |
| | 102 | TimerRemove(&commitTimer); |
| | 103 | |
| | 104 | JournalCommitTransaction(journal); |
| | 105 | } |
| | 106 | |
| | 107 | /* May not always want timer running, esp. if we are waiting for commits. */ |
| | 108 | JournalCommitSetTimer(&commitTimer, journal); |
| | 109 | |
| | 110 | WaitAddToQueue(&journal->commitWait, &commitWait); |
| | 111 | |
| | 112 | ThrSuspendThread(currThread); |
| | 113 | ThrSchedule(); /* Will return here when the thread is scheduled again */ |
| | 114 | WaitRemoveFromQueue(&journal->commitWait, &commitWait); |
| | 115 | |
| | 116 | /* Get the running transaction, if we timed out, and commit that. Check expires. */ |
| | 117 | if (journal->currTransaction && currTime.seconds >= journal->currTransaction->expires) |
| | 118 | journal->commitRequest=journal->currTransaction->transId; |
| | 119 | } |
| | 120 | } |
| | 121 | |
| | 122 | int JournalNextLogBlock(struct Journal* journal, DWORD* ret) |
| | 123 | { |
| | 124 | DWORD blockNum; |
| | 125 | |
| | 126 | blockNum=journal->head; |
| | 127 | |
| | 128 | journal->head++; |
| | 129 | journal->free--; |
| | 130 | |
| | 131 | /* Check for wraparound! */ |
| | 132 | |
| | 133 | return JournalBlockMap(journal, blockNum, ret); |
| | 134 | } |
| | 135 | |
| | 136 | struct JournalHead* JournalGetDescriptorBuffer(struct Journal* journal) |
| | 137 | { |
| | 138 | int err; |
| | 139 | DWORD blockNum; |
| | 140 | struct Buffer* buffer; |
| | 141 | |
| | 142 | err=JournalNextLogBlock(journal, &blockNum); |
| | 143 | |
| | 144 | if (err) |
| | 145 | return NULL; |
| | 146 | |
| | 147 | buffer=JournalBlockRead(journal, blockNum); |
| | 148 | |
| | 149 | if (!buffer) |
| | 150 | return NULL; |
| | 151 | |
| | 152 | memset(buffer->data, 0, journal->sectorSize); |
| | 153 | |
| | 154 | return JournalAddHeader(buffer); |
| | 155 | } |
| | 156 | |
| | 215 | /* Start the per-journal commit kernel thread. */ |
| | 216 | journal->commitThread=ThrCreateKernelThreadArg(JournalCommitter, journal); |
| | 217 | journal->commitInterval=JOURN_COMMIT_INTERVAL; |
| | 218 | |
| | 219 | JournalRecover(journal, jSb); |
| | 220 | |
| | 221 | /* Set up transaction sequence numbers. */ |
| | 222 | journal->commitSequence=journal->transSequence-1; |
| | 223 | journal->commitRequest=journal->commitSequence; |
| | 224 | |
| | 225 | journal->head=BeToCpu32(jSb->first); |
| | 226 | journal->free=BeToCpu32(jSb->maxLen)-journal->head; |
| | 227 | |
| | 228 | ThrStartThread(journal->commitThread); |
| | 229 | |