/nordugrid-arc-2.0.0/src/hed/libs/data/DataBuffer.cpp

# · C++ · 676 lines · 611 code · 50 blank · 15 comment · 194 complexity · a7ae7f7d46556bff7dc41c78e090013a MD5 · raw file

  1. // -*- indent-tabs-mode: nil -*-
  2. #ifdef HAVE_CONFIG_H
  3. #include <config.h>
  4. #endif
  5. #include <cstdlib>
  6. #include <arc/CheckSum.h>
  7. #include <arc/data/DataBuffer.h>
  8. namespace Arc {
  9. bool DataBuffer::set(CheckSum *cksum, unsigned int size, int blocks) {
  10. lock.lock();
  11. if (blocks < 0) {
  12. lock.unlock();
  13. return false;
  14. }
  15. if (bufs != NULL) {
  16. for (int i = 0; i < bufs_n; i++)
  17. if (bufs[i].start)
  18. free(bufs[i].start);
  19. free(bufs);
  20. bufs_n = 0;
  21. bufs = NULL;
  22. set_counter++;
  23. cond.broadcast(); /* make all waiting loops to exit */
  24. }
  25. if ((size == 0) || (blocks == 0)) {
  26. lock.unlock();
  27. return true;
  28. }
  29. bufs = (buf_desc*)malloc(sizeof(buf_desc) * blocks);
  30. if (bufs == NULL) {
  31. lock.unlock();
  32. return false;
  33. }
  34. bufs_n = blocks;
  35. for (int i = 0; i < blocks; i++) {
  36. bufs[i].start = NULL;
  37. bufs[i].taken_for_read = false;
  38. bufs[i].taken_for_write = false;
  39. bufs[i].size = size;
  40. bufs[i].used = 0;
  41. bufs[i].offset = 0;
  42. }
  43. //checksum = cksum;
  44. checksums.clear();
  45. checksums.push_back(checksum_desc(cksum));
  46. if (cksum)
  47. cksum->start();
  48. lock.unlock();
  49. return true;
  50. }
  51. int DataBuffer::add(CheckSum *cksum) {
  52. if (!cksum)
  53. return -1;
  54. lock.lock();
  55. checksum_desc cs = cksum;
  56. cs.sum->start();
  57. for (int i = 0; i < bufs_n; i++)
  58. if (bufs[i].used != 0) {
  59. if (bufs[i].offset == cs.offset) {
  60. cs.sum->add(bufs[i].start, bufs[i].used);
  61. cs.offset += bufs[i].used;
  62. i = -1;
  63. cs.ready = true;
  64. }
  65. else if (cs.offset < bufs[i].offset)
  66. cs.ready = false;
  67. }
  68. if (eof_read_flag && cs.ready)
  69. cs.sum->end();
  70. checksums.push_back(cs);
  71. int res = checksums.size() - 1;
  72. lock.unlock();
  73. return res;
  74. }
  75. DataBuffer::DataBuffer(unsigned int size, int blocks) {
  76. bufs_n = 0;
  77. bufs = NULL;
  78. set_counter = 0;
  79. eof_read_flag = false;
  80. eof_write_flag = false;
  81. error_read_flag = false;
  82. error_write_flag = false;
  83. error_transfer_flag = false;
  84. set(NULL, size, blocks);
  85. eof_pos = 0;
  86. }
  87. DataBuffer::DataBuffer(CheckSum *cksum, unsigned int size,
  88. int blocks) {
  89. bufs_n = 0;
  90. bufs = NULL;
  91. set_counter = 0;
  92. eof_read_flag = false;
  93. eof_write_flag = false;
  94. error_read_flag = false;
  95. error_write_flag = false;
  96. error_transfer_flag = false;
  97. set(cksum, size, blocks);
  98. eof_pos = 0;
  99. }
  100. DataBuffer::~DataBuffer() {
  101. set(NULL, 0, 0);
  102. }
  103. bool DataBuffer::eof_read() {
  104. return eof_read_flag;
  105. }
  106. bool DataBuffer::eof_write() {
  107. return eof_write_flag;
  108. }
  109. bool DataBuffer::error_transfer() {
  110. return error_transfer_flag;
  111. }
  112. bool DataBuffer::error_read() {
  113. return error_read_flag;
  114. }
  115. bool DataBuffer::error_write() {
  116. return error_write_flag;
  117. }
  118. void DataBuffer::eof_read(bool eof_) {
  119. lock.lock();
  120. if (eof_)
  121. for (std::list<checksum_desc>::iterator itCheckSum = checksums.begin();
  122. itCheckSum != checksums.end(); itCheckSum++)
  123. if (itCheckSum->sum)
  124. itCheckSum->sum->end();
  125. eof_read_flag = eof_;
  126. cond.broadcast();
  127. lock.unlock();
  128. }
  129. void DataBuffer::eof_write(bool eof_) {
  130. lock.lock();
  131. eof_write_flag = eof_;
  132. cond.broadcast();
  133. lock.unlock();
  134. }
  135. bool DataBuffer::error() {
  136. return (error_read_flag || error_write_flag || error_transfer_flag);
  137. }
  138. void DataBuffer::error_read(bool error_) {
  139. lock.lock();
  140. // error_read_flag=error_;
  141. if (error_) {
  142. if (!(error_write_flag || error_transfer_flag))
  143. error_read_flag = true;
  144. for (std::list<checksum_desc>::iterator itCheckSum = checksums.begin();
  145. itCheckSum != checksums.end(); itCheckSum++)
  146. if (itCheckSum->sum)
  147. itCheckSum->sum->end();
  148. eof_read_flag = true;
  149. }
  150. else
  151. error_read_flag = false;
  152. cond.broadcast();
  153. lock.unlock();
  154. }
  155. void DataBuffer::error_write(bool error_) {
  156. lock.lock();
  157. // error_write_flag=error_;
  158. if (error_) {
  159. if (!(error_read_flag || error_transfer_flag))
  160. error_write_flag = true;
  161. eof_write_flag = true;
  162. }
  163. else
  164. error_write_flag = false;
  165. cond.broadcast();
  166. lock.unlock();
  167. }
  168. bool DataBuffer::wait_eof_read() {
  169. lock.lock();
  170. for (;;) {
  171. if (eof_read_flag)
  172. break;
  173. cond.wait(lock);
  174. }
  175. lock.unlock();
  176. return true;
  177. }
  178. bool DataBuffer::wait_read() {
  179. lock.lock();
  180. for (;;) {
  181. if (eof_read_flag)
  182. break;
  183. if (error_read_flag)
  184. break;
  185. cond.wait(lock);
  186. }
  187. lock.unlock();
  188. return true;
  189. }
  190. bool DataBuffer::wait_eof_write() {
  191. lock.lock();
  192. for (;;) {
  193. if (eof_write_flag)
  194. break;
  195. cond.wait(lock);
  196. }
  197. lock.unlock();
  198. return true;
  199. }
  200. bool DataBuffer::wait_write() {
  201. lock.lock();
  202. for (;;) {
  203. if (eof_write_flag)
  204. break;
  205. if (error_write_flag)
  206. break;
  207. cond.wait(lock);
  208. }
  209. lock.unlock();
  210. return true;
  211. }
  212. bool DataBuffer::wait_eof() {
  213. lock.lock();
  214. for (;;) {
  215. if (eof_read_flag && eof_write_flag)
  216. break;
  217. cond.wait(lock);
  218. }
  219. lock.unlock();
  220. return true;
  221. }
  222. bool DataBuffer::cond_wait() {
  223. // Wait for any event
  224. int tmp = set_counter;
  225. bool eof_read_flag_tmp = eof_read_flag;
  226. bool eof_write_flag_tmp = eof_write_flag;
  227. // cond.wait(lock);
  228. bool err = false;
  229. for (;;) {
  230. if (!speed.transfer())
  231. if ((!(error_read_flag || error_write_flag)) &&
  232. (!(eof_read_flag && eof_write_flag)))
  233. error_transfer_flag = true;
  234. if (eof_read_flag && eof_write_flag) { // there wil be no more events
  235. lock.unlock();
  236. Glib::Thread::yield();
  237. lock.lock();
  238. return true;
  239. }
  240. if (eof_read_flag_tmp != eof_read_flag)
  241. return true;
  242. if (eof_write_flag_tmp != eof_write_flag)
  243. return true;
  244. if (error())
  245. return false; // useless to wait for - better fail
  246. if (set_counter != tmp)
  247. return false;
  248. if (err)
  249. break; // Some event
  250. int t = 60;
  251. Glib::TimeVal stime;
  252. stime.assign_current_time();
  253. // Using timeout to workaround lost signal
  254. err = cond.timed_wait(lock, stime + t);
  255. }
  256. return true;
  257. }
  258. bool DataBuffer::for_read() {
  259. if (bufs == NULL)
  260. return false;
  261. lock.lock();
  262. for (int i = 0; i < bufs_n; i++)
  263. if ((!bufs[i].taken_for_read) && (!bufs[i].taken_for_write) &&
  264. (bufs[i].used == 0)) {
  265. lock.unlock();
  266. return true;
  267. }
  268. lock.unlock();
  269. return false;
  270. }
  271. bool DataBuffer::for_read(int& handle, unsigned int& length, bool wait) {
  272. lock.lock();
  273. if (bufs == NULL) {
  274. lock.unlock();
  275. return false;
  276. }
  277. for (;;) {
  278. if (error()) { /* errors detected/set - any continuation is unusable */
  279. lock.unlock();
  280. return false;
  281. }
  282. for (int i = 0; i < bufs_n; i++)
  283. if ((!bufs[i].taken_for_read) && (!bufs[i].taken_for_write) &&
  284. (bufs[i].used == 0)) {
  285. if (bufs[i].start == NULL) {
  286. bufs[i].start = (char*)malloc(bufs[i].size);
  287. if (bufs[i].start == NULL)
  288. continue;
  289. }
  290. handle = i;
  291. bufs[i].taken_for_read = true;
  292. length = bufs[i].size;
  293. cond.broadcast();
  294. lock.unlock();
  295. return true;
  296. }
  297. /* suitable block not found - wait for changes or quit */
  298. if (eof_write_flag) { /* writing side quited, no need to wait */
  299. lock.unlock();
  300. return false;
  301. }
  302. if (!wait) {
  303. lock.unlock();
  304. return false;
  305. }
  306. if (!cond_wait()) {
  307. lock.unlock();
  308. return false;
  309. }
  310. }
  311. lock.unlock();
  312. return false;
  313. }
  314. bool DataBuffer::is_read(char *buf, unsigned int length,
  315. unsigned long long int offset) {
  316. lock.lock();
  317. for (int i = 0; i < bufs_n; i++)
  318. if (bufs[i].start == buf) {
  319. lock.unlock();
  320. return is_read(i, length, offset);
  321. }
  322. lock.unlock();
  323. return false;
  324. }
  325. bool DataBuffer::is_read(int handle, unsigned int length,
  326. unsigned long long int offset) {
  327. lock.lock();
  328. if (bufs == NULL) {
  329. lock.unlock();
  330. return false;
  331. }
  332. if (handle >= bufs_n) {
  333. lock.unlock();
  334. return false;
  335. }
  336. if (!bufs[handle].taken_for_read) {
  337. lock.unlock();
  338. return false;
  339. }
  340. if (length > bufs[handle].size) {
  341. lock.unlock();
  342. return false;
  343. }
  344. bufs[handle].taken_for_read = false;
  345. bufs[handle].used = length;
  346. bufs[handle].offset = offset;
  347. if ((offset + length) > eof_pos)
  348. eof_pos = offset + length;
  349. /* checksum on the fly */
  350. for (std::list<checksum_desc>::iterator itCheckSum = checksums.begin();
  351. itCheckSum != checksums.end(); itCheckSum++)
  352. if ((itCheckSum->sum != NULL) && (offset == itCheckSum->offset))
  353. for (int i = handle; i < bufs_n; i++)
  354. if (bufs[i].used != 0) {
  355. if (bufs[i].offset == itCheckSum->offset) {
  356. itCheckSum->sum->add(bufs[i].start, bufs[i].used);
  357. itCheckSum->offset += bufs[i].used;
  358. i = -1;
  359. itCheckSum->ready = true;
  360. }
  361. else if (itCheckSum->offset < bufs[i].offset)
  362. itCheckSum->ready = false;
  363. }
  364. cond.broadcast();
  365. lock.unlock();
  366. return true;
  367. }
  368. bool DataBuffer::for_write() {
  369. if (bufs == NULL)
  370. return false;
  371. lock.lock();
  372. for (int i = 0; i < bufs_n; i++)
  373. if ((!bufs[i].taken_for_read) && (!bufs[i].taken_for_write) &&
  374. (bufs[i].used != 0)) {
  375. lock.unlock();
  376. return true;
  377. }
  378. lock.unlock();
  379. return false;
  380. }
  381. /* return true + buffer with data,
  382. return false in case of failure, or eof + no buffers claimed for read */
  383. bool DataBuffer::for_write(int& handle, unsigned int& length,
  384. unsigned long long int& offset, bool wait) {
  385. lock.lock();
  386. if (bufs == NULL) {
  387. lock.unlock();
  388. return false;
  389. }
  390. for (;;) {
  391. if (error()) { /* internal/external errors - no need to continue */
  392. lock.unlock();
  393. return false;
  394. }
  395. bool have_for_read = false;
  396. bool have_unused = false;
  397. unsigned long long int min_offset = (unsigned long long int)(-1);
  398. handle = -1;
  399. for (int i = 0; i < bufs_n; i++) {
  400. if (bufs[i].taken_for_read)
  401. have_for_read = true;
  402. if ((!bufs[i].taken_for_read) && (!bufs[i].taken_for_write) &&
  403. (bufs[i].used != 0))
  404. if (bufs[i].offset < min_offset) {
  405. min_offset = bufs[i].offset;
  406. handle = i;
  407. }
  408. if (bufs[i].taken_for_read || (bufs[i].used == 0))
  409. have_unused = true;
  410. }
  411. if (handle != -1) {
  412. bool keep_buffers = false;
  413. for (std::list<checksum_desc>::iterator itCheckSum = checksums.begin();
  414. itCheckSum != checksums.end(); itCheckSum++)
  415. if ((!itCheckSum->ready) && (bufs[handle].offset >= itCheckSum->offset)) {
  416. keep_buffers = true;
  417. break;
  418. }
  419. if (keep_buffers)
  420. /* try to keep buffers as long as possible for checksuming */
  421. if (have_unused && (!eof_read_flag)) {
  422. /* still have chances to get that block */
  423. if (!wait) {
  424. lock.unlock();
  425. return false;
  426. }
  427. if (!cond_wait()) {
  428. lock.unlock();
  429. return false;
  430. }
  431. continue;
  432. }
  433. bufs[handle].taken_for_write = true;
  434. length = bufs[handle].used;
  435. offset = bufs[handle].offset;
  436. cond.broadcast();
  437. lock.unlock();
  438. return true;
  439. }
  440. if (eof_read_flag && (!have_for_read)) {
  441. lock.unlock();
  442. return false;
  443. }
  444. /* suitable block not found - wait for changes or quit */
  445. if (!wait) {
  446. lock.unlock();
  447. return false;
  448. }
  449. if (!cond_wait()) {
  450. lock.unlock();
  451. return false;
  452. }
  453. }
  454. lock.unlock();
  455. return false;
  456. }
  457. bool DataBuffer::is_written(char *buf) {
  458. lock.lock();
  459. for (int i = 0; i < bufs_n; i++)
  460. if (bufs[i].start == buf) {
  461. lock.unlock();
  462. return is_written(i);
  463. }
  464. lock.unlock();
  465. return false;
  466. }
  467. bool DataBuffer::is_notwritten(char *buf) {
  468. lock.lock();
  469. for (int i = 0; i < bufs_n; i++)
  470. if (bufs[i].start == buf) {
  471. lock.unlock();
  472. return is_notwritten(i);
  473. }
  474. lock.unlock();
  475. return false;
  476. }
  477. bool DataBuffer::is_written(int handle) {
  478. lock.lock();
  479. if (bufs == NULL) {
  480. lock.unlock();
  481. return false;
  482. }
  483. if (handle >= bufs_n) {
  484. lock.unlock();
  485. return false;
  486. }
  487. if (!bufs[handle].taken_for_write) {
  488. lock.unlock();
  489. return false;
  490. }
  491. /* speed control */
  492. if (!speed.transfer(bufs[handle].used))
  493. if ((!(error_read_flag || error_write_flag)) &&
  494. (!(eof_read_flag && eof_write_flag)))
  495. error_transfer_flag = true;
  496. bufs[handle].taken_for_write = false;
  497. bufs[handle].used = 0;
  498. bufs[handle].offset = 0;
  499. cond.broadcast();
  500. lock.unlock();
  501. return true;
  502. }
  503. bool DataBuffer::is_notwritten(int handle) {
  504. lock.lock();
  505. if (bufs == NULL) {
  506. lock.unlock();
  507. return false;
  508. }
  509. if (handle >= bufs_n) {
  510. lock.unlock();
  511. return false;
  512. }
  513. if (!bufs[handle].taken_for_write) {
  514. lock.unlock();
  515. return false;
  516. }
  517. bufs[handle].taken_for_write = false;
  518. cond.broadcast();
  519. lock.unlock();
  520. return true;
  521. }
  522. char* DataBuffer::operator[](int block) {
  523. lock.lock();
  524. if ((block < 0) || (block >= bufs_n)) {
  525. lock.unlock();
  526. return NULL;
  527. }
  528. char *tmp = bufs[block].start;
  529. lock.unlock();
  530. return tmp;
  531. }
  532. bool DataBuffer::wait_any() {
  533. lock.lock();
  534. bool res = cond_wait();
  535. lock.unlock();
  536. return res;
  537. }
  538. bool DataBuffer::wait_used() {
  539. lock.lock();
  540. for (int i = 0; i < bufs_n; i++) {
  541. if ((bufs[i].taken_for_read) || (bufs[i].taken_for_write) ||
  542. (bufs[i].used != 0)) {
  543. if (!cond_wait()) {
  544. lock.unlock();
  545. return false;
  546. }
  547. i = -1;
  548. }
  549. }
  550. lock.unlock();
  551. return true;
  552. }
  553. bool DataBuffer::wait_for_read() {
  554. lock.lock();
  555. for (int i = 0; i < bufs_n; i++) {
  556. if (bufs[i].taken_for_read) {
  557. if (!cond_wait()) {
  558. lock.unlock();
  559. return false;
  560. }
  561. i = -1;
  562. }
  563. }
  564. lock.unlock();
  565. return true;
  566. }
  567. bool DataBuffer::wait_for_write() {
  568. lock.lock();
  569. for (int i = 0; i < bufs_n; i++) {
  570. if (bufs[i].taken_for_write) {
  571. if (!cond_wait()) {
  572. lock.unlock();
  573. return false;
  574. }
  575. i = -1;
  576. }
  577. }
  578. lock.unlock();
  579. return true;
  580. }
  581. bool DataBuffer::checksum_valid() const {
  582. if (checksums.size() != 0)
  583. return (checksums.begin()->ready && (checksums.begin()->offset == eof_pos));
  584. else
  585. return false;
  586. }
  587. bool DataBuffer::checksum_valid(int index) const {
  588. if (index < 0)
  589. return false;
  590. int i = 0;
  591. for (std::list<checksum_desc>::const_iterator itCheckSum = checksums.begin();
  592. itCheckSum != checksums.end(); itCheckSum++) {
  593. if (index == i)
  594. return itCheckSum->ready;
  595. i++;
  596. }
  597. return false;
  598. }
  599. const CheckSum* DataBuffer::checksum_object() const {
  600. if (checksums.size() != 0)
  601. return checksums.begin()->sum;
  602. else
  603. return NULL;
  604. }
  605. const CheckSum* DataBuffer::checksum_object(int index) const {
  606. if (index < 0)
  607. return NULL;
  608. int i = 0;
  609. for (std::list<checksum_desc>::const_iterator itCheckSum = checksums.begin();
  610. itCheckSum != checksums.end(); itCheckSum++) {
  611. if (index == i)
  612. return itCheckSum->sum;
  613. i++;
  614. }
  615. return NULL;
  616. }
  617. unsigned int DataBuffer::buffer_size() const {
  618. if (bufs == NULL)
  619. return 65536;
  620. unsigned int size = 0;
  621. for (int i = 0; i < bufs_n; i++)
  622. if (size < bufs[i].size)
  623. size = bufs[i].size;
  624. return size;
  625. }
  626. } // namespace Arc