00001 // ----------------------------------------------------------------------^ 00002 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone 00003 // (mailto: <gcalderone@ifc.inaf.it>) 00004 // 00005 // This file is part of MCS. 00006 // 00007 // MCS is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation; either version 2 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // MCS is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with MCS; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 // 00021 // ----------------------------------------------------------------------$ 00022 #include "mcs.hh" 00023 using namespace mcs; 00024 00025 //CURL includes 00026 #include <curl/curl.h> 00027 00028 //CFITSIO include 00029 #if ENABLE_CFITSIO 00030 #include <fitsio.h> 00031 //#include <fstream> 00032 #endif //ENABLE_CFITSIO 00033 00034 00035 Synchro Pipe::synchro; 00036 int Pipe::filecount = 0; 00037 00038 Pipe::Pipe() 00039 { 00040 pipefn = ""; 00041 pipefd[0] = 0; 00042 pipefd[1] = 0; 00043 flcreated = false; 00044 named = false; 00045 } 00046 00047 Pipe::~Pipe() 00048 { 00049 //Assume that is always the thread who reads from the pipe that 00050 //manages the object creation/destruction 00051 //closeRead(); 00052 } 00053 00054 bool Pipe::isReady() 00055 { return flcreated; } 00056 00057 string Pipe::filename() 00058 { return pipefn; } 00059 00060 00061 bool Pipe::consumerHasGone() 00062 { 00063 if (pipefd[1]) 00064 if (Select(pipefd[1], 0, 1, MCS_SELECT_WRITE) == -1) 00065 return true; 00066 00067 return false; 00068 } 00069 00070 00071 void Pipe::create() 00072 { 00073 if (flcreated) 00074 throw MCS_ERROR(MSG_PIPE_YET_OPENED); 00075 00076 if (pipefd[0] + pipefd[1]) 00077 throw MCS_ERROR(MSG_PIPE_YET_OPENED); 00078 00079 if (pipe(pipefd) != 0) 00080 throw MCS_ERROR(MSG_CALLING_PIPE); 00081 00082 flcreated = true; 00083 named = false; 00084 } 00085 00086 string Pipe::createNamed() 00087 { 00088 char filename[20]; 00089 00090 if (flcreated) 00091 throw MCS_ERROR(MSG_PIPE_YET_OPENED); 00092 00093 if (pipefd[0] + pipefd[1]) 00094 throw MCS_ERROR(MSG_PIPE_YET_OPENED); 00095 00096 do { 00097 /* 00098 Due to the fact that a Pipe object is typically used by two 00099 concurrent threads, and that the FIFO file is not open just as 00100 it is created (instead it is opened in the openRead() method) 00101 it is not safe to use tempnam-like functions. So we provide our 00102 own mechanisms to solve filename conflicts. 00103 */ 00104 synchro.enter(); 00105 sprintf(filename, "/tmp/mcspipe%04d", filecount); 00106 filecount++; 00107 filecount = filecount % 10000; 00108 synchro.leave(); 00109 00110 if (mkfifo(filename, S_IREAD | S_IWRITE) == 0) 00111 break; 00112 00113 sleep_ms(20); 00114 } while (1); 00115 00116 pipefn = filename; 00117 flcreated = true; 00118 named = true; 00119 00120 return pipefn; 00121 } 00122 00123 00124 00125 00126 00127 00128 int Pipe::openRead() 00129 { 00130 if (! flcreated) 00131 throw MCS_ERROR(MSG_PIPE_NOT_CREATED); 00132 00133 if (! pipefd[0]) { 00134 if (named) { 00135 pipefd[0] = open(pipefn.c_str(), O_RDONLY); 00136 unlink(pipefn.c_str()); //Remove the FIFO, it is no longer needed 00137 if (pipefd[0] == -1) throw MCS_ERROR(MSG_CANT_OPEN_FILE, pipefn.c_str()); 00138 } 00139 00140 //Ensure the other side hand of the pipe has been opened 00141 while (Select(pipefd[0], 0, 100, MCS_SELECT_READ) != 1) ; 00142 } 00143 00144 return pipefd[0]; 00145 } 00146 00147 00148 int Pipe::openWrite() 00149 { 00150 if (! flcreated) 00151 throw MCS_ERROR(MSG_PIPE_NOT_CREATED); 00152 00153 if (! pipefd[1]) { 00154 if (named) { 00155 pipefd[1] = open(pipefn.c_str(), O_WRONLY); 00156 unlink(pipefn.c_str()); //Remove the FIFO, it is no longer needed 00157 if (pipefd[1] == -1) throw MCS_ERROR(MSG_CANT_OPEN_FILE, pipefn.c_str()); 00158 } 00159 00160 //Ensure the other side hand of the pipe has been opened 00161 while (Select(pipefd[1], 0, 100, MCS_SELECT_WRITE) != 1) ; 00162 } 00163 00164 return pipefd[1]; 00165 } 00166 00167 00168 void Pipe::closeRead() 00169 { 00170 if (! flcreated) return; //Already closed 00171 if (named) unlink(pipefn.c_str()); //Remove the FIFO 00172 00173 if (pipefd[0]) { 00174 //Close read side of the pipe 00175 close(pipefd[0]); 00176 pipefd[0] = 0; 00177 } 00178 00179 pipefn = ""; 00180 flcreated = false; 00181 named = false; 00182 } 00183 00184 void Pipe::closeWrite() 00185 { 00186 if (! flcreated) return; //Already closed 00187 if (named) unlink(pipefn.c_str()); //Remove the FIFO 00188 00189 if (pipefd[1]) { 00190 //Close write side of the pipe 00191 close(pipefd[1]); 00192 pipefd[1] = 0; 00193 } 00194 } 00195 00196 00197 00198 00199 00200 00201 00202 00203 00204 00205 bool mcs::URLReader::fl_curl_global_init = false; 00206 00207 mcs::URLReader::URLReader() : Pipe() 00208 { 00209 if (! fl_curl_global_init) { 00210 fl_curl_global_init = true; 00211 curl_global_init(CURL_GLOBAL_ALL); 00212 } 00213 00214 thr = NULL; 00215 } 00216 00217 00218 mcs::URLReader::~URLReader() 00219 { Close(); } 00220 00221 00222 string mcs::URLReader::url() 00223 { return lurl; } 00224 00225 bool mcs::URLReader::chkLocal(string& url) 00226 { 00227 bool local = (bool) ( 00228 (url.find("://") == string::npos) || 00229 (url.find("file://") == 0) 00230 ); 00231 00232 if (local) url = subst(url, "file://", "", MCS_SUBST_LEADING); 00233 return local; 00234 } 00235 00236 00237 int mcs::URLReader::OpenAsFD(string url) 00238 { 00239 local = chkLocal(url); 00240 this->lurl = url; 00241 00242 create(); 00243 00244 thr = new ThreadFunc(thread_run, this); 00245 thr->startDetached(); 00246 return openRead(); 00247 } 00248 00249 00250 const char* mcs::URLReader::OpenAsFifo(string url) 00251 { 00252 local = chkLocal(url); 00253 this->lurl = url; 00254 00255 string fn = createNamed(); 00256 00257 thr = new ThreadFunc(thread_run, this); 00258 thr->startDetached(); 00259 00260 return fn.c_str(); 00261 } 00262 00263 00264 00265 void mcs::URLReader::Download(string url, string fn) 00266 { 00267 ofstream out(fn.c_str()); 00268 00269 if (! out.is_open()) 00270 throw MCS_ERROR(MSG_CANT_OPEN_FILE, fn.csz); 00271 00272 int fd = OpenAsFD(url); 00273 char buf[1024]; 00274 int n; 00275 00276 while ((n = read(fd, buf, 1024))) 00277 out.write(buf, n); 00278 00279 out.close(); 00280 Close(); 00281 } 00282 00283 00284 00285 void mcs::URLReader::Close() 00286 { 00287 if (thr) { 00288 closeRead(); 00289 lurl = ""; 00290 00291 while (thr->state() <= MCS_STATE_RUNNING) 00292 sleep_ms(20); 00293 00294 if (thr->error()) 00295 { 00296 Event e = *thr->error(); 00297 delete thr; 00298 thr = NULL; 00299 throw e; 00300 } 00301 delete thr; 00302 thr = NULL; 00303 } 00304 } 00305 00306 00307 00308 int mcs::URLReader::thread_run(void* p) 00309 { 00310 URLReader* This = (URLReader*) p; 00311 This->thread_fetch(); 00312 return 0; 00313 } 00314 00315 00316 void mcs::URLReader::thread_fetch() 00317 { 00318 openWrite(); //Open file for writing, it is necessary here otherwise the 00319 //openRead() on the other thread won't return 00320 00321 if (local) { 00322 int fd = open(lurl.c_str(), O_RDONLY); 00323 char buf[1024]; 00324 int len; 00325 00326 if (fd == -1) { 00327 closeWrite(); 00328 throw MCS_ERROR(MSG_CANT_OPEN_FILE, lurl.c_str()); 00329 } 00330 00331 while ((len = read(fd, buf, 1024))) 00332 cb_write(buf, len, 1, this); 00333 00334 closeWrite(); 00335 } 00336 else { 00337 CURLcode res; 00338 CURL* curl = curl_easy_init(); 00339 00340 if (! curl) 00341 throw MCS_ERROR(MSG_CURL_INIT); 00342 00343 res = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 00344 if (res != CURLE_OK) goto error; 00345 00346 //Timeout in seconds 00347 res = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 60); 00348 if (res != CURLE_OK) goto error; 00349 00350 res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); 00351 if (res != CURLE_OK) goto error; 00352 00353 res = curl_easy_setopt(curl, CURLOPT_URL, lurl.c_str()); 00354 if (res != CURLE_OK) goto error; 00355 00356 //res = curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, cb_progress); 00357 //if (res != CURLE_OK) goto error; 00358 00359 res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb_write); 00360 if (res != CURLE_OK) goto error; 00361 00362 res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, this); 00363 if (res != CURLE_OK) goto error; 00364 00365 res = curl_easy_setopt(curl, CURLOPT_PRIVATE, this); 00366 if (res != CURLE_OK) goto error; 00367 00368 res = curl_easy_perform(curl); 00369 if (res != 0) goto error; 00370 00371 closeWrite(); 00372 return; 00373 00374 error: 00375 closeWrite(); 00376 curl_easy_cleanup((CURL*) curl); 00377 throw MCS_ERROR(MSG_CURL_ERROR, curl_easy_strerror(res)); 00378 } 00379 } 00380 00381 00382 size_t mcs::URLReader::cb_write(void *ptr, size_t size, size_t nmemb, 00383 void *This) 00384 { 00385 URLReader* p = (URLReader*) This; 00386 00387 if (p->consumerHasGone()) //The pipe has been closed on the consumer side 00388 return 0; //This will abort CURL data fetching 00389 00390 //The Write() method is virtual because some derived class may wants 00391 //to write in a different manner 00392 return p->Write(ptr, size, nmemb); 00393 } 00394 00395 00396 void mcs::URLReader::flush() 00397 { fsync(openWrite()); } 00398 00399 00400 //In the base class version of the Write() method simply writes on 00401 //output file descriptor. 00402 unsigned int mcs::URLReader::Write(void *ptr, unsigned int size, 00403 unsigned int nmemb) 00404 { return write(openWrite(), ptr, size * nmemb); } 00405 00406 00407 00408 00409 int mcs::URLReader::Read(char* buf, int maxlen) 00410 { return read(openRead(), buf, maxlen); } 00411 00412 00413 //Event* mcs::URLReader::thread_error() 00414 //{ 00415 // if (thr) 00416 // return thr->error(); 00417 // 00418 // return NULL; 00419 //} 00420 00421 00422 //int mcs::URLReader::cb_progress(void *clientp, 00423 // double dltotal, double dlnow, 00424 // double ultotal, double ulnow) 00425 //{ 00426 // cout << "Download statistics: " << dlnow << " : " << dltotal << endl; 00427 // return 0; //Continue reading 00428 //} 00429 00430 00431 00432 00433 #if ENABLE_CFITSIO 00434 string mcs::fitsError(int status) { 00435 char buf[31]; 00436 fits_get_errstatus(status, buf); 00437 return string(buf); 00438 } 00439 00440 00441 FITSReader::FITSReader() : RecordSet() 00442 { fptr = NULL; } 00443 00444 00445 FITSReader::~FITSReader() 00446 {} 00447 00448 00449 #define FITSKEYLEN 70 00450 #define CHECK_FITS_ERROR if (status) throw MCS_ERROR(MSG_FITS_ERROR, fitsError(status).c_str()) 00451 00452 00453 int FITSReader::HDUCount() 00454 { 00455 int status = 0; 00456 fitsfile *fptr = (fitsfile*) this->fptr; 00457 00458 fits_get_num_hdus(fptr, &nhdu, &status); 00459 00460 return nhdu; 00461 } 00462 00463 00464 int FITSReader::currentHDU() 00465 { 00466 int i; 00467 fitsfile *fptr = (fitsfile*) this->fptr; 00468 fits_get_hdu_num(fptr, &i); 00469 00470 return i; 00471 } 00472 00473 void FITSReader::selectHDU(string name, int extver) 00474 { 00475 int status, i; 00476 fitsfile *fptr = (fitsfile*) this->fptr; 00477 00478 status = 0; 00479 fits_movnam_hdu(fptr, ANY_HDU, (char*) name.c_str(), extver, &status); 00480 CHECK_FITS_ERROR; 00481 00482 fits_get_hdu_num(fptr, &i); 00483 selectHDU(i); 00484 } 00485 00486 00487 bool FITSReader::selectNextHDU() 00488 { 00489 int status = 0; 00490 int exttype = ANY_HDU; 00491 00492 fitsfile *fptr = (fitsfile*) this->fptr; 00493 00494 fits_movrel_hdu(fptr, 1, &exttype, &status); 00495 if (status == END_OF_FILE) 00496 return false; 00497 00498 CHECK_FITS_ERROR; 00499 selectHDU(currentHDU()); 00500 00501 return true; 00502 } 00503 00504 00505 void FITSReader::selectHDU(int hdunum) 00506 { 00507 int status; 00508 long int repeat, width; 00509 int i, j; 00510 int fits_type; 00511 Types type; 00512 bool flunsign; 00513 string s; 00514 char buf[FITSKEYLEN]; 00515 char reqColName[5]; 00516 char head_name[80]; 00517 char head_val[80]; 00518 char head_comment[80]; 00519 Record meta; 00520 int nkeys; 00521 int hdutype; 00522 00523 fitsfile *fptr = (fitsfile*) this->fptr; 00524 fits_get_num_hdus(fptr, &nhdu, &status); 00525 00526 if ((hdunum <= 0) || (hdunum > nhdu)) 00527 throw; //ERROR 00528 00529 status = 0; 00530 hdutype = ANY_HDU; 00531 fits_movabs_hdu(fptr, hdunum, &hdutype, &status); 00532 CHECK_FITS_ERROR; 00533 00534 fits_get_hdrspace(fptr, &nkeys, NULL, &status); 00535 CHECK_FITS_ERROR; 00536 00537 header.clear(); 00538 header_comments.clear(); 00539 00540 for (i=1; i<=nkeys; i++) { 00541 fits_read_keyn(fptr, i, head_name, head_val, head_comment, &status); 00542 CHECK_FITS_ERROR; 00543 00544 Data* d = new Data(string(head_val)); 00545 d->setName(string(head_name)); 00546 header.addField(d); 00547 00548 d = new Data(string(head_comment)); 00549 d->setName(string(head_name)); 00550 header_comments.addField(d); 00551 } 00552 00553 fits_get_hdu_type(fptr, &hdutype, &status); 00554 CHECK_FITS_ERROR; 00555 00556 if ((hdutype == BINARY_TBL) || 00557 (hdutype == ASCII_TBL) ) { 00558 //Number of records 00559 fits_get_num_rows(fptr, &nrows, &status); 00560 CHECK_FITS_ERROR; 00561 00562 //Number of fields 00563 fits_get_num_cols(fptr, &ncols, &status); 00564 CHECK_FITS_ERROR; 00565 00566 for (i=0; i< ncols; i++) { 00567 sprintf(reqColName, "%d", i+1); 00568 fits_get_colname(fptr, CASEINSEN, reqColName, buf, &j, &status); 00569 fits_get_coltype(fptr, j, &fits_type, &repeat, &width, &status); 00570 CHECK_FITS_ERROR; 00571 00572 if (! FITS2Types(fits_type, type, flunsign)) 00573 throw MCS_ERROR(MSG_TYPE_NOT_HANDLED, i, fits_type); 00574 00575 if (! VarLenType(type)) 00576 width = 0; 00577 00578 Data* d = new Data(NULL, type, buf, width, flunsign); 00579 meta.addField(d); 00580 } 00581 00582 i = MCS_RS_USEMETAREC | MCS_RS_KNOW_NROWS; 00583 if (local) 00584 i |= MCS_RS_RANDOM; 00585 00586 init(i, nrows, &meta); 00587 startFetch(); 00588 } 00589 else { //Empty recordset 00590 i = MCS_RS_USEMETAREC | MCS_RS_KNOW_NROWS; 00591 init(i, 0, &meta); 00592 } 00593 } 00594 00595 //static FILE* _origstdin_ = stdin; 00596 00597 //int fits_open_pipe(fitsfile** fptr, int filedes, int rwmode, int* status) 00598 //{ 00599 // if (filedes == 0) 00600 // stdin = _origstdin_; 00601 // else 00602 // _origstdin_ = fdopen(filedes, "r"); 00603 // 00604 // return fits_open_file(fptr, "-", READONLY, status); 00605 //} 00606 00607 00608 //void FITSReader::open(int fd) 00609 //{ 00610 // int status = 0; 00611 // fitsfile *fptr; 00612 // 00613 // fits_open_pipe(&fptr, fd, READONLY, &status); 00614 // CHECK_FITS_ERROR; 00615 // this->fptr = fptr; 00616 // 00617 // fits_get_num_hdus(fptr, &nhdu, &status); 00618 // CHECK_FITS_ERROR; 00619 // 00620 // selectHDU(1); 00621 //} 00622 00623 00624 //static FILE* _origstdin_ = stdin; 00625 00626 void FITSReader::open(Buffer& buf) 00627 { 00628 int status; 00629 fitsfile *fptr; 00630 00631 memfile.set(buf[0], buf.size(), AUTO_FREE); 00632 00633 memfilep = memfile[0]; 00634 memfilesize = memfile.size(); 00635 fits_open_memfile(&fptr, "mem.fits", READONLY, 00636 &memfilep, &memfilesize, 00637 0, NULL, &status); 00638 00639 CHECK_FITS_ERROR; 00640 this->fptr = fptr; 00641 00642 fits_get_num_hdus(fptr, &nhdu, &status); 00643 CHECK_FITS_ERROR; 00644 00645 selectHDU(1); 00646 } 00647 00648 00649 00650 00651 void FITSReader::open(string fn) 00652 { 00653 int status; 00654 fitsfile *fptr; 00655 00656 local = URLReader::chkLocal(fn); 00657 //local = false; 00658 00659 status = 0; 00660 //if (local) { 00661 if (local && this->ffile_is_compressed(fn)) { 00662 fits_open_file(&fptr, fn.c_str(), READONLY, &status); 00663 } 00664 else { 00665 //The FITSReader can read also remote files (using its parent class 00666 //URLReader). Note that CFITSIO cannot read a FITS file as a 00667 //stream so actually it is entirely loaded into memory and then 00668 //parsed. 00669 00670 //Open the remote file as a file descriptor 00671 URLReader url; 00672 int fd = url.OpenAsFD(fn.c_str()); 00673 int n; 00674 char tmp[8192]; 00675 00676 //Load the FITS file into memory 00677 memfile.free(); 00678 while ((n = read(fd, tmp, 8192))) 00679 memfile(n) << tmp; 00680 00681 memfilep = memfile[0]; 00682 memfilesize = memfile.size(); 00683 fits_open_memfile(&fptr, "mem.fits", READONLY, 00684 &memfilep, &memfilesize, 00685 0, NULL, &status); 00686 00688 //stdin = fdopen(fd, "r"); 00689 // 00691 //fits_open_file(&fptr, "-", READONLY, &status); 00692 // 00694 //stdin = _origstdin_; 00695 00696 //Close the remote file descriptor. If an error occurred during timeout 00697 //an exception will be thrown here. 00698 url.Close(); 00699 } 00700 00701 CHECK_FITS_ERROR; 00702 this->fptr = fptr; 00703 00704 fits_get_num_hdus(fptr, &nhdu, &status); 00705 CHECK_FITS_ERROR; 00706 00707 selectHDU(1); 00708 } 00709 00710 00711 00712 bool FITSReader::fetch(unsigned int newpos, bool random) 00713 { 00714 int i, status = 0; 00715 fitsfile *fptr = (fitsfile*) this->fptr; 00716 00717 if (newpos >= nrows) 00718 return false; 00719 00720 for (i=0; i<ncols; i++) { 00721 void* p = rec()[i].buffer(); 00722 int fitstype; 00723 int isnull; 00724 00725 Types2FITS(rec()[i].type(), rec()[i].isUnsigned(), fitstype); 00726 00727 fits_read_col(fptr, fitstype, i+1, newpos+1, 1, 1, NULL, 00728 (VarLenType(rec()[i].type()) ? &p : p), 00729 &isnull, &status); 00730 CHECK_FITS_ERROR; 00731 00732 rec()[i].setNull(isnull); 00733 } 00734 00735 return true; 00736 } 00737 00738 00739 void FITSReader::close() { 00740 int status = 0; 00741 fitsfile *fptr = (fitsfile*) this->fptr; 00742 00743 if (fptr) { 00744 fits_close_file(fptr, &status); 00745 fptr = NULL; 00746 CHECK_FITS_ERROR; 00747 } 00748 } 00749 00750 bool FITSReader::ffile_is_compressed(string fn) { 00751 char buf[2]; 00752 00753 try { 00754 std::ifstream in(fn.c_str(), ios_base::in | ios_base::binary); 00755 00756 in.read(&buf[0], 2); 00757 00758 in.close(); 00759 00760 if ( (memcmp(buf, "\037\213", 2) == 0) || /* GZIP */ 00761 (memcmp(buf, "\120\113", 2) == 0) || /* PKZIP */ 00762 (memcmp(buf, "\037\036", 2) == 0) || /* PACK */ 00763 (memcmp(buf, "\037\235", 2) == 0) || /* LZW */ 00764 (memcmp(buf, "\037\240", 2) == 0) ) /* LZH */ 00765 { 00766 return true; /* compressed file */ 00767 } else { 00768 return false; /* not a compressed file */ 00769 } 00770 } catch(Event& e) { 00771 cerr <<"ffile_is_compressed: "<< e.msg() << endl; 00772 return false; 00773 } 00774 00775 } 00776 #endif //ENABLE_CFITSIO 00777 00778 00779 00780 00781 00782 00783 //FileReader::FileReader() : RecordSet() 00784 //{ 00785 // fd = 0; 00786 //} 00787 // 00788 //FileReader::~FileReader() 00789 //{ 00790 // this->close(); 00791 //} 00792 // 00793 //void FileReader::open(string url) 00794 //{ 00795 // this->close(); 00796 // 00797 // if (master.count() == 0) 00798 // throw; 00799 // 00800 // fd = input.OpenAsFD(url); 00801 // init(0); 00802 // startFetch(); 00803 //} 00804 // 00805 // 00806 //bool FileReader::fetch(unsigned int newpos, bool random) 00807 //{ 00808 // if (sep.length() > 0) { //Variable length record 00809 // ; 00810 // 00811 // } 00812 // else { //Fixed length record 00813 // size_t recsize = 0; 00814 // int i; 00815 // for (i=0; i<master.count(); i++) //Compute record size 00816 // recsize += master[i].maxLength(); 00817 // 00818 // buf.chkAllocation(recsize); 00819 // unsigned int size = read(fd, buf[0], recsize); 00820 // 00821 // if (size < recsize) 00822 // throw; 00823 // 00824 // //Copy data into the current record object 00825 // rec() = master; 00826 // unsigned int cur = 0; 00827 // for (i=0; i<master.count(); i++) { 00828 // buf(cur, rec()[i].maxLength()) >> rec()[i].buffer(); 00829 // cur += rec()[i].maxLength(); 00830 // } 00831 // } 00832 // 00833 // return true; 00834 //} 00835 // 00836 //void FileReader::close() 00837 //{ 00838 // sep = ""; 00839 // eor = ""; 00840 // master.clear(); 00841 //} 00842 // 00843 //void FileReader::setMaster(Record& rec) 00844 //{ 00845 // sep = ""; 00846 // eor = ""; 00847 // master = rec; 00848 //} 00849 // 00850 //void FileReader::setMaster(Record& rec, string sep) 00851 //{ 00852 // this->sep = sep; 00853 // eor = ""; 00854 // master = rec; 00855 //} 00856 // 00857 //void FileReader::setMaster(Record& rec, string sep, string eor) 00858 //{ 00859 // this->sep = sep; 00860 // this->eor = eor; 00861 // master = rec; 00862 //}
![]() |
MCS (My Customizable Server) ver. 0.3.3-alpha3
|