FluxDB.pm 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. ################################################################################
  2. # $Id: FluxDB.pm 2880 2007-04-12 18:52:02Z b4rt $
  3. # $Date: 2007-04-12 13:52:02 -0500 (Thu, 12 Apr 2007) $
  4. # $Revision: 2880 $
  5. ################################################################################
  6. # #
  7. # LICENSE #
  8. # #
  9. # This program is free software; you can redistribute it and/or #
  10. # modify it under the terms of the GNU General Public License (GPL) #
  11. # as published by the Free Software Foundation; either version 2 #
  12. # of the License, or (at your option) any later version. #
  13. # #
  14. # This program is distributed in the hope that it will be useful, #
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of #
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
  17. # GNU General Public License for more details. #
  18. # #
  19. # To read the license please visit http://www.gnu.org/copyleft/gpl.html #
  20. # #
  21. # #
  22. ################################################################################
  23. # #
  24. # Requirements for dbi-Mode : #
  25. # * DBI ( perl -MCPAN -e "install Bundle::DBI" ) #
  26. # * DBD::mysql for MySQL ( perl -MCPAN -e "install DBD::mysql" ) #
  27. # * DBD::SQLite for SQLite ( perl -MCPAN -e "install DBD::SQLite" ) #
  28. # * DBD::Pg for PostgreSQL ( perl -MCPAN -e "install DBD::Pg" ) #
  29. # #
  30. ################################################################################
  31. package FluxDB;
  32. use strict;
  33. use warnings;
  34. ################################################################################
  35. ################################################################################
  36. # fields #
  37. ################################################################################
  38. # version in a var
  39. my $VERSION = do {
  40. my @r = (q$Revision: 2880 $ =~ /\d+/g); sprintf "%d"."%02d" x $#r, @r };
  41. # state
  42. my $state = Fluxd::MOD_STATE_NULL;
  43. # message, error etc. keep it in one string for simplicity atm.
  44. my $message = "";
  45. # loglevel
  46. my $loglevel = 0;
  47. # operation-mode : dbi / php
  48. my $mode = "dbi";
  49. # docroot
  50. my $docroot = "/var/www";
  51. # load conf : 0|1
  52. my $loadConf = 1;
  53. # flux-config-hash
  54. my %fluxConf;
  55. # flux-config-test-keys
  56. my @fluxConfTestKeys = ('fluxd_dbmode', 'fluxd_loglevel');
  57. # load users : 0|1
  58. my $loadUsers = 0;
  59. # usernames
  60. my %names;
  61. # users
  62. my @users;
  63. # database-conf-file
  64. my $dbConfig = "config.db.php";
  65. # database-handle
  66. my $dbHandle = undef;
  67. # database-settings
  68. my $dbType = "";
  69. my $dbName = "";
  70. my $dbHost = "";
  71. my $dbPort = 0;
  72. my $dbUser = "";
  73. my $dbPass = "";
  74. my $dbDSN = "";
  75. # php
  76. my $php = "/usr/bin/php";
  77. # fluxcli
  78. my $fluxcli = "bin/fluxcli.php";
  79. ################################################################################
  80. # constructor + destructor #
  81. ################################################################################
  82. #------------------------------------------------------------------------------#
  83. # Sub: new #
  84. # Arguments: null #
  85. # Returns: object reference #
  86. #------------------------------------------------------------------------------#
  87. sub new {
  88. my $class = shift;
  89. my $self = bless ({}, ref ($class) || $class);
  90. return $self;
  91. }
  92. #------------------------------------------------------------------------------#
  93. # Sub: destroy #
  94. # Arguments: null #
  95. # Returns: null #
  96. #------------------------------------------------------------------------------#
  97. sub destroy {
  98. # log
  99. Fluxd::printMessage("FluxDB", "shutdown\n");
  100. # set state
  101. $state = Fluxd::MOD_STATE_NULL;
  102. # close connection
  103. dbDisconnect();
  104. # undef
  105. undef $dbHandle;
  106. undef %fluxConf;
  107. undef @users;
  108. undef %names;
  109. }
  110. ################################################################################
  111. # public methods #
  112. ################################################################################
  113. #------------------------------------------------------------------------------#
  114. # Sub: initialize. this is separated from constructor to call it independent #
  115. # from object-creation. #
  116. # Arguments: path-to-docroot, path-to-php, mode #
  117. # Returns: 0|1 #
  118. #------------------------------------------------------------------------------#
  119. sub initialize {
  120. shift; # class
  121. # path-docroot
  122. $docroot = shift;
  123. if (!(defined $docroot)) {
  124. # message
  125. $message = "path-to-docroot not defined";
  126. # set state
  127. $state = Fluxd::MOD_STATE_ERROR;
  128. # return
  129. return 0;
  130. }
  131. # path-php
  132. $php = shift;
  133. if (!(defined $php)) {
  134. # message
  135. $message = "path-to-php not defined";
  136. # set state
  137. $state = Fluxd::MOD_STATE_ERROR;
  138. # return
  139. return 0;
  140. }
  141. if (!(-x $php)) {
  142. # message
  143. $message = "cant execute php (".$php.")";
  144. # set state
  145. $state = Fluxd::MOD_STATE_ERROR;
  146. # return
  147. return 0;
  148. }
  149. # db-mode
  150. my $_dbmode = shift;
  151. # print
  152. Fluxd::printMessage("FluxDB", "initializing (mode: ".$_dbmode." ; docroot: ".$docroot." ; php: ".$php.")\n");
  153. # db-mode
  154. SWITCH: {
  155. $_ = $_dbmode;
  156. # dbi
  157. /^dbi/ && do {
  158. $mode = $_;
  159. # load DBI
  160. if (eval "require DBI") {
  161. DBI->import();
  162. } else {
  163. # message
  164. $message = "cant load DBI-module : ".$@;
  165. # set state
  166. $state = Fluxd::MOD_STATE_ERROR;
  167. # return
  168. return 0;
  169. }
  170. # db-config
  171. $dbConfig = $docroot."inc/config/".$dbConfig;
  172. if (!(-f $dbConfig)) {
  173. # message
  174. $message = "db-config no file (".$dbConfig.")";
  175. # set state
  176. $state = Fluxd::MOD_STATE_ERROR;
  177. # return
  178. return 0;
  179. }
  180. # load Database-Config
  181. if (loadDatabaseConfig($dbConfig) == 0) {
  182. # return
  183. return 0;
  184. }
  185. # connect
  186. if (dbConnect() == 0) {
  187. # close connection
  188. dbDisconnect();
  189. # return
  190. return 0;
  191. }
  192. # load config
  193. if ($loadConf == 1) {
  194. if (loadFluxConfigDBI() == 0) {
  195. # close connection
  196. dbDisconnect();
  197. # return
  198. return 0;
  199. }
  200. }
  201. # load users
  202. if ($loadUsers == 1) {
  203. if (loadFluxUsersDBI() == 0) {
  204. # close connection
  205. dbDisconnect();
  206. # return
  207. return 0;
  208. }
  209. }
  210. # close connection
  211. dbDisconnect();
  212. # done
  213. last SWITCH;
  214. };
  215. # php
  216. /^php/ && do {
  217. $mode = $_;
  218. # fluxcli
  219. if (!(-f $docroot.$fluxcli)) {
  220. # message
  221. $message = "fluxcli missing (".$docroot.$fluxcli.")";
  222. # set state
  223. $state = Fluxd::MOD_STATE_ERROR;
  224. # return
  225. return 0;
  226. }
  227. # load config
  228. if ($loadConf == 1) {
  229. if (loadFluxConfigPHP() == 0) {
  230. # return
  231. return 0;
  232. }
  233. }
  234. # load users
  235. if ($loadUsers == 1) {
  236. if (loadFluxUsersPHP() == 0) {
  237. # return
  238. return 0;
  239. }
  240. }
  241. # done
  242. last SWITCH;
  243. };
  244. # no valid mode. bail out
  245. # message
  246. $message = "no valid mode";
  247. # set state
  248. $state = Fluxd::MOD_STATE_ERROR;
  249. # return
  250. return 0;
  251. }
  252. # loglevel
  253. $loglevel = $fluxConf{"fluxd_loglevel"};
  254. # print
  255. Fluxd::printMessage("FluxDB", "data loaded and cached, FluxDB ready.\n");
  256. # set state
  257. $state = Fluxd::MOD_STATE_OK;
  258. # return
  259. return 1;
  260. }
  261. #------------------------------------------------------------------------------#
  262. # Sub: getVersion #
  263. # Arguments: null #
  264. # Returns: VERSION #
  265. #------------------------------------------------------------------------------#
  266. sub getVersion {
  267. return $VERSION;
  268. }
  269. #------------------------------------------------------------------------------#
  270. # Sub: getState #
  271. # Arguments: null #
  272. # Returns: state #
  273. #------------------------------------------------------------------------------#
  274. sub getState {
  275. return $state;
  276. }
  277. #------------------------------------------------------------------------------#
  278. # Sub: getMessage #
  279. # Arguments: null #
  280. # Returns: message #
  281. #------------------------------------------------------------------------------#
  282. sub getMessage {
  283. return $message;
  284. }
  285. #------------------------------------------------------------------------------#
  286. # Sub: getMode #
  287. # Arguments: null #
  288. # Returns: mode #
  289. #------------------------------------------------------------------------------#
  290. sub getMode {
  291. return $mode;
  292. }
  293. #------------------------------------------------------------------------------#
  294. # Sub: getDatabaseType #
  295. # Arguments: null #
  296. # Returns: Database-Type #
  297. #------------------------------------------------------------------------------#
  298. sub getDatabaseType {
  299. return $dbType;
  300. }
  301. #------------------------------------------------------------------------------#
  302. # Sub: getDatabaseName #
  303. # Arguments: null #
  304. # Returns: Database-Name #
  305. #------------------------------------------------------------------------------#
  306. sub getDatabaseName {
  307. return $dbName;
  308. }
  309. #------------------------------------------------------------------------------#
  310. # Sub: getDatabaseHost #
  311. # Arguments: null #
  312. # Returns: Database-Host #
  313. #------------------------------------------------------------------------------#
  314. sub getDatabaseHost {
  315. return $dbHost;
  316. }
  317. #------------------------------------------------------------------------------#
  318. # Sub: getDatabasePort #
  319. # Arguments: null #
  320. # Returns: Database-Port #
  321. #------------------------------------------------------------------------------#
  322. sub getDatabasePort {
  323. return $dbPort;
  324. }
  325. #------------------------------------------------------------------------------#
  326. # Sub: getDatabaseUser #
  327. # Arguments: null #
  328. # Returns: Database-User #
  329. #------------------------------------------------------------------------------#
  330. sub getDatabaseUser {
  331. return $dbUser;
  332. }
  333. #------------------------------------------------------------------------------#
  334. # Sub: getDatabasePassword #
  335. # Arguments: null #
  336. # Returns: Database-Password #
  337. #------------------------------------------------------------------------------#
  338. sub getDatabasePassword {
  339. return $dbPass;
  340. }
  341. #------------------------------------------------------------------------------#
  342. # Sub: getDatabaseDSN #
  343. # Arguments: null #
  344. # Returns: Database-DSN #
  345. #------------------------------------------------------------------------------#
  346. sub getDatabaseDSN {
  347. return $dbDSN;
  348. }
  349. #------------------------------------------------------------------------------#
  350. # Sub: getFluxConfig #
  351. # Arguments: key #
  352. # Returns: conf-value #
  353. #------------------------------------------------------------------------------#
  354. sub getFluxConfig {
  355. shift; # class
  356. my $key = shift;
  357. return (exists $fluxConf{$key}) ? $fluxConf{$key} : "";
  358. }
  359. #------------------------------------------------------------------------------#
  360. # Sub: setFluxConfig #
  361. # Arguments: key,value #
  362. # Returns: null #
  363. #------------------------------------------------------------------------------#
  364. sub setFluxConfig {
  365. shift; # class
  366. my $key = shift;
  367. $fluxConf{$key} = shift;
  368. }
  369. #------------------------------------------------------------------------------#
  370. # Sub: getFluxUsernames #
  371. # Arguments: null #
  372. # Returns: hash #
  373. #------------------------------------------------------------------------------#
  374. sub getFluxUsernames {
  375. return %names;
  376. }
  377. #------------------------------------------------------------------------------#
  378. # Sub: getFluxUsers #
  379. # Arguments: null #
  380. # Returns: array #
  381. #------------------------------------------------------------------------------#
  382. sub getFluxUsers {
  383. return @users;
  384. }
  385. #------------------------------------------------------------------------------#
  386. # Sub: reload #
  387. # Arguments: null #
  388. # Returns: 0|1 #
  389. #------------------------------------------------------------------------------#
  390. sub reload {
  391. # print
  392. if ($loglevel > 0) {
  393. Fluxd::printMessage("FluxDB", "reloading DB-Cache...\n");
  394. }
  395. SWITCH: {
  396. $_ = $mode;
  397. # dbi
  398. /^dbi/ && do {
  399. # connect
  400. if (dbConnect() == 0) {
  401. # close connection
  402. dbDisconnect();
  403. # return
  404. return 0;
  405. }
  406. # load config
  407. if ($loadConf == 1) {
  408. if (loadFluxConfigDBI() == 0) {
  409. # close connection
  410. dbDisconnect();
  411. # return
  412. return 0;
  413. }
  414. }
  415. # load users
  416. if ($loadUsers == 1) {
  417. if (loadFluxUsersDBI() == 0) {
  418. # close connection
  419. dbDisconnect();
  420. # return
  421. return 0;
  422. }
  423. }
  424. # close connection
  425. dbDisconnect();
  426. };
  427. # php
  428. /^php/ && do {
  429. # load config
  430. if ($loadConf == 1) {
  431. if (loadFluxConfigPHP() == 0) {
  432. # return
  433. return 0;
  434. }
  435. }
  436. # load users
  437. if ($loadUsers == 1) {
  438. if (loadFluxUsersPHP() == 0) {
  439. # return
  440. return 0;
  441. }
  442. }
  443. };
  444. }
  445. # print
  446. if ($loglevel > 0) {
  447. Fluxd::printMessage("FluxDB", "done reloading DB-Cache.\n");
  448. }
  449. # done
  450. return 1;
  451. }
  452. ################################################################################
  453. # private methods #
  454. ################################################################################
  455. #------------------------------------------------------------------------------#
  456. # Sub: loadDatabaseConfig #
  457. # Arguments: db-config-file (config.db.php) #
  458. # Returns: 0|1 #
  459. #------------------------------------------------------------------------------#
  460. sub loadDatabaseConfig {
  461. my $file = shift;
  462. open(CONFIG, $file) || return 0;
  463. my $lineSep = $/;
  464. undef $/;
  465. while (<CONFIG>) {
  466. if (/db_type.*[^\[]\"(.*)\"[^\]]/) {
  467. $dbType = $1;
  468. }
  469. if (/db_host.*[^\[]\"(.*)\"[^\]]/) {
  470. $dbHost = $1;
  471. }
  472. if (/db_name.*[^\[]\"(.*)\"[^\]]/) {
  473. $dbName = $1;
  474. }
  475. if (/db_user.*[^\[]\"(.*)\"[^\]]/) {
  476. $dbUser = $1;
  477. }
  478. if (/db_pass.*[^\[]\"(.*)\"[^\]]/) {
  479. $dbPass = $1;
  480. }
  481. }
  482. $/ = $lineSep;
  483. close(CONFIG);
  484. # build dsn
  485. $dbDSN = "DBI:";
  486. SWITCH: {
  487. $_ = $dbType;
  488. # MySQL
  489. /^mysql/i && do {
  490. $dbDSN .= "mysql:".$dbName.":".$dbHost;
  491. if ($dbPort > 0) {
  492. $dbDSN .= $dbPort;
  493. }
  494. last SWITCH;
  495. };
  496. # SQLite
  497. /^sqlite/i && do {
  498. $dbDSN .= "SQLite:dbname=".$dbHost;
  499. $dbUser = "";
  500. $dbPass = "";
  501. last SWITCH;
  502. };
  503. # PostgreSQL
  504. /^postgres/i && do {
  505. $dbDSN .= "Pg:dbname=".$dbName;
  506. if ($dbPort > 0) {
  507. $dbDSN .= ";port=".$dbPort;
  508. }
  509. last SWITCH;
  510. };
  511. # no valid db-type. bail out
  512. # message
  513. $message = "no valid db-type : ".$dbType;
  514. # set state
  515. $state = Fluxd::MOD_STATE_ERROR;
  516. # return
  517. return 0;
  518. }
  519. return 1;
  520. }
  521. #------------------------------------------------------------------------------#
  522. # Sub: dbConnect #
  523. # Arguments: null #
  524. # Returns: 0|1 #
  525. #------------------------------------------------------------------------------#
  526. sub dbConnect {
  527. # connect
  528. $dbHandle = DBI->connect(
  529. $dbDSN, $dbUser, $dbPass, { PrintError => 0, AutoCommit => 1 }
  530. );
  531. # check
  532. if (!(defined $dbHandle)) {
  533. # message
  534. $message = "error connecting to database :\n".$DBI::errstr;
  535. # set state
  536. $state = Fluxd::MOD_STATE_ERROR;
  537. # return
  538. return 0;
  539. }
  540. return 1;
  541. }
  542. #------------------------------------------------------------------------------#
  543. # Sub: dbDisconnect #
  544. # Arguments: null #
  545. # Returns: null #
  546. #------------------------------------------------------------------------------#
  547. sub dbDisconnect {
  548. # disconnect
  549. if (defined $dbHandle) {
  550. $dbHandle->disconnect();
  551. undef $dbHandle;
  552. }
  553. }
  554. #------------------------------------------------------------------------------#
  555. # Sub: checkFluxConfig #
  556. # Arguments: null #
  557. # Returns: 0|1 #
  558. #------------------------------------------------------------------------------#
  559. sub checkFluxConfig {
  560. foreach my $fluxConfTestKey (@fluxConfTestKeys) {
  561. if (!(exists $fluxConf{$fluxConfTestKey})) {
  562. # message
  563. $message = "checkFluxConfig failed. config does not exist : ".$fluxConfTestKey;
  564. # set state
  565. $state = Fluxd::MOD_STATE_ERROR;
  566. # return
  567. return 0;
  568. }
  569. if (!(defined $fluxConf{$fluxConfTestKey})) {
  570. # message
  571. $message = "checkFluxConfig failed. config not defined : ".$fluxConfTestKey;
  572. # set state
  573. $state = Fluxd::MOD_STATE_ERROR;
  574. # return
  575. return 0;
  576. }
  577. }
  578. # return
  579. return 1;
  580. }
  581. #------------------------------------------------------------------------------#
  582. # Sub: checkFluxUsers #
  583. # Arguments: null #
  584. # Returns: 0|1 #
  585. #------------------------------------------------------------------------------#
  586. sub checkFluxUsers{
  587. if (scalar(@users) > 0) {
  588. # return
  589. return 1;
  590. } else {
  591. # message
  592. $message = "checkFluxUsers failed.";
  593. # set state
  594. $state = Fluxd::MOD_STATE_ERROR;
  595. # return
  596. return 0;
  597. }
  598. }
  599. #------------------------------------------------------------------------------#
  600. # Sub: loadFluxConfigDBI #
  601. # Arguments: null #
  602. # Returns: 0|1 #
  603. #------------------------------------------------------------------------------#
  604. sub loadFluxConfigDBI {
  605. if (defined $dbHandle) {
  606. # flush first
  607. %fluxConf = ();
  608. # load from db
  609. my $sth = $dbHandle->prepare(q{ SELECT tf_key, tf_value FROM tf_settings });
  610. $sth->execute();
  611. my ($tfKey, $tfValue);
  612. my $rv = $sth->bind_columns(undef, \$tfKey, \$tfValue);
  613. while ($sth->fetch()) {
  614. $fluxConf{$tfKey} = $tfValue;
  615. }
  616. $sth->finish();
  617. # check
  618. return checkFluxConfig();
  619. } else {
  620. # message
  621. $message = "cannot load flux-config from database (dbi)";
  622. # set state
  623. $state = Fluxd::MOD_STATE_ERROR;
  624. # return
  625. return 0;
  626. }
  627. }
  628. #------------------------------------------------------------------------------#
  629. # Sub: loadFluxUsersDBI #
  630. # Arguments: null #
  631. # Returns: 0|1 #
  632. #------------------------------------------------------------------------------#
  633. sub loadFluxUsersDBI {
  634. if (defined $dbHandle) {
  635. # flush first
  636. @users = ();
  637. %names = ();
  638. # load from db
  639. my $sth = $dbHandle->prepare(q{ SELECT uid, user_id FROM tf_users });
  640. $sth->execute();
  641. my ($uid, $userid);
  642. my $rv = $sth->bind_columns(undef, \$uid, \$userid);
  643. my $index = 0;
  644. while ($sth->fetch()) {
  645. $users[$index] = {
  646. uid => $uid,
  647. username => $userid
  648. };
  649. $names{$userid} = $index;
  650. $index++;
  651. }
  652. $sth->finish();
  653. # check
  654. return checkFluxUsers();
  655. } else {
  656. # message
  657. $message = "cannot load flux-users from database (dbi)";
  658. # set state
  659. $state = Fluxd::MOD_STATE_ERROR;
  660. # return
  661. return 0;
  662. }
  663. }
  664. #------------------------------------------------------------------------------#
  665. # Sub: loadFluxConfigPHP #
  666. # Arguments: null #
  667. # Returns: 0|1 #
  668. #------------------------------------------------------------------------------#
  669. sub loadFluxConfigPHP {
  670. # flush first
  671. %fluxConf = ();
  672. # dump and init
  673. my $shellCmd = $php." ".$fluxcli." dump settings";
  674. my ($tfKey, $tfValue);
  675. open(CALL, $shellCmd." |");
  676. while(<CALL>) {
  677. chomp;
  678. ($tfKey, $tfValue) = split(/\*/, $_);
  679. $fluxConf{$tfKey} = $tfValue;
  680. }
  681. close(CALL);
  682. # check
  683. return checkFluxConfig();
  684. }
  685. #------------------------------------------------------------------------------#
  686. # Sub: loadFluxUsersPHP #
  687. # Arguments: null #
  688. # Returns: 0|1 #
  689. #------------------------------------------------------------------------------#
  690. sub loadFluxUsersPHP {
  691. # flush first
  692. @users = ();
  693. %names = ();
  694. # dump and init
  695. my $shellCmd = $php." ".$fluxcli." dump users";
  696. my ($uid, $userid);
  697. my $index = 0;
  698. open(CALL, $shellCmd." |");
  699. while(<CALL>) {
  700. chomp;
  701. ($uid, $userid) = split(/\*/, $_);
  702. $users[$index] = {
  703. uid => $uid,
  704. username => $userid
  705. };
  706. $names{$userid} = $index;
  707. $index++;
  708. }
  709. close(CALL);
  710. # check
  711. return checkFluxUsers();
  712. }
  713. ################################################################################
  714. # make perl happy #
  715. ################################################################################
  716. 1;