2 Copyright (C) 2008 Steve Thomas <SMT837784@yahoo.com>
4 This file is part of RT Perfecter.
6 RT Perfecter is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 RT Perfecter is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with RT Perfecter. If not, see <http://www.gnu.org/licenses/>.
31 // I know Microsoft's compiler, .Net 2005 or older, does not come with this file.
32 // You can use this if you don't have dirent.h: http://www.cs.fiu.edu/~weiss/cop4338_spr06/dirent.h
33 // Umm I'm not sure if the license on that file, which appears to be public domain, conflicts with GPL v3.
34 // So only use that if you need it and the licenses don't conflict.
40 #define DIRECTORY_SEPERATOR '\\'
43 #define DIRECTORY_SEPERATOR '/'
52 RTRead::RTRead(char *dir, uint64 maxIndex, int verbose)
54 int dirLen = strlen(dir), dirFileLen;
55 char *file = new char[dirLen + NAME_MAX + 2];
57 struct dirent *pDirFile;
58 FileList *head = NULL, *current = NULL, *temp = new FileList;
62 m_maxIndex = maxIndex;
68 strncpy(file, dir, dirLen);
69 if (dir[dirLen - 1] != DIRECTORY_SEPERATOR)
71 file[dirLen] = DIRECTORY_SEPERATOR;
79 printf("Error #%u: Opening directory '%s'\n", errno, dir);
84 for (pDirFile = readdir(pDir); pDirFile != NULL; pDirFile = readdir(pDir))
86 dirFileLen = strlen(pDirFile->d_name);
87 if (pDirFile->d_name[0] != '.' && dirFileLen > 5 &&
88 pDirFile->d_name[dirFileLen - 5] == '.' &&
89 (pDirFile->d_name[dirFileLen - 4] == 'p' || pDirFile->d_name[dirFileLen - 4] == 'P') &&
90 (pDirFile->d_name[dirFileLen - 3] == 'a' || pDirFile->d_name[dirFileLen - 3] == 'A') &&
91 (pDirFile->d_name[dirFileLen - 2] == 'r' || pDirFile->d_name[dirFileLen - 2] == 'R') &&
92 (pDirFile->d_name[dirFileLen - 1] == 't' || pDirFile->d_name[dirFileLen - 1] == 'T'))
95 strcpy(file + dirLen, pDirFile->d_name);
96 if (getInfo(file, dirLen + dirFileLen, temp) == 0)
98 m_chains += temp->chains;
107 current->next = temp;
115 printf("Continue? (y/n): ");
117 while (ch != EOF && ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N')
121 if (ch != 'y' && ch != 'Y')
127 fclose(current->pFile);
128 delete [] current->name;
144 printf("Error no '*.part' input files found in directory '%s'.\n", dir);
148 // Push file list into priority queue
149 PriorityQueueNode tmpNode;
150 unsigned int i = 0, node, par;
152 m_pq = new PriorityQueueNode[m_pqSize];
155 if (readGoodChain(head->pFile, &(m_pq[i].chain)) == 0)
157 // Init priority queue node
158 m_pq[i].pFile = head->pFile;
159 m_pq[i].fName = head->name;
161 // Insert into priority queue
165 par = (node - 1) >> 1;
166 if (m_pq[par].chain.endpt > m_pq[node].chain.endpt)
168 tmpNode = m_pq[node];
171 m_pq[node] = m_pq[par];
177 par = (node - 1) >> 1;
178 } while (m_pq[par].chain.endpt > tmpNode.chain.endpt);
182 m_pq[node] = tmpNode;
190 printf("File had no valid chains '%s'\n", head->name);
191 delete [] head->name;
194 // Delete file list node
200 printf("Starting with %u files.\n", m_pqSize);
201 m_startTime = clock();
208 for (unsigned int i = 0; i < m_pqSize; i++)
210 if (m_pq[i].pFile != NULL)
212 fclose(m_pq[i].pFile);
214 if (m_pq[i].fName != NULL)
216 delete [] m_pq[i].fName;
223 int RTRead::readChain(RTChainCP *chain)
225 PriorityQueueNode tmp;
226 unsigned int child, node;
232 *chain = m_pq[0].chain;
233 bool remove = (readGoodChain(m_pq[0].pFile, &(m_pq[0].chain)) != 0);
239 printf("Finished with file '%s'\n", m_pq[0].fName);
241 delete [] m_pq[0].fName;
243 // Remove node from queue
247 if (m_pq[1].chain.endpt < m_pq[2].chain.endpt)
256 m_pq[2].fName = NULL;
257 m_pq[2].pFile = NULL;
259 else if (m_pqSize == 1)
262 m_pq[1].fName = NULL;
263 m_pq[1].pFile = NULL;
265 else if (m_pqSize == 0)
275 tmp = m_pq[m_pqSize];
276 m_pq[m_pqSize].fName = NULL;
277 m_pq[m_pqSize].pFile = NULL;
283 // Move tmp node to proper posistion in queue
286 if (m_pq[1].chain.endpt > m_pq[2].chain.endpt)
290 while (tmp.chain.endpt > m_pq[child].chain.endpt)
292 m_pq[node] = m_pq[child];
295 child = (node << 1) + 1;
296 if (child >= m_pqSize)
300 if (child + 1 < m_pqSize && m_pq[child].chain.endpt > m_pq[child + 1].chain.endpt)
302 // child = right node
306 if (node != 0 || remove)
311 else if (m_pqSize == 2 && !remove)
313 if (m_pq[0].chain.endpt > m_pq[1].chain.endpt)
323 int RTRead::readGoodChain(FILE *pFile, RTChainCP *chain)
333 ret = fread((void*)chain, 16, 1, pFile);
335 ret = fread((void*)&chain->checkpoint, 2, 1, pFile);
338 if (ferror(pFile) != 0)
340 printf("Error reading file.\n");
341 printf("Continue? (y/n): ");
343 while (ch != EOF && ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N')
347 if (ch != 'y' && ch != 'Y')
353 else if (feof(pFile) != 0)
363 } while (ret != 1 || chain->startpt > m_maxIndex || chain->endpt > m_maxIndex);
367 void RTRead::printStatus()
369 double percent = ((double) m_chainsRead / (double) m_chains) * 100.0;
370 double timeElapsed = (clock() - m_startTime) / (double)CLOCKS_PER_SEC;
372 printf("\n*** Status ***\n");
374 printf(" Chains Read: %I64u\n", m_chainsRead);
375 printf(" Total Chains: %I64u\n", m_chains);
377 printf(" Chains Read: %llu\n", m_chainsRead);
378 printf(" Total Chains: %llu\n", m_chains);
380 printf(" Files Open: %u\n", m_pqSize);
381 printf(" Percent: %0.1f\n", percent);
382 printf(" Time Elapsed: %0.0f sec\n", timeElapsed);
383 printf(" Time Left: %0.0f sec\n\n", timeElapsed / (percent / 100.0) - timeElapsed);
386 int RTRead::getInfo(char *file, int len, FileList *ret)
393 printf("Opening file '%s'\n", file);
395 pFile = fopen(file, "rb");
403 fseek(pFile, 0, SEEK_END);
408 printf("Error file size of '%s' is not a multible of 16 bytes.\n", file);
411 fseek(pFile, 0, SEEK_SET);
412 ret->chains = size >> 4;
415 ret->name = new char[len + 1];
416 strncpy(ret->name, file, len);
417 ret->name[len] = '\0';