Merge lp:~fpstovall/nrtb/bk2thefuture into lp:nrtb

Proposed by Rick Stovall
Status: Merged
Approved by: Rick Stovall
Approved revision: 53
Merged at revision: 15
Proposed branch: lp:~fpstovall/nrtb/bk2thefuture
Merge into: lp:nrtb
Diff against target: 7286 lines (+3314/-2762)
42 files modified
cpp/common/Makefile (+7/-8)
cpp/common/abs_queue/Makefile (+33/-0)
cpp/common/abs_queue/abs_queue.h (+187/-0)
cpp/common/abs_queue/abs_queue_test.cpp (+120/-0)
cpp/common/circular_queue/Makefile (+4/-2)
cpp/common/circular_queue/circular_queue.h (+23/-128)
cpp/common/circular_queue/circular_queue_test.cpp (+47/-81)
cpp/common/common_rl/Makefile (+6/-3)
cpp/common/common_rl/common.cpp (+168/-192)
cpp/common/common_rl/common.h (+29/-33)
cpp/common/common_rl/common_rl_test.cpp (+18/-0)
cpp/common/confreader/Makefile (+5/-3)
cpp/common/confreader/confreader.cpp (+140/-148)
cpp/common/confreader/confreader.h (+234/-233)
cpp/common/confreader/conftest.cpp (+54/-48)
cpp/common/linear_queue/Makefile (+4/-2)
cpp/common/linear_queue/linear_queue.h (+6/-117)
cpp/common/linear_queue/linear_queue_test.cpp (+52/-85)
cpp/common/logger/Makefile (+20/-22)
cpp/common/logger/logger.cpp (+141/-0)
cpp/common/logger/logger.h (+76/-0)
cpp/common/logger/logger_test.cpp (+105/-0)
cpp/common/point/Makefile (+4/-5)
cpp/common/point/common_test.cpp (+65/-65)
cpp/common/point/triad.h (+176/-176)
cpp/common/serializer/Makefile (+2/-2)
cpp/common/serializer/serializer.cpp (+0/-2)
cpp/common/serializer/serializer.h (+3/-3)
cpp/common/singleton/Makefile (+3/-2)
cpp/common/singleton/singleton.h (+64/-60)
cpp/common/singleton/singleton_test.cpp (+8/-7)
cpp/common/sockets/Makefile (+5/-3)
cpp/common/sockets/base_socket.cpp (+565/-598)
cpp/common/sockets/base_socket.h (+472/-528)
cpp/common/sockets/socket_test.cpp (+53/-87)
cpp/common/timer/Makefile (+38/-0)
cpp/common/timer/hires_timer.cpp (+174/-0)
cpp/common/timer/hires_timer.h (+131/-0)
cpp/common/timer/timer_test.cpp (+72/-0)
obsolete/Cpp/common/logger/log_setup.cpp (+0/-43)
obsolete/Cpp/common/logger/log_setup.h (+0/-30)
obsolete/Cpp/common/logger/log_test.cpp (+0/-46)
To merge this branch: bzr merge lp:~fpstovall/nrtb/bk2thefuture
Reviewer Review Type Date Requested Status
Rick Stovall code merge Approve
Review via email: mp+179547@code.launchpad.net

Description of the change

This branch moves our development focus back to C++ (C++11). In preparing for this, the following has been accomplished:

   * The D code has been moved to the "obsolete" directory.
   * The needed C++ common libs have been restored from the obsolete directory.
   * Threading now uses the C++11 model; the old thread class has been removed.
   * The work_queue template has been replaced by cleaner thread safe queues.
   * The tcp_server_socket factory has been redesigned to use a producer/consumer model.
   * There is a new logger class which is simple and fast.
   * All the common code has been reviewed, formatted neatly, and updated to C++11 standards.

The upshot of all this is that we are closer to a working alpha phase release now than at any time in the last couple of years. I intend to allow this to rest until Sunday, at which time I will promoted it to main branch if there are no objections.

To post a comment you must log in.
Revision history for this message
Rick Stovall (fpstovall) wrote :

Per earlier discussion and after extensive unit testing and no objections, this merge is approved.

review: Approve (code merge)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== renamed directory 'obsolete/Cpp' => 'cpp'
2=== modified file 'cpp/common/Makefile'
3--- obsolete/Cpp/common/Makefile 2011-12-14 19:24:03 +0000
4+++ cpp/common/Makefile 2013-08-09 21:47:12 +0000
5@@ -16,7 +16,7 @@
6 #
7 #***********************************************
8
9-lib: ./lib/nrtb_common.a ./lib/nrtb_communication.a
10+lib: ./lib/nrtb_common.a
11
12 ./lib/nrtb_common.a:
13 @echo "============= building common libs ==============="
14@@ -24,9 +24,6 @@
15 @ar -r ./lib/nrtb_common.a ./obj/*.o
16 @echo "============= common libs complete ==============="
17
18-./lib/nrtb_communication.a:
19- @cd comm_handlers; make lib
20-
21 modules:
22 @echo "============= building common modules ==============="
23 @make doit
24@@ -36,14 +33,13 @@
25 @echo "============= cleaning common libs ==============="
26 @make action=clean doit
27 @rm -fv ./obj/* ./lib/* ./include/*
28- @cd comm_handlers; make clean
29 @echo "========== common lib cleanup complete ==========="
30
31 doit:
32 @cd common_rl; make ${action}
33 @cd point; make ${action}
34 @cd timer; make ${action}
35- @cd threads; make ${action}
36+ @cd abs_queue; make ${action}
37 @cd circular_queue; make ${action}
38 @cd linear_queue; make ${action}
39 @cd sockets; make ${action}
40@@ -51,6 +47,9 @@
41 @cd singleton; make ${action}
42 @cd logger; make ${action}
43 @cd confreader; make ${action}
44- @cd GPB; make ${action}
45- @cd transceiver; make ${action}
46+
47+# --- the following are obsolete and may be removed later.
48+# @cd threads; make ${action}
49+# @cd GPB; make ${action}
50+# @cd transceiver; make ${action}
51
52
53=== added directory 'cpp/common/abs_queue'
54=== added file 'cpp/common/abs_queue/Makefile'
55--- cpp/common/abs_queue/Makefile 1970-01-01 00:00:00 +0000
56+++ cpp/common/abs_queue/Makefile 2013-08-09 21:47:12 +0000
57@@ -0,0 +1,33 @@
58+#***********************************************
59+#This file is part of the NRTB project (https://launchpad.net/nrtb).
60+#
61+# NRTB is free software: you can redistribute it and/or modify
62+# it under the terms of the GNU General Public License as published by
63+# the Free Software Foundation, either version 3 of the License, or
64+# (at your option) any later version.
65+#
66+# NRTB is distributed in the hope that it will be useful,
67+# but WITHOUT ANY WARRANTY; without even the implied warranty of
68+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69+# GNU General Public License for more details.
70+#
71+# You should have received a copy of the GNU General Public License
72+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
73+#
74+#***********************************************
75+
76+switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP
77+
78+lib: abs_queue_test
79+ @./abs_queue_test
80+ @cp -v abs_queue.h ../include
81+ @echo build complete
82+
83+abs_queue_test: abs_queue.h abs_queue_test.cpp
84+ @rm -f abs_queue_test
85+ g++ -c abs_queue_test.cpp -I../include ${switches}
86+ g++ -o abs_queue_test abs_queue_test.o -lpthread ${switches}
87+
88+clean:
89+ @rm -rvf *.o abs_queue_test ../include/abs_queue.h *.log ../obj/abs_queue.o
90+ @echo all objects and executables have been erased.
91
92=== added file 'cpp/common/abs_queue/abs_queue.h'
93--- cpp/common/abs_queue/abs_queue.h 1970-01-01 00:00:00 +0000
94+++ cpp/common/abs_queue/abs_queue.h 2013-08-09 21:47:12 +0000
95@@ -0,0 +1,187 @@
96+/***********************************************
97+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
98+
99+ NRTB is free software: you can redistribute it and/or modify
100+ it under the terms of the GNU General Public License as published by
101+ the Free Software Foundation, either version 3 of the License, or
102+ (at your option) any later version.
103+
104+ NRTB is distributed in the hope that it will be useful,
105+ but WITHOUT ANY WARRANTY; without even the implied warranty of
106+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
107+ GNU General Public License for more details.
108+
109+ You should have received a copy of the GNU General Public License
110+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
111+
112+ **********************************************/
113+
114+#ifndef nrtb_abs_queue_h
115+#define nrtb_abs_queue_h
116+
117+#include <common.h>
118+#include <atomic>
119+#include <mutex>
120+#include <condition_variable>
121+
122+namespace nrtb
123+{
124+
125+/********************************************************
126+ * The abs_queue template is designed for use with
127+ * the classic producer/consumer thread management model.
128+ * The producer uses abs_queue::push() to put items
129+ * in the queue as they become available, and the consumer
130+ * thread calls abs_queue::park() when it is ready
131+ * for the next item to work.
132+ *
133+ * This queue will expand as needed. Constrast this with
134+ * the circular_queue, which is of a fixed size and will
135+ * drop older data when full
136+ *
137+ * Common uses would be for buffering outgoing or incomming
138+ * messages from a communications channel, providing a feed
139+ * queue for parallel threads to make full use of multi-core
140+ * processors, or any case where one or more threads are
141+ * passing data to another set of threads.
142+********************************************************/
143+template <class T, class queue_t>
144+class abs_queue
145+{
146+public:
147+ class queue_not_ready: public nrtb::base_exception {};
148+
149+ /// Total number of items placed in queue.
150+ std::atomic<int> in_count {0};
151+ /// Total number of items read from queue.
152+ std::atomic<int> out_count {0};
153+
154+ /*********************************************
155+ * creates the queue with the specified
156+ * number of elements.
157+ *********************************************/
158+ abs_queue();
159+
160+ /*********************************************
161+ * releases all items in the queue
162+ *********************************************/
163+ ~abs_queue();
164+
165+ /*********************************************
166+ * Puts an item in the queue.
167+ *********************************************/
168+ void push(T item);
169+
170+ /*********************************************
171+ * Pops the next item off the queue, blocking
172+ * if needed until an item becomes available.
173+ *********************************************/
174+ T pop();
175+
176+ /*********************************************
177+ * puts the queue in shutdown mode.
178+ *********************************************/
179+ void shutdown();
180+
181+ // returns the number of items in the queue
182+ int size();
183+ // resizes the buffer, may cause data loss
184+ void resize(int newsize);
185+ // clears the buffer, data will be discarded.
186+ void clear();
187+
188+protected:
189+
190+ queue_t buffer;
191+ std::mutex mylock;
192+ std::condition_variable signal;
193+ bool ready {true};
194+};
195+
196+template <class T, class queue_t>
197+abs_queue<T,queue_t>::abs_queue()
198+{
199+};
200+
201+template <class T, class queue_t>
202+abs_queue<T,queue_t>::~abs_queue()
203+{
204+ shutdown();
205+};
206+
207+template <class T, class queue_t>
208+void abs_queue<T,queue_t>::push(T item)
209+{
210+ if (ready)
211+ {
212+ in_count++;
213+ {
214+ std::unique_lock<std::mutex> lock(mylock);
215+ buffer.push(item);
216+ }
217+ signal.notify_one();
218+ }
219+ else
220+ {
221+ queue_not_ready e;
222+ throw e;
223+ }
224+};
225+
226+template <class T, class queue_t>
227+T abs_queue<T,queue_t>::pop()
228+{
229+ std::unique_lock<std::mutex> lock(mylock);
230+ while (buffer.empty() && ready)
231+ signal.wait(lock);
232+ if (ready)
233+ {
234+ T returnme = buffer.front();
235+ buffer.pop();
236+ out_count++;
237+ return returnme;
238+ }
239+ else
240+ {
241+ queue_not_ready e;
242+ throw e;
243+ };
244+};
245+
246+template <class T, class queue_t>
247+void abs_queue<T,queue_t>::shutdown()
248+{
249+ try
250+ {
251+ std::unique_lock<std::mutex> lock(mylock);
252+ ready = false;
253+ while (buffer.size()) { buffer.pop(); }
254+ signal.notify_all();
255+ }
256+ catch (...) {}
257+}
258+
259+template <class T, class queue_t>
260+int abs_queue<T,queue_t>::size()
261+{
262+ std::unique_lock<std::mutex> lock(mylock);
263+ return buffer.size();
264+};
265+
266+template <class T, class queue_t>
267+void abs_queue<T,queue_t>::resize(int newsize)
268+{
269+ std::unique_lock<std::mutex> lock(mylock);
270+ buffer.set_capacity(newsize);
271+};
272+
273+template <class T, class queue_t>
274+void abs_queue<T,queue_t>::clear()
275+{
276+ std::unique_lock<std::mutex> lock(mylock);
277+ while (buffer.size()) buffer.pop();
278+};
279+
280+} // namespace nrtb
281+
282+#endif //nrtb_abs_queue_h//
283
284=== added file 'cpp/common/abs_queue/abs_queue_test.cpp'
285--- cpp/common/abs_queue/abs_queue_test.cpp 1970-01-01 00:00:00 +0000
286+++ cpp/common/abs_queue/abs_queue_test.cpp 2013-08-09 21:47:12 +0000
287@@ -0,0 +1,120 @@
288+/***********************************************
289+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
290+
291+ NRTB is free software: you can redistribute it and/or modify
292+ it under the terms of the GNU General Public License as published by
293+ the Free Software Foundation, either version 3 of the License, or
294+ (at your option) any later version.
295+
296+ NRTB is distributed in the hope that it will be useful,
297+ but WITHOUT ANY WARRANTY; without even the implied warranty of
298+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
299+ GNU General Public License for more details.
300+
301+ You should have received a copy of the GNU General Public License
302+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
303+
304+ **********************************************/
305+
306+#include <unistd.h> // included for usleep()
307+#include <string>
308+#include <iostream>
309+#include "abs_queue.h"
310+#include <memory>
311+#include <atomic>
312+#include <future>
313+#include <queue>
314+
315+using namespace nrtb;
316+using namespace std;
317+
318+typedef abs_queue<int,std::queue<int>> test_queue;
319+typedef shared_ptr<test_queue> queue_p;
320+
321+int consumer_task(string name, queue_p input)
322+{
323+ bool ready {true};
324+ int count {0};
325+ try
326+ {
327+ while (ready)
328+ {
329+ int num = input->pop();
330+ count++;
331+ usleep(1);
332+ }
333+ }
334+ catch (...)
335+ {
336+ // exit if we get any exception.
337+ ready = false;
338+ };
339+ return count;
340+};
341+
342+int main()
343+{
344+ cout << "***** abs_queue unit test ******" << endl;
345+ /************************************************
346+ * Load queue and then cook it down...
347+ ***********************************************/
348+ // make and load a queue
349+ queue_p q1(new test_queue());
350+ for (int i=0; i<100; i++)
351+ {
352+ q1->push(i);
353+ };
354+ // the queue should be loaded with 0-99
355+ // attach a thread and process it.
356+ auto t1 = async(launch::async,consumer_task,"task 1",q1);
357+ while (q1->size()) usleep(100);
358+ cout << "cp 1 "
359+ << q1->in_count << ":"
360+ << q1->out_count << endl;
361+ /************************************************
362+ * now that the preload is exhasted, shove items
363+ * in one at a time to make sure each is picked
364+ * up correctly.
365+ ***********************************************/
366+ for (int i=200; i<225; i++)
367+ {
368+ q1->push(i);
369+ usleep(100);
370+ };
371+ cout << "cp 2 "
372+ << q1->in_count << ":"
373+ << q1->out_count << endl;
374+ /************************************************
375+ * Last check; attach a second thread to the queue
376+ * and make sure both are servicing it.
377+ ***********************************************/
378+ auto t2 = async(launch::async,consumer_task,"task 2",q1);
379+ for (int i=300; i<325; i++)
380+ {
381+ q1->push(i);
382+ };
383+ while (q1->size()) usleep(100);
384+ // shut it all down
385+ q1->shutdown();
386+ // important numbers
387+ int t1_count = t1.get();
388+ int t2_count = t2.get();
389+ int q1_in = q1->in_count;
390+ int q1_out = q1->out_count;
391+ // release the queues.
392+ q1.reset();
393+ // do some reporting.
394+ cout << "cp 3 "
395+ << q1_in << ":" << q1_out
396+ << " t1=" << t1_count
397+ << " t2=" << t2_count
398+ << endl;
399+ bool passed = (q1_in == q1_out)
400+ and (q1_out == (t1_count + t2_count));
401+ cout << "***** abs_queue TEST "
402+ << (passed ? "PASSED" : "FAILED")
403+ << " ******" << endl;
404+ // inverted logic needed because 0 is good for
405+ // return codes.
406+ return !passed;
407+};
408\ No newline at end of file
409
410=== modified file 'cpp/common/circular_queue/Makefile'
411--- obsolete/Cpp/common/circular_queue/Makefile 2012-04-06 12:10:36 +0000
412+++ cpp/common/circular_queue/Makefile 2013-08-09 21:47:12 +0000
413@@ -16,6 +16,8 @@
414 #
415 #***********************************************
416
417+switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP
418+
419 lib: circular_queue_test
420 @./circular_queue_test
421 @cp -v circular_queue.h ../include
422@@ -23,8 +25,8 @@
423
424 circular_queue_test: circular_queue.h circular_queue_test.cpp
425 @rm -f circular_queue_test
426- g++ -c circular_queue_test.cpp -I../include -std=gnu++0x
427- g++ -o circular_queue_test circular_queue_test.o ../obj/common.o ../obj/base_thread.o -lpthread -std=gnu++0x
428+ g++ -c circular_queue_test.cpp -I../include ${switches}
429+ g++ -o circular_queue_test circular_queue_test.o -lpthread ${switches}
430
431 clean:
432 @rm -rvf *.o circular_queue_test ../include/circular_queue.h *.log ../obj/circular_queue.o
433
434=== modified file 'cpp/common/circular_queue/circular_queue.h'
435--- obsolete/Cpp/common/circular_queue/circular_queue.h 2011-10-06 20:09:07 +0000
436+++ cpp/common/circular_queue/circular_queue.h 2013-08-09 21:47:12 +0000
437@@ -20,18 +20,31 @@
438 #define nrtb_circular_queue_h
439
440 #include <iostream>
441-#include <base_thread.h>
442 #include <boost/circular_buffer.hpp>
443+#include <atomic>
444+#include <mutex>
445+#include <condition_variable>
446+#include <common.h>
447+#include <abs_queue.h>
448
449 namespace nrtb
450 {
451+
452+// specialize boost::circular_buffer to act like a queue.
453+template <class T>
454+class base_cq : public boost::circular_buffer<T>
455+{
456+public:
457+ void push(T elem) { this->push_back(elem); };
458+ void pop() { this->pop_front(); };
459+};
460
461 /********************************************************
462 * The circular_queue template is designed for use with
463 * the classic producer/consumer thread management model.
464 * The producer uses circular_queue::push() to put items
465 * in the queue as they become available, and the consumer
466- * thread calls circular_queue::park() when it is ready
467+ * thread calls circular_queue::pop() when it is ready
468 * for the next item to work.
469 *
470 * Common uses would be for buffering outgoing or incomming
471@@ -41,132 +54,14 @@
472 * passing data to another set of threads.
473 ********************************************************/
474 template <class T>
475-class circular_queue
476-{
477-public:
478- class queue_not_ready: public base_exception {};
479-
480- /*********************************************
481- * creates the queue with the specified
482- * number of elements. All memory is allocated
483- * at construction to minimize delays at runtime.
484- *********************************************/
485- circular_queue(int size);
486-
487- /*********************************************
488- * releases all items in the queue
489- *********************************************/
490- virtual ~circular_queue();
491-
492- /*********************************************
493- * Puts an item in the queue.
494- *********************************************/
495- void push(T item);
496-
497- /*********************************************
498- * Pops the next item off the queue, blocking
499- * if needed until an item becomes available.
500- *********************************************/
501- T pop();
502-
503- /*********************************************
504- * puts the queue in shutdown mode.
505- *********************************************/
506- void shutdown();
507-
508- // returns the number of items in the queue
509- int size();
510- // resizes the buffer, may cause data loss
511- void resize(int newsize);
512- // clears the buffer, data will be discarded.
513- void clear();
514-
515-protected:
516-
517- boost::circular_buffer<T> buffer;
518- cond_variable buffer_lock;
519- bool ready;
520-};
521-
522-template <class T>
523-circular_queue<T>::circular_queue(int size)
524-{
525- buffer.set_capacity(size);
526- ready = true;
527-};
528-
529-// TODO: needed ... a queue stop method.
530-
531-template <class T>
532-circular_queue<T>::~circular_queue()
533-{
534-};
535-
536-template <class T>
537-void circular_queue<T>::push(T item)
538-{
539- if (ready)
540- {
541- scope_lock lock(buffer_lock);
542- buffer.push_back(item);
543- buffer_lock.signal();
544- }
545- else
546- {
547- queue_not_ready e;
548- throw e;
549- }
550-};
551-
552-template <class T>
553-T circular_queue<T>::pop()
554-{
555- scope_lock lock(buffer_lock);
556- while (buffer.empty() && ready)
557- buffer_lock.wait();
558- if (!ready)
559- {
560- queue_not_ready e;
561- throw e;
562- };
563- T returnme = buffer.front();
564- buffer.pop_front();
565- return returnme;
566-};
567-
568-template <class T>
569-void circular_queue<T>::shutdown()
570-{
571- try
572- {
573- scope_lock lock(buffer_lock);
574- ready = false;
575- buffer_lock.broadcast_signal();
576- buffer.clear();
577- }
578- catch (...) {}
579-}
580-
581-
582-template <class T>
583-int circular_queue<T>::size()
584-{
585- scope_lock lock(buffer_lock);
586- return buffer.size();
587-};
588-
589-template <class T>
590-void circular_queue<T>::resize(int newsize)
591-{
592- scope_lock lock(buffer_lock);
593- buffer.set_capacity(newsize);
594-};
595-
596-template <class T>
597-void circular_queue<T>::clear()
598-{
599- scope_lock lock(buffer_lock);
600- buffer.clear();
601+class circular_queue : public abs_queue<T, base_cq<T>>
602+{
603+public:
604+ // convienence constructor because a 0 size circular_queue is useless.
605+ circular_queue(int size=10) : abs_queue<T, base_cq<T>>()
606+ {
607+ this->resize(size);
608+ };
609 };
610
611 } // namespace nrtb
612
613=== modified file 'cpp/common/circular_queue/circular_queue_test.cpp'
614--- obsolete/Cpp/common/circular_queue/circular_queue_test.cpp 2011-10-06 20:09:07 +0000
615+++ cpp/common/circular_queue/circular_queue_test.cpp 2013-08-09 21:47:12 +0000
616@@ -18,78 +18,41 @@
617
618 #include <string>
619 #include <iostream>
620+#include <unistd.h>
621 #include "circular_queue.h"
622-#include <boost/shared_ptr.hpp>
623+#include <memory>
624+#include <future>
625
626 using namespace nrtb;
627 using namespace std;
628
629 typedef circular_queue<int> test_queue;
630-typedef boost::shared_ptr<test_queue> queue_p;
631+typedef std::shared_ptr<test_queue> queue_p;
632
633-class consumer_task: public thread
634+int consumer_task(string name, queue_p input)
635 {
636-public:
637-
638- consumer_task(string n, queue_p buffer)
639- {
640- name = n;
641- input = buffer;
642- count = 0;
643- };
644-
645- ~consumer_task()
646- {
647- cout << ">> in " << name << "::~consumer_task()" << endl;
648- try
649- {
650- this->thread::~thread();
651- input.reset();
652- }
653- catch (...) {};
654- cout << "<< leaving " << name << "::~consumer_task()" << endl;
655- };
656-
657- int get_count() { return count; };
658-
659- void run()
660- {
661- try
662- {
663- while (true)
664- {
665- int num = input->pop();
666- {
667- static mutex console;
668- scope_lock lock(console);
669- cout << name << " picked up " << num
670- << endl;
671- };
672- count++;
673- lastnum = num;
674- yield();
675- }
676- }
677- catch (...) {};
678- };
679-
680-protected:
681- // link to the feed queue
682- queue_p input;
683- // a name to report
684- string name;
685- // number of items processed
686- int count;
687- // last number caught
688- int lastnum;
689+ bool ready {true};
690+ int count {0};
691+ try
692+ {
693+ while (ready)
694+ {
695+ int num = input->pop();
696+ count++;
697+ usleep(1);
698+ }
699+ }
700+ catch (...)
701+ {
702+ // exit on any exception
703+ ready = false;
704+ };
705+ return count;
706 };
707
708-typedef boost::shared_ptr<consumer_task> task_p;
709-
710-
711 int main()
712 {
713- int er_count = 0;
714+ cout << "***** circular_queue unit test *****" << endl;
715 /************************************************
716 * Load queue and then cook it down...
717 ***********************************************/
718@@ -101,10 +64,11 @@
719 };
720 // the queue should be loaded with 50-99
721 // attach a thread and process it.
722- task_p p1(new consumer_task("task 1",q1));
723- p1->start();
724+ auto t1 = async(launch::async,consumer_task,"task 1",q1);
725 while (q1->size()) usleep(100);
726- cout << "cp 1 " << p1->get_count() << endl;
727+ cout << "cp 1 "
728+ << q1->in_count << ":"
729+ << q1->out_count << endl;
730 /************************************************
731 * now that the preload is exhasted, shove items
732 * in one at a time to make sure each is picked
733@@ -112,40 +76,42 @@
734 ***********************************************/
735 for (int i=200; i<225; i++)
736 {
737- q1->push(i);
738- usleep(100);
739+ q1->push(i);
740+ usleep(100);
741 };
742- cout << "cp 2 " << p1->get_count() << endl;
743+ cout << "cp 2 "
744+ << q1->in_count << ":"
745+ << q1->out_count << endl;
746 /************************************************
747 * Last check; attach a second thread to the queue
748 * and make sure both are servicing it.
749 ***********************************************/
750- task_p p2(new consumer_task("task 2",q1));
751- p2->start();
752+ auto t2 = async(launch::async,consumer_task,"task 2",q1);
753 for (int i=300; i<325; i++)
754 {
755- q1->push(i);
756+ q1->push(i);
757 };
758 while (q1->size()) usleep(100);
759 // shut it all down
760 q1->shutdown();
761- p1->join();
762- p2->join();
763 // important numbers
764- int tot_items = p1->get_count() + p2->get_count();
765- int p1_items = p1->get_count() - 75;
766- int p2_items = p2->get_count();
767+ int q1_in = q1->in_count;
768+ int q1_out = q1->out_count;
769+ int t1_items = t1.get();
770+ int t2_items = t2.get();
771 // release she threads and queues.
772- p1.reset();
773- p2.reset();
774 q1.reset();
775 // do some reporting.
776 cout << "cp 3 "
777- << tot_items
778- << " [75 + (" << p1_items
779- << " + " << p2_items
780- << ")]" << endl;
781- bool passed = (tot_items == 100);
782+ << q1_in << ":" << q1_out
783+ << " t1=" << t1_items
784+ << " t2=" << t2_items
785+ << endl;
786+ bool passed = (q1_in - 50 == q1_out)
787+ and (q1_out == (t1_items + t2_items));
788+ cout << "***** circular_queue TEST "
789+ << (passed ? "PASSED" : "FAILED")
790+ << " ******" << endl;
791 // inverted logic needed because 0 is good for
792 // return codes.
793 return !passed;
794
795=== modified file 'cpp/common/common_rl/Makefile'
796--- obsolete/Cpp/common/common_rl/Makefile 2012-04-06 12:16:10 +0000
797+++ cpp/common/common_rl/Makefile 2013-08-09 21:47:12 +0000
798@@ -16,6 +16,9 @@
799 #
800 #***********************************************
801
802+switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP
803+
804+
805 lib: common_rl_test
806 @./common_rl_test
807 @cp -v common.h ../include
808@@ -24,12 +27,12 @@
809
810 common.o: common.h common.cpp Makefile
811 @rm -f common.o
812- g++ -c -O3 common.cpp -std=gnu++0x
813+ g++ -c -O3 common.cpp ${switches}
814
815 common_rl_test: common.o common_rl_test.cpp
816 @rm -f common_rl_test
817- g++ -c common_rl_test.cpp -std=gnu++0x
818- g++ -o common_rl_test common_rl_test.o common.o -std=gnu++0x
819+ g++ -c common_rl_test.cpp ${switches}
820+ g++ -o common_rl_test common_rl_test.o common.o ${switches}
821
822 clean:
823 @rm -rvf *.o ../include/common.h ../obj/common.o common_rl_test
824
825=== modified file 'cpp/common/common_rl/common.cpp'
826--- obsolete/Cpp/common/common_rl/common.cpp 2010-12-25 22:44:22 +0000
827+++ cpp/common/common_rl/common.cpp 2013-08-09 21:47:12 +0000
828@@ -19,7 +19,6 @@
829 #include <stdlib.h>
830 #include <iostream>
831 #include <math.h>
832-#include <time.h>
833 #include "common.h"
834
835 using namespace std;
836@@ -27,247 +26,224 @@
837 namespace nrtb
838 {
839
840-base_exception::base_exception()
841-{
842- ctime = time(NULL);
843-};
844-
845-base_exception::base_exception(const string & text)
846-{
847- ctime = time(NULL);
848- _text = text;
849-};
850-
851-void base_exception::store(const string & s)
852-{
853- _text = s;
854-};
855-
856-string base_exception::comment()
857-{
858- return _text;
859-};
860-
861-unsigned long int base_exception::creation_time()
862-{
863- return ctime;
864-};
865-
866 const string __ricks_handy_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
867 const string __ricks_handy_lower = "abcdefghijklmnopqrstuvwxyz";
868
869-string changecase(const string &s,const string &upper, const string &lower)
870+string changecase(const string &s,const string &upper,
871+ const string &lower)
872 {
873- try
874- {
875- string returnme = "";
876- for (int i = 0; i < s.size(); i++)
877- {
878- unsigned long int loc = lower.find(s[i]);
879- if (loc == string::npos)
880- {
881- returnme += s[i];
882- }
883- else
884- {
885- returnme += upper[loc];
886- };
887- };
888- return returnme;
889- }
890- catch (...)
891- {
892- throw translate_exception();
893- };
894+ try
895+ {
896+ string returnme = "";
897+ for (int i = 0; i < s.size(); i++)
898+ {
899+ unsigned long int loc = lower.find(s[i]);
900+ if (loc == string::npos)
901+ {
902+ returnme += s[i];
903+ }
904+ else
905+ {
906+ returnme += upper[loc];
907+ };
908+ };
909+ return returnme;
910+ }
911+ catch (...)
912+ {
913+ throw translate_exception();
914+ };
915 };
916
917 string upcase(const string &s)
918 {
919- return changecase(s,__ricks_handy_upper,__ricks_handy_lower);
920+ return changecase(s,__ricks_handy_upper,__ricks_handy_lower);
921 };
922
923 string downcase(const string &s)
924 {
925- return changecase(s,__ricks_handy_lower,__ricks_handy_upper);
926+ return changecase(s,__ricks_handy_lower,__ricks_handy_upper);
927 };
928
929
930 const string __ricks_handy_hexits = "0123456789ABCDEF";
931
932-string gsub(const string & target, const string & findme, const string & putme)
933+string gsub(const string & target, const string & findme,
934+ const string & putme)
935 {
936- // error checking
937- if (findme.empty() || target.empty())
938- {
939- throw gsub_exception();
940- };
941- string returnme = "";
942- unsigned long int okay_through = 0;
943- unsigned long int step = findme.length();
944- unsigned long int where = target.find(findme,okay_through);
945- while (where != string::npos)
946- {
947- returnme += target.substr(okay_through,where-okay_through) + putme;
948- okay_through = where + step;
949- where = target.find(findme,okay_through);
950- };
951- returnme += target.substr(okay_through);
952- return returnme;
953+ // error checking
954+ if (findme.empty() || target.empty())
955+ {
956+ throw gsub_exception();
957+ };
958+ string returnme = "";
959+ unsigned long int okay_through = 0;
960+ unsigned long int step = findme.length();
961+ unsigned long int where = target.find(findme,okay_through);
962+ while (where != string::npos)
963+ {
964+ returnme += target.substr(okay_through,where-okay_through) + putme;
965+ okay_through = where + step;
966+ where = target.find(findme,okay_through);
967+ };
968+ returnme += target.substr(okay_through);
969+ return returnme;
970 };
971
972 strlist split(const string & source, const char token)
973 {
974- strlist returnme;
975- returnme.clear();
976- if (source.size() > 0)
977- {
978- unsigned long int loc;
979- unsigned long int processed = 0;
980- try
981- {
982- loc = source.find(token,processed);
983- while (loc != string::npos)
984- {
985- returnme.push_back(source.substr(processed,loc-processed));
986- processed = loc + 1;
987- loc = source.find(token,processed);
988- }
989- returnme.push_back(source.substr(processed));
990- }
991- catch (...)
992- {
993- throw split_exception();
994- };
995- };
996- return returnme;
997+ strlist returnme;
998+ returnme.clear();
999+ if (source.size() > 0)
1000+ {
1001+ unsigned long int loc;
1002+ unsigned long int processed = 0;
1003+ try
1004+ {
1005+ loc = source.find(token,processed);
1006+ while (loc != string::npos)
1007+ {
1008+ returnme.push_back(source.substr(processed,loc-processed));
1009+ processed = loc + 1;
1010+ loc = source.find(token,processed);
1011+ }
1012+ returnme.push_back(source.substr(processed));
1013+ }
1014+ catch (...)
1015+ {
1016+ throw split_exception();
1017+ };
1018+ };
1019+ return returnme;
1020 };
1021
1022 string trim(std::string s)
1023 {
1024- const string ws = "\t\n ";
1025- unsigned long int where = s.find_first_not_of(ws);
1026- if (where != string::npos)
1027- {
1028- s.erase(0,where);
1029- };
1030- where = s.find_last_not_of(ws);
1031- if (where != string::npos)
1032- {
1033- s.erase(where+1);
1034- };
1035- return s;
1036+ const string ws = "\t\n ";
1037+ unsigned long int where = s.find_first_not_of(ws);
1038+ if (where != string::npos)
1039+ {
1040+ s.erase(0,where);
1041+ };
1042+ where = s.find_last_not_of(ws);
1043+ if (where != string::npos)
1044+ {
1045+ s.erase(where+1);
1046+ };
1047+ return s;
1048 };
1049
1050 string mconvert(const string &s)
1051 {
1052- /* This function is designed to escape strings destined for
1053- * use in SQL queries and the like. Specifically, the following
1054- * is done to the string passed in:
1055- * 1. "\" is replaced with "\\"
1056- * 2. "'" is replaced with "\'"
1057- * 3. """ (double quote) is replaced with "\""
1058- * 4. 0x00 is replaced with "\"+0x00.
1059- */
1060- string returnme = "";
1061- if (s.length() > 0)
1062- {
1063- returnme = gsub(s,"\\","\\\\");
1064- returnme = gsub(returnme,"'", "\\'");
1065- returnme = gsub(returnme,"\"","\\\"");
1066- // special handling is required to make strings including
1067- // 0x00; this is the kludge I found to work at 2200 tonight.
1068- string findme = " "; findme[0] = 0;
1069- returnme = gsub(returnme,findme,"\\0");
1070- };
1071- return returnme;
1072+ /* This function is designed to escape strings destined for
1073+ * use in SQL queries and the like. Specifically, the following
1074+ * is done to the string passed in:
1075+ * 1. "\" is replaced with "\\"
1076+ * 2. "'" is replaced with "\'"
1077+ * 3. """ (double quote) is replaced with "\""
1078+ * 4. 0x00 is replaced with "\"+0x00.
1079+ */
1080+ string returnme = "";
1081+ if (s.length() > 0)
1082+ {
1083+ returnme = gsub(s,"\\","\\\\");
1084+ returnme = gsub(returnme,"'", "\\'");
1085+ returnme = gsub(returnme,"\"","\\\"");
1086+ // special handling is required to make strings including
1087+ // 0x00; this is the kludge I found to work at 2200 tonight.
1088+ string findme = " "; findme[0] = 0;
1089+ returnme = gsub(returnme,findme,"\\0");
1090+ };
1091+ return returnme;
1092 };
1093
1094 string dateflip(string date, const string & sep)
1095 {
1096- string out;
1097- try
1098- {
1099- strlist temp = split(date,'-');
1100- out = temp[1]+ sep + temp[2] + sep + temp[0];
1101- }
1102- catch (...)
1103- {
1104- throw dateflip_exception();
1105- };
1106- return out;
1107+ string out;
1108+ try
1109+ {
1110+ strlist temp = split(date,'-');
1111+ out = temp[1]+ sep + temp[2] + sep + temp[0];
1112+ }
1113+ catch (...)
1114+ {
1115+ throw dateflip_exception();
1116+ };
1117+ return out;
1118 }; // string dateflip
1119
1120 string http_hextochar(string s)
1121 {
1122- try
1123- {
1124- s = upcase(s);
1125- unsigned char v = (16 * __ricks_handy_hexits.find(s[0]))
1126- + __ricks_handy_hexits.find(s[1]);
1127- return s = v;
1128- }
1129- catch (...)
1130- {
1131- throw hextrans_exception();
1132- };
1133+ try
1134+ {
1135+ s = upcase(s);
1136+ unsigned char v = (16 * __ricks_handy_hexits.find(s[0]))
1137+ + __ricks_handy_hexits.find(s[1]);
1138+ return s = v;
1139+ }
1140+ catch (...)
1141+ {
1142+ throw hextrans_exception();
1143+ };
1144 }; // string hextochar
1145
1146 string http_chartohex(const string &s)
1147 {
1148- string out;
1149- try
1150- {
1151- for (long int i=0; i < s.length() ; i++ ) {
1152- unsigned char v = s[i];
1153- div_t hexval = div(v,16);
1154- out += __ricks_handy_hexits[hexval.quot];
1155- out += __ricks_handy_hexits[hexval.rem];
1156- }; /* endfor */
1157- }
1158- catch (...)
1159- {
1160- throw hextrans_exception();
1161- };
1162- return out;
1163+ string out;
1164+ try
1165+ {
1166+ for (long int i=0; i < s.length() ; i++ ) {
1167+ unsigned char v = s[i];
1168+ div_t hexval = div(v,16);
1169+ out += __ricks_handy_hexits[hexval.quot];
1170+ out += __ricks_handy_hexits[hexval.rem];
1171+ }; /* endfor */
1172+ }
1173+ catch (...)
1174+ {
1175+ throw hextrans_exception();
1176+ };
1177+ return out;
1178 };// string chartohex()
1179
1180 string http_enhex(const string & s)
1181 {
1182- string out;
1183- try
1184- {
1185- for (long int i=0; i < s.length() ; i++ ) {
1186- unsigned char v = s[i];
1187- div_t hexval = div(v,16);
1188- out += "%";
1189- out += __ricks_handy_hexits[hexval.quot];
1190- out += __ricks_handy_hexits[hexval.rem];
1191- }; /* endfor */
1192- }
1193- catch (...)
1194- {
1195- throw hextrans_exception();
1196- };
1197- return out;
1198+ string out;
1199+ try
1200+ {
1201+ for (long int i=0; i < s.length() ; i++ )
1202+ {
1203+ unsigned char v = s[i];
1204+ div_t hexval = div(v,16);
1205+ out += "%";
1206+ out += __ricks_handy_hexits[hexval.quot];
1207+ out += __ricks_handy_hexits[hexval.rem];
1208+ }; /* endfor */
1209+ }
1210+ catch (...)
1211+ {
1212+ throw hextrans_exception();
1213+ };
1214+ return out;
1215 }; // string enhex()
1216
1217 string http_unhex(string s)
1218 {
1219- try
1220- {
1221- while (s.find('%') != string::npos)
1222- {
1223- int where = s.find('%');
1224- string hexchar = s.substr(where+1,2);
1225- s.erase(where,3);
1226- s.insert(where,http_hextochar(hexchar));
1227- }; /* endwhile */
1228- }
1229- catch (...)
1230- {
1231- throw hextrans_exception();
1232- };
1233- return s;
1234+ try
1235+ {
1236+ while (s.find('%') != string::npos)
1237+ {
1238+ int where = s.find('%');
1239+ string hexchar = s.substr(where+1,2);
1240+ s.erase(where,3);
1241+ s.insert(where,http_hextochar(hexchar));
1242+ }; /* endwhile */
1243+ }
1244+ catch (...)
1245+ {
1246+ throw hextrans_exception();
1247+ };
1248+ return s;
1249 };// string unhex()
1250
1251
1252
1253=== modified file 'cpp/common/common_rl/common.h'
1254--- obsolete/Cpp/common/common_rl/common.h 2010-12-25 22:44:22 +0000
1255+++ cpp/common/common_rl/common.h 2013-08-09 21:47:12 +0000
1256@@ -20,10 +20,10 @@
1257 #ifndef __ga_common_h
1258 #define __ga_common_h 1
1259
1260-//#include <stream.h>
1261 #include <string>
1262 #include <map>
1263 #include <vector>
1264+#include <chrono>
1265
1266 namespace nrtb
1267 {
1268@@ -39,40 +39,36 @@
1269 ** get the time the exception was created and any text the thrower may have
1270 ** provided.
1271 **/
1272- class base_exception: public std::exception
1273- {
1274- protected:
1275- unsigned long int ctime;
1276- std::string _text;
1277- public:
1278- /** Default constructor.
1279- **
1280- ** Creates an nrtb_exception recording it's creation time but without
1281- ** a comment string.
1282- **/
1283- base_exception();
1284- /** Constructs with a comment string.
1285- **
1286- ** Creates an nrtb_exception recording it's creation time and storing the
1287- ** provided string "text" for recall later via the comment method.
1288- **
1289- ** This version takes an ISO standard C++ string.
1290- **/
1291- base_exception(const std::string & text);
1292- /// NOP virtual distructor for safe inheritance
1293- virtual ~base_exception() throw() {};
1294- /** Stores a comment string.
1295- **/
1296- void store(const std::string & s);
1297- /** Returns the value stored at exception creation.
1298- **/
1299- std::string comment();
1300- /** Returns the unix time the exception was created.
1301- **/
1302- unsigned long int creation_time();
1303+class base_exception: public std::exception
1304+{
1305+protected:
1306+ typedef std::chrono::high_resolution_clock myclock;
1307+ typedef std::chrono::high_resolution_clock::time_point mark;
1308+ typedef std::chrono::microseconds ms;
1309+ mark created {myclock::now()};
1310+ std::string _text;
1311+
1312+public:
1313+ /// NOP virtual distructor for safe inheritance
1314+ virtual ~base_exception() throw() {};
1315+ /** Stores a comment string.
1316+ **/
1317+ void store(const std::string & s) { _text = s; };
1318+ /** Returns the value stored at exception creation.
1319+ **/
1320+ std::string comment() { return _text; };
1321+ /** Returns the time the exception was created.
1322+ **/
1323+ mark creation_time() { return created; };
1324+ /** Returns the age of the exception
1325+ **/
1326+ ms age_in_ms()
1327+ {
1328+ return std::chrono::duration_cast<ms>(myclock::now() - created);
1329+ };
1330 };
1331
1332-// Thrown by gsub() in cases of unexpected error.
1333+// Thrown by gsub() in cases of unexpectaed error.
1334 class gsub_exception: public nrtb::base_exception {};
1335 // Thrown by split() in cases of unexpected error.
1336 class split_exception: public nrtb::base_exception {};
1337
1338=== modified file 'cpp/common/common_rl/common_rl_test.cpp'
1339--- obsolete/Cpp/common/common_rl/common_rl_test.cpp 2011-07-21 22:14:53 +0000
1340+++ cpp/common/common_rl/common_rl_test.cpp 2013-08-09 21:47:12 +0000
1341@@ -18,6 +18,7 @@
1342
1343 #include "common.h"
1344 #include <iostream>
1345+#include <unistd.h>
1346
1347 using namespace std;
1348
1349@@ -96,6 +97,23 @@
1350 "nrtb::http_unhex()",
1351 nrtb::http_unhex("%4D%69%58%65%44%63%41%73%45") == tstr);
1352
1353+ try
1354+ {
1355+ nrtb::base_exception e;
1356+ e.store("Test code");
1357+ usleep(100);
1358+ throw e;
1359+ }
1360+ catch (nrtb::base_exception & e)
1361+ {
1362+ returnme += report_test(
1363+ "nrtb::base_exception::comment()",
1364+ e.comment() == "Test code");
1365+ returnme += report_test(
1366+ "nrtb::base_exception::age_in_ms()",
1367+ e.age_in_ms().count() > 100 );
1368+ };
1369+
1370 cout << "=== nrtb::common_rl unit test complete ===" << endl;
1371 return returnme;
1372 };
1373\ No newline at end of file
1374
1375=== modified file 'cpp/common/confreader/Makefile'
1376--- obsolete/Cpp/common/confreader/Makefile 2012-04-06 12:19:37 +0000
1377+++ cpp/common/confreader/Makefile 2013-08-09 21:47:12 +0000
1378@@ -16,6 +16,8 @@
1379 #
1380 #***********************************************
1381
1382+switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP
1383+
1384 lib: conftest
1385 @rm -f conf_test.log
1386 @./conftest test=1 test2-2 test2=71.837486 test3="jack danials" --doit
1387@@ -26,12 +28,12 @@
1388
1389 confreader.o: confreader.h confreader.cpp Makefile
1390 @rm -f confreader.o
1391- g++ -c confreader.cpp -I../include -std=gnu++0x
1392+ g++ -c confreader.cpp -I../include ${switches}
1393
1394 conftest: confreader.o conftest.cpp
1395 @rm -f conftest
1396- g++ -c conftest.cpp -I../include -std=gnu++0x
1397- g++ -o conftest conftest.o confreader.o ../obj/common.o ../obj/log_setup.o ../obj/base_thread.o -lpthread -lPocoFoundation -lPocoUtil -std=gnu++0x
1398+ g++ -c conftest.cpp -I../include ${switches}
1399+ g++ -o conftest conftest.o confreader.o ../obj/common.o ../obj/logger.o -lpthread ${switches}
1400
1401 clean:
1402 @rm -rvf *.o conftest ../include/confreader.h ../obj/confreader.o conf_test.log
1403
1404=== modified file 'cpp/common/confreader/confreader.cpp'
1405--- obsolete/Cpp/common/confreader/confreader.cpp 2011-08-13 15:06:08 +0000
1406+++ cpp/common/confreader/confreader.cpp 2013-08-09 21:47:12 +0000
1407@@ -21,206 +21,198 @@
1408 #include "confreader.h"
1409 #include <fstream>
1410 #include <iostream>
1411-#include <common.h>
1412-#include "Poco/Logger.h"
1413
1414 using namespace std;
1415 using namespace nrtb;
1416
1417-const std::string logname = "conf_reader";
1418-
1419 namespace nrtb
1420 {
1421
1422 conf_reader::conf_reader()
1423 {
1424- Poco::Logger& logger = Poco::Logger::get(logname);
1425- logger.information("conf_reader instanciated.");
1426+ // nop constructor
1427 };
1428
1429-conf_reader::~conf_reader() {};
1430+conf_reader::~conf_reader()
1431+{
1432+ // nop destructor
1433+};
1434
1435 unsigned int conf_reader::read(const std::string & _filename, bool _clear)
1436 {
1437- Poco::Logger& logger = Poco::Logger::get(logname);
1438- logger.information("Reading from \"" + _filename + "\".");
1439- if (_filename != "") { filename = _filename; };
1440- if (filename != "")
1441- {
1442- try
1443- {
1444- ifstream cfile(filename.c_str());
1445- if (!cfile) throw base_exception();
1446- if (_clear) values.clear();
1447- // read the file line by line, ignoring comments.
1448- char inbuff[16*1024];
1449- while (cfile)
1450- {
1451- cfile.getline(inbuff, 16*1024);
1452- string in = inbuff;
1453- // truncate at the start of a comment.
1454- unsigned long int where = in.find("#");
1455- while (where != string::npos)
1456- {
1457- if (in[where-1] == '\\')
1458- {
1459- // comment char was escaped.. ignore.
1460- where = in.find("#",where+1);
1461- }
1462- else
1463- {
1464- // truncate the string at this point.
1465- in.erase(where);
1466- where = string::npos;
1467- };
1468- };
1469- // see if we can parse what's left.
1470- in = trim(in);
1471- unsigned long int split_point = in.find_first_of("\t ");
1472- if (split_point != string::npos)
1473- {
1474- // okay.. get the fields.
1475- pair arg;
1476- arg.first = gsub(trim(in.substr(0,split_point)),"\\#","#");
1477- arg.second = gsub(trim(in.substr(split_point)),"\\#","#");
1478- // is this an include directive?
1479- if (arg.first == "*INCLUDE")
1480- {
1481- read(arg.second,false);
1482- }
1483- else if (arg.first != "")
1484- {
1485- values.insert(arg);
1486- };
1487- };
1488- };
1489- }
1490- catch (...)
1491- {
1492- logger.warning("Problems reading configuration file \""
1493- + filename + "\"; data may be incomplete.");
1494- }
1495- };
1496- return values.size();
1497+ if (_filename != "") { filename = _filename; };
1498+ if (filename != "")
1499+ {
1500+ try
1501+ {
1502+ ifstream cfile(filename.c_str());
1503+ if (!cfile) throw base_exception();
1504+ if (_clear) values.clear();
1505+ // read the file line by line, ignoring comments.
1506+ char inbuff[16*1024];
1507+ while (cfile)
1508+ {
1509+ cfile.getline(inbuff, 16*1024);
1510+ string in = inbuff;
1511+ // truncate at the start of a comment.
1512+ unsigned long int where = in.find("#");
1513+ while (where != string::npos)
1514+ {
1515+ if (in[where-1] == '\\')
1516+ {
1517+ // comment char was escaped.. ignore.
1518+ where = in.find("#",where+1);
1519+ }
1520+ else
1521+ {
1522+ // truncate the string at this point.
1523+ in.erase(where);
1524+ where = string::npos;
1525+ };
1526+ };
1527+ // see if we can parse what's left.
1528+ in = trim(in);
1529+ unsigned long int split_point = in.find_first_of("\t ");
1530+ if (split_point != string::npos)
1531+ {
1532+ // okay.. get the fields.
1533+ pair arg;
1534+ arg.first = gsub(trim(in.substr(0,split_point)),"\\#","#");
1535+ arg.second = gsub(trim(in.substr(split_point)),"\\#","#");
1536+ // is this an include directive?
1537+ if (arg.first == "*INCLUDE")
1538+ {
1539+ read(arg.second,false);
1540+ }
1541+ else if (arg.first != "")
1542+ {
1543+ values.insert(arg);
1544+ };
1545+ };
1546+ };
1547+ }
1548+ catch (...)
1549+ {
1550+ cerr << "WARNING:Problems reading configuration file \""
1551+ << filename << "\"; data may be incomplete.";
1552+ }
1553+ };
1554+ return values.size();
1555 };
1556
1557 unsigned int conf_reader::read(int argc, char * argv[],
1558 const string & _filename)
1559 {
1560- Poco::Logger& logger = Poco::Logger::get(logname);
1561- logger.information("Reading from command line.");
1562- clear();
1563- filename = _filename;
1564- value_list_type cvars;
1565- // read values from the command line first.
1566- for (int i = 0; i < argc; i++)
1567- {
1568- string instring = argv[i];
1569- if (i == 0)
1570- {
1571- instring = "__exec_name="+instring;
1572- };
1573- strlist t = split(instring,'=');
1574- if (t.size() > 0)
1575- {
1576- // build the new insert pair;
1577- pair newval;
1578- newval.first = t[0];
1579- // assemble the value
1580- // (allows for including "=" in the argument)
1581- for (unsigned int l = 1; l < t.size(); l++)
1582- {
1583- newval.second += t[l];
1584- if (l < (t.size() -1) )
1585- {
1586- newval.second += "=";
1587- };
1588- };
1589- // store this in the list
1590- trim(newval.first);
1591- trim(newval.second);
1592- cvars.insert(newval);
1593- // is this a config file name?
1594- if (newval.first == "configfile")
1595- {
1596- filename = newval.second;
1597- };
1598- };
1599- }; // read the command line arguments.
1600- // read the file args if any.
1601- read(filename,false);
1602- // override the first instance of any value found in configs
1603- // or insert as appropriate.
1604- iterator c = cvars.begin();
1605- iterator e = cvars.end();
1606- while (c != e)
1607- {
1608- iterator here = values.find(c->first);
1609- if (here != values.end())
1610- {
1611- here->second = c->second;
1612- }
1613- else
1614- {
1615- values.insert(*c);
1616- };
1617- c++;
1618+ clear();
1619+ filename = _filename;
1620+ value_list_type cvars;
1621+ // read values from the command line first.
1622+ for (int i = 0; i < argc; i++)
1623+ {
1624+ string instring = argv[i];
1625+ if (i == 0)
1626+ {
1627+ instring = "__exec_name="+instring;
1628+ };
1629+ strlist t = split(instring,'=');
1630+ if (t.size() > 0)
1631+ {
1632+ // build the new insert pair;
1633+ pair newval;
1634+ newval.first = t[0];
1635+ // assemble the value
1636+ // (allows for including "=" in the argument)
1637+ for (unsigned int l = 1; l < t.size(); l++)
1638+ {
1639+ newval.second += t[l];
1640+ if (l < (t.size() -1) )
1641+ {
1642+ newval.second += "=";
1643 };
1644- std::stringstream message;
1645- message << "Read " << values.size() << " parameters.";
1646- logger.information(message.str());
1647- return values.size();
1648+ };
1649+ // store this in the list
1650+ trim(newval.first);
1651+ trim(newval.second);
1652+ cvars.insert(newval);
1653+ // is this a config file name?
1654+ if (newval.first == "configfile")
1655+ {
1656+ filename = newval.second;
1657+ };
1658+ };
1659+ }; // read the command line arguments.
1660+ // read the file args if any.
1661+ read(filename,false);
1662+ // override the first instance of any value found in configs
1663+ // or insert as appropriate.
1664+ iterator c = cvars.begin();
1665+ iterator e = cvars.end();
1666+ while (c != e)
1667+ {
1668+ iterator here = values.find(c->first);
1669+ if (here != values.end())
1670+ {
1671+ here->second = c->second;
1672+ }
1673+ else
1674+ {
1675+ values.insert(*c);
1676+ };
1677+ c++;
1678+ };
1679+ cout << "Read " << values.size() << " parameters.";
1680+ return values.size();
1681 };
1682
1683 void conf_reader::clear()
1684 {
1685- values.clear();
1686+ values.clear();
1687 };
1688
1689 conf_reader::iterator conf_reader::begin()
1690 {
1691- return values.begin();
1692+ return values.begin();
1693 };
1694
1695 conf_reader::iterator conf_reader::end()
1696 {
1697- return values.end();
1698+ return values.end();
1699 };
1700
1701 bool conf_reader::empty()
1702 {
1703- return values.empty();
1704+ return values.empty();
1705 };
1706
1707 unsigned int conf_reader::size()
1708 {
1709- return values.size();
1710+ return values.size();
1711 };
1712
1713 strlist conf_reader::all(const std::string & key)
1714 {
1715- strlist returnme;
1716- iterator current = values.find(key);
1717- iterator e = values.end();
1718- while ((current != e) && (current->first == key))
1719- {
1720- returnme.push_back(current->second);
1721- current++;
1722- };
1723- return returnme;
1724+ strlist returnme;
1725+ iterator current = values.find(key);
1726+ iterator e = values.end();
1727+ while ((current != e) && (current->first == key))
1728+ {
1729+ returnme.push_back(current->second);
1730+ current++;
1731+ };
1732+ return returnme;
1733 };
1734
1735 string conf_reader::operator [] (const std::string & key)
1736 {
1737- iterator res = values.find(key);
1738- string returnme = "";
1739- if (res != values.end()) returnme = res->second;
1740- return returnme;
1741+ iterator res = values.find(key);
1742+ string returnme = "";
1743+ if (res != values.end()) returnme = res->second;
1744+ return returnme;
1745 };
1746
1747 bool conf_reader::exists(const std::string & key)
1748 {
1749- return (values.find(key) != values.end());
1750+ return (values.find(key) != values.end());
1751 };
1752
1753 } // namespace nrtb
1754
1755=== modified file 'cpp/common/confreader/confreader.h'
1756--- obsolete/Cpp/common/confreader/confreader.h 2011-08-13 15:06:08 +0000
1757+++ cpp/common/confreader/confreader.h 2013-08-09 21:47:12 +0000
1758@@ -16,8 +16,8 @@
1759
1760 **********************************************/
1761
1762-#ifndef ricklib_confreader_h
1763-#define ricklib_confreader_h
1764+#ifndef nrtb_confreader_h
1765+#define nrtb_confreader_h
1766
1767 #include <string.h>
1768 #include <map>
1769@@ -25,13 +25,13 @@
1770 #include <string>
1771 #include <fstream>
1772 #include <boost/lexical_cast.hpp>
1773+#include <common.h>
1774+#include <logger.h>
1775 #include <singleton.h>
1776
1777-namespace nrtb
1778+namespace nrtb
1779 {
1780
1781-typedef std::vector<std::string> strlist;
1782-
1783 /** Reads command line and configuration file information.
1784 **
1785 ** For this NRTB implementation, this class is implemented as
1786@@ -47,241 +47,242 @@
1787 **/
1788 class conf_reader
1789 {
1790- private:
1791- typedef std::multimap<std::string,std::string> value_list_type;
1792- value_list_type values;
1793- std::string filename;
1794- protected:
1795- /** Reads and parses a configuration file.
1796- **
1797- ** Returns the number of values stored.
1798- **
1799- ** The optional parameter _clear when true clears the currently
1800- ** stored list of values. if false the new values read will be added
1801- ** to the existing list.
1802- **
1803- ** If the file named can not be processed completely, a warning
1804- ** message is published to cerr.
1805- **
1806- ** Configuration files are defined as follows.
1807- **
1808- ** 1. Files are read line by line. No value can cross a newline
1809- ** (and at least in this version) or include one. The good
1810- ** news is that you are allowed up to 16k for each line.
1811- **
1812- ** 2. values are specifed in name/value pairs, one per line, with
1813- ** the name first, followed by whitespace, followed by the
1814- ** value. Values may include whitespace. All leading and trailing
1815- ** whitespace is removed from both the name and the value.
1816- **
1817- ** 3. Comments start with a \# symbol; all text following a \# is
1818- ** ignored. If you need to use \# in a name or value, escape
1819- ** it with a backslash instead.
1820- **
1821- ** 4. Duplicate names are allowed.
1822- **
1823- ** 5. Names without values will be stored with "" as the value.
1824- **
1825- ** 6. A configuration file may include another configuration file
1826- ** automatically by the use of the "*INCLUDE" reserved name.
1827- ** When this name is found, it's value is used as the name of
1828- ** the new file to be read.
1829- **/
1830- unsigned int read(const std::string & _filename = "", bool _clear=true);
1831- public:
1832- /// conf_reader iterator, points to a conf_reader::pair
1833- typedef value_list_type::iterator iterator;
1834- /// conf_reader::pair is a std::pair<string,string>
1835- typedef std::pair<std::string,std::string> pair;
1836- /** No argument constructor; actually calls read() without a filename.
1837- **/
1838- conf_reader();
1839- /** NOP virtual destructor to allow safe inheritance.
1840- **/
1841- virtual ~conf_reader();
1842- /** Reads and parses the command line and the provided file.
1843- **
1844- ** Returns the number of values stored. argc and argv are, of
1845- ** course the same names you used as arguments to main(). Therefore
1846- ** you can easily read all command line and configuration file
1847- ** values like this:
1848- **
1849- ** int main(int argc, char* argv[])
1850- **
1851- ** {
1852- **
1853- ** conf_reader config;
1854- **
1855- ** config.read(argc,argv,"my_conf_file");
1856- **
1857- ** ...
1858- **
1859- ** }
1860- **
1861- ** See read(filename,_clear) for a discription of how configuration
1862- ** files are structured and parsed. This method unconditionally
1863- ** clears the existing value list before starting. For command line
1864- ** arguments the following rules are true.
1865- **
1866- ** 1. The executable name (argv[0]) is stored as a value with the
1867- ** name "__exec_name".
1868- **
1869- ** 2. Command line arguments of the form "name=value" are parsed
1870- ** stored as named values.
1871- **
1872- ** 3. All other command line arguments are stored as names with
1873- ** value = "".
1874- **
1875- ** 4. A command line argument of form "configfile=filename" will
1876- ** override the filename supplied as an argument to this method.
1877- **
1878- ** 5. In the case of duplicate command line arguments, the last one
1879- ** specified wins.
1880- **
1881- ** 6. In the case of names in the configuration file duplicating
1882- ** names from the command line, the values from the command line
1883- ** dominate. If there were multiple values for a given name
1884- ** specified in the file, only the first one (the one returned by
1885- ** the "[]" operator or get<>() method) is overridden.
1886- **/
1887- unsigned int read(int argc, char* argv[],
1888- const std::string & _filename);
1889- /// clears the name/value list.
1890- void clear();
1891- /// returns an iterator to the first item in the list.
1892- iterator begin();
1893- /// returns an iterator one past the end of the list.
1894- iterator end();
1895- /// True if there are no values, false otherwise.
1896- bool empty();
1897- /// Returns the number of values stored.
1898- unsigned int size();
1899- /** Returns the string value matching the supplied name.
1900- **
1901- ** NOTE: the use of get<T>(key) or get<T>(key,default) is preferred.
1902- ** This method is public to allow for specialized handling in the
1903- ** rare cases where it may be required.
1904- **
1905- ** If there are no matching names, "" is returned. Be aware that
1906- ** "" is a valid value, so you can not use this to verify that
1907- ** a given name was defined. Use exists() for that.
1908- **/
1909- std::string operator [] (const std::string & key);
1910- /** Returns all values associated with the supplied name.
1911- **
1912- ** NOTE: the use of getall<T>(key) is preferred. This method is
1913- ** public to allow specialized handling in rare case where it
1914- ** may be required.
1915- **
1916- ** If there are no values defined the strlist will be empty.
1917- **/
1918- strlist all(const std::string & key);
1919- /// True if the name exists, false otherwise.
1920- bool exists(const std::string & key);
1921- /** Use this to get all matching values.
1922- **
1923- ** Usage:
1924- **
1925- ** vector<type> mylist = conf_reader_object.getall<type>(key);
1926- **
1927- ** type can be any standard type (string, int, double, etc.) or any
1928- ** type for which the ">>" stream operator is defined. All values
1929- ** with matching names that can map to the requested type will be
1930- ** returned. Any that do not map will not be returned.
1931- **/
1932- template < class T >
1933- typename std::vector<T> getall(const std::string & key);
1934- /** Use this to get the matching value.
1935- **
1936- ** Useage:
1937- **
1938- ** type myvar = get<type>(key);
1939- **
1940- ** type can be any standard type (string, int, double, etc.) or any
1941- ** type for which the ">>" stream operator is defined. The return
1942- ** value is initialized to all zeros if no matching name is found or
1943- ** if the first value with that name does not map to the requested
1944- ** type. For the numeric types that results in zero being returned,
1945- ** but be aware that more complex object may be in non-sensible
1946- ** states if they were not found or could not map. Use exists() to
1947- ** verify the existance of a given name if needed.
1948- **/
1949- template < class T >
1950- T get(const std::string & key);
1951- /** Returns the value for the requested key, or the supplied default.
1952- **
1953- ** Works exactly like get<>() with the exception that if the key
1954- ** is not found in the list, the user supplied default value is
1955- ** returned instead of 0 or an empty string. If the value exists but
1956- ** can not map to the requested type, 0 or an empty string is
1957- ** returned for the standard types.
1958- **/
1959- template <class T>
1960- T get(const std::string & key, const T & def);
1961+private:
1962+ typedef std::multimap<std::string,std::string> value_list_type;
1963+ value_list_type values;
1964+public:
1965+ /// conf_reader iterator, points to a conf_reader::pair
1966+ typedef value_list_type::iterator iterator;
1967+ /// conf_reader::pair is a std::pair<string,string>
1968+ typedef std::pair<std::string,std::string> pair;
1969+ /** No argument constructor; actually calls read() without a filename.
1970+ **/
1971+ conf_reader();
1972+ /** NOP virtual destructor to allow safe inheritance.
1973+ **/
1974+ virtual ~conf_reader();
1975+ /** Reads and parses the command line and the provided file.
1976+ **
1977+ ** Returns the number of values stored. argc and argv are, of
1978+ ** course the same names you used as arguments to main(). Therefore
1979+ ** you can easily read all command line and configuration file
1980+ ** values like this:
1981+ **
1982+ ** int main(int argc, char* argv[])
1983+ **
1984+ ** {
1985+ **
1986+ ** conf_reader config;
1987+ **
1988+ ** config.read(argc,argv,"my_conf_file");
1989+ **
1990+ ** ...
1991+ **
1992+ ** }
1993+ **
1994+ ** See read(filename,_clear) for a discription of how configuration
1995+ ** files are structured and parsed. This method unconditionally
1996+ ** clears the existing value list before starting. For command line
1997+ ** arguments the following rules are true.
1998+ **
1999+ ** 1. The executable name (argv[0]) is stored as a value with the
2000+ ** name "__exec_name".
2001+ **
2002+ ** 2. Command line arguments of the form "name=value" are parsed
2003+ ** stored as named values.
2004+ **
2005+ ** 3. All other command line arguments are stored as names with
2006+ ** value = "".
2007+ **
2008+ ** 4. A command line argument of form "configfile=filename" will
2009+ ** override the filename supplied as an argument to this method.
2010+ **
2011+ ** 5. In the case of duplicate command line arguments, the last one
2012+ ** specified wins.
2013+ **
2014+ ** 6. In the case of names in the configuration file duplicating
2015+ ** names from the command line, the values from the command line
2016+ ** dominate. If there were multiple values for a given name
2017+ ** specified in the file, only the first one (the one returned by
2018+ ** the "[]" operator or get<>() method) is overridden.
2019+ **/
2020+ unsigned int read(int argc, char* argv[],
2021+ const std::string & _filename);
2022+ /// clears the name/value list.
2023+ void clear();
2024+ /// returns an iterator to the first item in the list.
2025+ iterator begin();
2026+ /// returns an iterator one past the end of the list.
2027+ iterator end();
2028+ /// True if there are no values, false otherwise.
2029+ bool empty();
2030+ /// Returns the number of values stored.
2031+ unsigned int size();
2032+ /** Returns the string value matching the supplied name.
2033+ **
2034+ ** NOTE: the use of get<T>(key) or get<T>(key,default) is preferred.
2035+ ** This method is public to allow for specialized handling in the
2036+ ** rare cases where it may be required.
2037+ **
2038+ ** If there are no matching names, "" is returned. Be aware that
2039+ ** "" is a valid value, so you can not use this to verify that
2040+ ** a given name was defined. Use exists() for that.
2041+ **/
2042+ std::string operator [] (const std::string & key);
2043+ /** Returns all values associated with the supplied name.
2044+ **
2045+ ** NOTE: the use of getall<T>(key) is preferred. This method is
2046+ ** public to allow specialized handling in rare case where it
2047+ ** may be required.
2048+ **
2049+ ** If there are no values defined the strlist will be empty.
2050+ **/
2051+ strlist all(const std::string & key);
2052+ /// True if the name exists, false otherwise.
2053+ bool exists(const std::string & key);
2054+ /** Use this to get all matching values.
2055+ **
2056+ ** Usage:
2057+ **
2058+ ** vector<type> mylist = conf_reader_object.getall<type>(key);
2059+ **
2060+ ** type can be any standard type (string, int, double, etc.) or any
2061+ ** type for which the ">>" stream operator is defined. All values
2062+ ** with matching names that can map to the requested type will be
2063+ ** returned. Any that do not map will not be returned.
2064+ **/
2065+ template < class T >
2066+ typename std::vector<T> getall(const std::string & key);
2067+ /** Use this to get the matching value.
2068+ **
2069+ ** Useage:
2070+ **
2071+ ** type myvar = get<type>(key);
2072+ **
2073+ ** type can be any standard type (string, int, double, etc.) or any
2074+ ** type for which the ">>" stream operator is defined. The return
2075+ ** value is initialized to all zeros if no matching name is found or
2076+ ** if the first value with that name does not map to the requested
2077+ ** type. For the numeric types that results in zero being returned,
2078+ ** but be aware that more complex object may be in non-sensible
2079+ ** states if they were not found or could not map. Use exists() to
2080+ ** verify the existance of a given name if needed.
2081+ **/
2082+ template < class T >
2083+ T get(const std::string & key);
2084+ /** Returns the value for the requested key, or the supplied default.
2085+ **
2086+ ** Works exactly like get<>() with the exception that if the key
2087+ ** is not found in the list, the user supplied default value is
2088+ ** returned instead of 0 or an empty string. If the value exists but
2089+ ** can not map to the requested type, 0 or an empty string is
2090+ ** returned for the standard types.
2091+ **/
2092+ template <class T>
2093+ T get(const std::string & key, const T & def);
2094+private:
2095+ std::string filename;
2096+protected:
2097+ /** Reads and parses a configuration file.
2098+ **
2099+ ** Returns the number of values stored.
2100+ **
2101+ ** The optional parameter _clear when true clears the currently
2102+ ** stored list of values. if false the new values read will be added
2103+ ** to the existing list.
2104+ **
2105+ ** If the file named can not be processed completely, a warning
2106+ ** message is published to cerr.
2107+ **
2108+ ** Configuration files are defined as follows.
2109+ **
2110+ ** 1. Files are read line by line. No value can cross a newline
2111+ ** (and at least in this version) or include one. The good
2112+ ** news is that you are allowed up to 16k for each line.
2113+ **
2114+ ** 2. values are specifed in name/value pairs, one per line, with
2115+ ** the name first, followed by whitespace, followed by the
2116+ ** value. Values may include whitespace. All leading and trailing
2117+ ** whitespace is removed from both the name and the value.
2118+ **
2119+ ** 3. Comments start with a \# symbol; all text following a \# is
2120+ ** ignored. If you need to use \# in a name or value, escape
2121+ ** it with a backslash instead.
2122+ **
2123+ ** 4. Duplicate names are allowed.
2124+ **
2125+ ** 5. Names without values will be stored with "" as the value.
2126+ **
2127+ ** 6. A configuration file may include another configuration file
2128+ ** automatically by the use of the "*INCLUDE" reserved name.
2129+ ** When this name is found, it's value is used as the name of
2130+ ** the new file to be read.
2131+ **/
2132+ unsigned int read(const std::string & _filename = "", bool _clear=true);
2133 };
2134
2135 typedef singleton<conf_reader> global_conf_reader;
2136
2137 template < class T >
2138- typename std::vector<T> conf_reader::getall(const std::string & key)
2139-{
2140- strlist tvals = all(key);
2141- std::vector<T> returnme;
2142- if (typeid(T) == typeid(std::string))
2143- {
2144- // T is a std::string.. we can do this quickly.
2145- strlist * wl = (strlist *) &returnme;
2146- *wl = tvals;
2147- }
2148- else
2149- {
2150- // T is non-string.. will require more playing around.
2151- unsigned int limit = tvals.size();
2152- for (unsigned int i = 0; i < limit; i++)
2153- {
2154- try
2155- {
2156- returnme.push_back(boost::lexical_cast<T>(tvals[i]));
2157- }
2158- catch (...) {};
2159- };
2160- };
2161- return returnme;
2162-};
2163-
2164-template < class T >
2165- T conf_reader::get(const std::string & key)
2166-{
2167- conf_reader & me = *this;
2168- std::string tval = me[key];
2169- T returnme;
2170- // initialize the return value to nulls
2171- // Needed for the numeric types, but bad for strings.
2172- if (typeid(T) != typeid(std::string))
2173- {
2174- // null out the working area (death for strings!)
2175- memset(&returnme,0,sizeof(T));
2176- };
2177- // This does appear to work for all the standard types.
2178- if (tval != "")
2179- {
2180- try
2181- {
2182- returnme = boost::lexical_cast<T>(tval);
2183- }
2184- catch (...) {};
2185- };
2186- return returnme;
2187-};
2188-
2189-template < class T >
2190- T conf_reader::get(const std::string & key, const T & def)
2191-{
2192- if (exists(key)) { return get<T>(key); }
2193- else { return def; };
2194+ typename std::vector<T> conf_reader::getall(const std::string & key)
2195+{
2196+ strlist tvals = all(key);
2197+ std::vector<T> returnme;
2198+ if (typeid(T) == typeid(std::string))
2199+ {
2200+ // T is a std::string.. we can do this quickly.
2201+ strlist * wl = (strlist *) &returnme;
2202+ *wl = tvals;
2203+ }
2204+ else
2205+ {
2206+ // T is non-string.. will require more playing around.
2207+ unsigned int limit = tvals.size();
2208+ for (unsigned int i = 0; i < limit; i++)
2209+ {
2210+ try
2211+ {
2212+ returnme.push_back(boost::lexical_cast<T>(tvals[i]));
2213+ }
2214+ catch (...) {};
2215+ };
2216+ };
2217+ return returnme;
2218+};
2219+
2220+template < class T >
2221+ T conf_reader::get(const std::string & key)
2222+{
2223+ conf_reader & me = *this;
2224+ std::string tval = me[key];
2225+ T returnme;
2226+ // initialize the return value to nulls
2227+ // Needed for the numeric types, but bad for strings.
2228+ if (typeid(T) != typeid(std::string))
2229+ {
2230+ // null out the working area (death for strings!)
2231+ memset(&returnme,0,sizeof(T));
2232+ };
2233+ // This does appear to work for all the standard types.
2234+ if (tval != "")
2235+ {
2236+ try
2237+ {
2238+ returnme = boost::lexical_cast<T>(tval);
2239+ }
2240+ catch (...) {};
2241+ };
2242+ return returnme;
2243+};
2244+
2245+template < class T >
2246+ T conf_reader::get(const std::string & key, const T & def)
2247+{
2248+ if (exists(key)) { return get<T>(key); }
2249+ else { return def; };
2250 };
2251
2252 }; // namespace nrtb
2253
2254-#endif // ricklib_confreader_h
2255+#endif // nrtb_confreader_h
2256
2257
2258=== modified file 'cpp/common/confreader/conftest.cpp'
2259--- obsolete/Cpp/common/confreader/conftest.cpp 2011-08-13 15:06:08 +0000
2260+++ cpp/common/confreader/conftest.cpp 2013-08-09 21:47:12 +0000
2261@@ -19,54 +19,56 @@
2262 /* confreader test program */
2263
2264 #include "confreader.h"
2265-#include <log_setup.h>
2266 #include <iostream>
2267-#include "Poco/Logger.h"
2268-#include "Poco/SimpleFileChannel.h"
2269-//#include "Poco/AutoPtr.h"
2270
2271 using namespace nrtb;
2272 using namespace std;
2273
2274+log_queue lq;
2275+log_file_writer writer(lq, "conf_test.log");
2276+
2277 int main(int argc, char* argv[])
2278 {
2279 bool set_if_failed = false;
2280- setup_global_logging("conf_test.log");
2281- Poco::Logger & log = Poco::Logger::get("conftest");
2282- log.information("=-=-=-=-=-= conftest Init =-=-=-=-=-=-=");
2283- global_conf_reader & config = global_conf_reader::get_instance();
2284+ log_recorder log("config_test",lq);
2285+ log.info("=-=-=-=-=-= conftest Init =-=-=-=-=-=-=");
2286+ conf_reader & config = global_conf_reader::get_reference();
2287+
2288 try
2289 {
2290- log.information("Starting read");
2291- config.read(argc,argv,"test.config");
2292+ log.info("Starting read");
2293+ config.read(argc,argv,"test.config");
2294 }
2295 catch (...)
2296 {
2297- set_if_failed = true;
2298- cerr << "Failed reading the configuration." << endl;
2299+ set_if_failed = true;
2300+ cerr << "Failed reading the configuration." << endl;
2301+ log.severe("Failed reading the configuration.");
2302 };
2303 if (config.size() != 12)
2304 {
2305- set_if_failed = true;
2306- cerr << "Did not find 12 parameters." << endl;
2307+ set_if_failed = true;
2308+ cerr << "Did not find 12 parameters." << endl;
2309+ log.severe("Did not find 12 parameters.");
2310 };
2311 // iterator test
2312 try
2313 {
2314- conf_reader::iterator c = config.begin();
2315- conf_reader::iterator e = config.end();
2316- while (c != e)
2317- {
2318- cout << "\t\"" << c->first << "\"=\"" << c->second
2319- << "\"" << endl;
2320- c++;
2321- };
2322+ conf_reader::iterator c = config.begin();
2323+ conf_reader::iterator e = config.end();
2324+ while (c != e)
2325+ {
2326+ cout << "\t\"" << c->first << "\"=\"" << c->second
2327+ << "\"" << endl;
2328+ c++;
2329+ };
2330 }
2331 catch (...)
2332 {
2333- set_if_failed = true;
2334- cerr << "Iterator test failed." << endl;
2335- };
2336+ set_if_failed = true;
2337+ cerr << "Iterator test failed." << endl;
2338+ log.severe("Iterator test failed.");
2339+};
2340 // template test.
2341 int test = config.get<int>("test",-1);
2342 int test2 = config.get<int>("test2",-1);
2343@@ -74,56 +76,60 @@
2344 double test4 = config.get<double>("test",-1);
2345 double test5 = config.get<double>("test2",-1);
2346 cout << "(int) test = " << test
2347- << "\n(int) test2 = " << test2
2348- << "\n(string) test3 = \"" << test3 << "\""
2349- << "\n(double) test = " << test4
2350- << "\n(double) test2 = " << test5
2351- << endl;
2352+ << "\n(int) test2 = " << test2
2353+ << "\n(string) test3 = \"" << test3 << "\""
2354+ << "\n(double) test = " << test4
2355+ << "\n(double) test2 = " << test5
2356+ << endl;
2357 if (
2358- (test != 1) or (test2 != 0)
2359- or (test3 != "jack danials")
2360- or (test4 != 1.0) or (test5 != 71.837486)
2361+ (test != 1) or (test2 != 0)
2362+ or (test3 != "jack danials")
2363+ or (test4 != 1.0) or (test5 != 71.837486)
2364 )
2365 {
2366- set_if_failed = true;
2367- cerr << "** Template test failed." << endl;
2368+ set_if_failed = true;
2369+ cerr << "** Template test failed." << endl;
2370+ log.severe("** Template test failed.");
2371 };
2372 // exists test.
2373 cout << "?var \"--doit\" exists? "
2374- << (config.exists("--doit") ? "Yes" : "No")
2375- << endl;
2376+ << (config.exists("--doit") ? "Yes" : "No")
2377+ << endl;
2378 if (!config.exists("--doit"))
2379 {
2380- set_if_failed = true;
2381- cerr << "exists() test failed." << endl;
2382+ set_if_failed = true;
2383+ cerr << "exists() test failed." << endl;
2384+ log.severe("exists() test failed.");
2385 };
2386 vector<int> intlist = config.getall<int>("test");
2387 cout << "valid int \"test\" values:" << endl;
2388 for (unsigned int i=0; i < intlist.size(); i++)
2389 {
2390- cout << "\t" << i << ": " << intlist[i] << endl;
2391+ cout << "\t" << i << ": " << intlist[i] << endl;
2392 };
2393 if (intlist.size() != 2)
2394 {
2395- set_if_failed = true;
2396- cerr << "getall<int>() did not find 2 parameters." << endl;
2397+ set_if_failed = true;
2398+ cerr << "getall<int>() did not find 2 parameters." << endl;
2399+ log.severe("getall<int>() did not find 2 parameters.");
2400 };
2401 strlist strings = config.getall<string>("test");
2402 cout << "valid string \"test\" values:" << endl;
2403 for (unsigned int i=0; i < strings.size(); i++)
2404 {
2405- cout << "\t" << i << ": " << strings[i] << endl;
2406+ cout << "\t" << i << ": " << strings[i] << endl;
2407 };
2408 if (strings.size() != 3)
2409 {
2410- set_if_failed = true;
2411- cerr << "getall<string>() did not find 3 parameters." << endl;
2412+ set_if_failed = true;
2413+ cerr << "getall<string>() did not find 3 parameters." << endl;
2414+ log.severe("getall<string>() did not find 3 parameters.");
2415 };
2416 if (set_if_failed)
2417 {
2418- cerr << "** ntrb::conf_reader UNIT TEST FAILED. **" << endl;
2419- log.fatal("UNIT TEST FAILED");
2420+ cerr << "** ntrb::conf_reader UNIT TEST FAILED. **" << endl;
2421+ log.critical("UNIT TEST FAILED");
2422 };
2423- log.information("Run Complete");
2424+ log.info("Run Complete");
2425 return set_if_failed;
2426 };
2427
2428=== modified file 'cpp/common/linear_queue/Makefile'
2429--- obsolete/Cpp/common/linear_queue/Makefile 2012-04-06 17:18:50 +0000
2430+++ cpp/common/linear_queue/Makefile 2013-08-09 21:47:12 +0000
2431@@ -16,6 +16,8 @@
2432 #
2433 #***********************************************
2434
2435+switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP
2436+
2437 lib: linear_queue_test
2438 @./linear_queue_test
2439 @cp -v linear_queue.h ../include
2440@@ -23,8 +25,8 @@
2441
2442 linear_queue_test: linear_queue.h linear_queue_test.cpp
2443 @rm -f linear_queue_test
2444- g++ -c linear_queue_test.cpp -I../include -std=gnu++0x
2445- g++ -o linear_queue_test linear_queue_test.o ../obj/common.o ../obj/base_thread.o -lpthread -std=gnu++0x
2446+ g++ -c linear_queue_test.cpp -I../include ${switches}
2447+ g++ -o linear_queue_test linear_queue_test.o -lpthread ${switches}
2448
2449 clean:
2450 @rm -rvf *.o linear_queue_test ../include/linear_queue.h *.log ../obj/linear_queue.o
2451
2452=== modified file 'cpp/common/linear_queue/linear_queue.h'
2453--- obsolete/Cpp/common/linear_queue/linear_queue.h 2011-10-07 00:01:15 +0000
2454+++ cpp/common/linear_queue/linear_queue.h 2013-08-09 21:47:12 +0000
2455@@ -19,9 +19,11 @@
2456 #ifndef nrtb_linear_queue_h
2457 #define nrtb_linear_queue_h
2458
2459-#include <iostream>
2460-#include <base_thread.h>
2461-#include <list>
2462+#include <atomic>
2463+#include <mutex>
2464+#include <condition_variable>
2465+#include <queue>
2466+#include <abs_queue.h>
2467
2468 namespace nrtb
2469 {
2470@@ -45,120 +47,7 @@
2471 * passing data to another set of threads.
2472 ********************************************************/
2473 template <class T>
2474-class linear_queue
2475-{
2476-public:
2477- class queue_not_ready: public base_exception {};
2478-
2479- /*********************************************
2480- * creates the queue with the specified
2481- * number of elements.
2482- *********************************************/
2483- linear_queue();
2484-
2485- /*********************************************
2486- * releases all items in the queue
2487- *********************************************/
2488- virtual ~linear_queue();
2489-
2490- /*********************************************
2491- * Puts an item in the queue.
2492- *********************************************/
2493- void push(T item);
2494-
2495- /*********************************************
2496- * Pops the next item off the queue, blocking
2497- * if needed until an item becomes available.
2498- *********************************************/
2499- T pop();
2500-
2501- /*********************************************
2502- * puts the queue in shutdown mode.
2503- *********************************************/
2504- void shutdown();
2505-
2506- // returns the number of items in the queue
2507- int size();
2508- // clears the buffer, data will be discarded.
2509- void clear();
2510-
2511-protected:
2512-
2513- std::list<T> buffer;
2514- cond_variable buffer_lock;
2515- bool ready;
2516-};
2517-
2518-template <class T>
2519-linear_queue<T>::linear_queue()
2520-{
2521- ready = true;
2522-};
2523-
2524-template <class T>
2525-linear_queue<T>::~linear_queue()
2526-{
2527-};
2528-
2529-template <class T>
2530-void linear_queue<T>::push(T item)
2531-{
2532- if (ready)
2533- {
2534- scope_lock lock(buffer_lock);
2535- buffer.push_back(item);
2536- buffer_lock.signal();
2537- }
2538- else
2539- {
2540- queue_not_ready e;
2541- throw e;
2542- }
2543-};
2544-
2545-template <class T>
2546-T linear_queue<T>::pop()
2547-{
2548- scope_lock lock(buffer_lock);
2549- while (buffer.empty() && ready)
2550- buffer_lock.wait();
2551- if (!ready)
2552- {
2553- queue_not_ready e;
2554- throw e;
2555- };
2556- T returnme = buffer.front();
2557- buffer.pop_front();
2558- return returnme;
2559-};
2560-
2561-template <class T>
2562-void linear_queue<T>::shutdown()
2563-{
2564- try
2565- {
2566- scope_lock lock(buffer_lock);
2567- ready = false;
2568- buffer_lock.broadcast_signal();
2569- buffer.clear();
2570- }
2571- catch (...) {}
2572-}
2573-
2574-
2575-template <class T>
2576-int linear_queue<T>::size()
2577-{
2578- scope_lock lock(buffer_lock);
2579- return buffer.size();
2580-};
2581-
2582-template <class T>
2583-void linear_queue<T>::clear()
2584-{
2585- scope_lock lock(buffer_lock);
2586- buffer.clear();
2587-};
2588+class linear_queue : public abs_queue<T,std::queue<T>> {};
2589
2590 } // namespace nrtb
2591
2592
2593=== modified file 'cpp/common/linear_queue/linear_queue_test.cpp'
2594--- obsolete/Cpp/common/linear_queue/linear_queue_test.cpp 2011-10-07 00:01:15 +0000
2595+++ cpp/common/linear_queue/linear_queue_test.cpp 2013-08-09 21:47:12 +0000
2596@@ -15,81 +15,45 @@
2597 along with NRTB. If not, see <http://www.gnu.org/licenses/>.
2598
2599 **********************************************/
2600-
2601+
2602+#include <unistd.h> // included for usleep()
2603 #include <string>
2604 #include <iostream>
2605 #include "linear_queue.h"
2606-#include <boost/shared_ptr.hpp>
2607+#include <memory>
2608+#include <atomic>
2609+#include <future>
2610
2611 using namespace nrtb;
2612 using namespace std;
2613
2614 typedef linear_queue<int> test_queue;
2615-typedef boost::shared_ptr<test_queue> queue_p;
2616+typedef shared_ptr<test_queue> queue_p;
2617
2618-class consumer_task: public thread
2619+int consumer_task(string name, queue_p input)
2620 {
2621-public:
2622-
2623- consumer_task(string n, queue_p buffer)
2624- {
2625- name = n;
2626- input = buffer;
2627- count = 0;
2628- };
2629-
2630- ~consumer_task()
2631- {
2632- cout << ">> in " << name << "::~consumer_task()" << endl;
2633- try
2634- {
2635- this->thread::~thread();
2636- input.reset();
2637- }
2638- catch (...) {};
2639- cout << "<< leaving " << name << "::~consumer_task()" << endl;
2640- };
2641-
2642- int get_count() { return count; };
2643-
2644- void run()
2645- {
2646- try
2647- {
2648- while (true)
2649- {
2650- int num = input->pop();
2651- {
2652- static mutex console;
2653- scope_lock lock(console);
2654- cout << name << " picked up " << num
2655- << endl;
2656- };
2657- count++;
2658- lastnum = num;
2659- yield();
2660- }
2661- }
2662- catch (...) {};
2663- };
2664-
2665-protected:
2666- // link to the feed queue
2667- queue_p input;
2668- // a name to report
2669- string name;
2670- // number of items processed
2671- int count;
2672- // last number caught
2673- int lastnum;
2674+ bool ready {true};
2675+ int count {0};
2676+ try
2677+ {
2678+ while (ready)
2679+ {
2680+ int num = input->pop();
2681+ count++;
2682+ usleep(1);
2683+ }
2684+ }
2685+ catch (...)
2686+ {
2687+ // exit if we get any exception.
2688+ ready = false;
2689+ };
2690+ return count;
2691 };
2692
2693-typedef boost::shared_ptr<consumer_task> task_p;
2694-
2695-
2696 int main()
2697 {
2698- int er_count = 0;
2699+ cout << "***** linear_queue unit test ******" << endl;
2700 /************************************************
2701 * Load queue and then cook it down...
2702 ***********************************************/
2703@@ -97,14 +61,15 @@
2704 queue_p q1(new test_queue());
2705 for (int i=0; i<100; i++)
2706 {
2707- q1->push(i);
2708+ q1->push(i);
2709 };
2710- // the queue should be loaded with 50-99
2711+ // the queue should be loaded with 0-99
2712 // attach a thread and process it.
2713- task_p p1(new consumer_task("task 1",q1));
2714- p1->start();
2715+ auto t1 = async(launch::async,consumer_task,"task 1",q1);
2716 while (q1->size()) usleep(100);
2717- cout << "cp 1 " << p1->get_count() << endl;
2718+ cout << "cp 1 "
2719+ << q1->in_count << ":"
2720+ << q1->out_count << endl;
2721 /************************************************
2722 * now that the preload is exhasted, shove items
2723 * in one at a time to make sure each is picked
2724@@ -112,40 +77,42 @@
2725 ***********************************************/
2726 for (int i=200; i<225; i++)
2727 {
2728- q1->push(i);
2729- usleep(100);
2730+ q1->push(i);
2731+ usleep(100);
2732 };
2733- cout << "cp 2 " << p1->get_count() << endl;
2734+ cout << "cp 2 "
2735+ << q1->in_count << ":"
2736+ << q1->out_count << endl;
2737 /************************************************
2738 * Last check; attach a second thread to the queue
2739 * and make sure both are servicing it.
2740 ***********************************************/
2741- task_p p2(new consumer_task("task 2",q1));
2742- p2->start();
2743+ auto t2 = async(launch::async,consumer_task,"task 2",q1);
2744 for (int i=300; i<325; i++)
2745 {
2746- q1->push(i);
2747+ q1->push(i);
2748 };
2749 while (q1->size()) usleep(100);
2750 // shut it all down
2751 q1->shutdown();
2752- p1->join();
2753- p2->join();
2754 // important numbers
2755- int tot_items = p1->get_count() + p2->get_count();
2756- int p1_items = p1->get_count() - 125;
2757- int p2_items = p2->get_count();
2758- // release she threads and queues.
2759- p1.reset();
2760- p2.reset();
2761+ int t1_count = t1.get();
2762+ int t2_count = t2.get();
2763+ int q1_in = q1->in_count;
2764+ int q1_out = q1->out_count;
2765+ // release the queues.
2766 q1.reset();
2767 // do some reporting.
2768 cout << "cp 3 "
2769- << tot_items
2770- << " [125 + (" << p1_items
2771- << " + " << p2_items
2772- << ")]" << endl;
2773- bool passed = (tot_items == 150);
2774+ << q1_in << ":" << q1_out
2775+ << " t1=" << t1_count
2776+ << " t2=" << t2_count
2777+ << endl;
2778+ bool passed = (q1_in == q1_out)
2779+ and (q1_out == (t1_count + t2_count));
2780+ cout << "***** linear_queue TEST "
2781+ << (passed ? "PASSED" : "FAILED")
2782+ << " ******" << endl;
2783 // inverted logic needed because 0 is good for
2784 // return codes.
2785 return !passed;
2786
2787=== modified file 'cpp/common/logger/Makefile'
2788--- obsolete/Cpp/common/logger/Makefile 2012-04-06 17:42:05 +0000
2789+++ cpp/common/logger/Makefile 2013-08-09 21:47:12 +0000
2790@@ -1,5 +1,5 @@
2791 #***********************************************
2792-#This file is part of the NRTB project (https://launchpad.net/nrtb).
2793+# This file is part of the NRTB project (https://launchpad.net/nrtb).
2794 #
2795 # NRTB is free software: you can redistribute it and/or modify
2796 # it under the terms of the GNU General Public License as published by
2797@@ -16,27 +16,25 @@
2798 #
2799 #***********************************************
2800
2801-lib: log_test
2802- @echo "Testing..."
2803- @rm -f test_output.log
2804- @./log_test
2805- @grep "Program run complete." test_output.log
2806- @cp -fv log_setup.h ../include
2807- @cp -fv log_setup.o ../obj
2808-
2809-
2810-log_setup.o: log_setup.h log_setup.cpp Makefile
2811- @rm -f log_setup.o
2812- g++ -c log_setup.cpp -I ../include -std=gnu++0x
2813-
2814-log_test: log_setup.o log_test.cpp Makefile
2815- @rm -vf log_test
2816- g++ -c log_test.cpp -I../include -std=gnu++0x
2817- g++ -o log_test log_setup.o log_test.o -lPocoFoundation -std=gnu++0x
2818-# g++ -g common_test.cpp -idirafter . -o common_test
2819+switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP
2820+
2821+lib: logger_test
2822+ @./logger_test
2823+ @cp -v logger.h ../include/
2824+ @cp -v logger.o ../obj/
2825+ @echo build complete
2826+
2827+logger_test: logger.o logger_test.cpp
2828+ @rm -f logger_test
2829+ g++ -c -O3 logger_test.cpp -I ../include ${switches}
2830+ g++ -o logger_test logger_test.o logger.o -lpthread ${switches}
2831+
2832+
2833+logger.o: logger.cpp logger.h Makefile
2834+ @rm -f logger.o
2835+ g++ -c -O3 logger.cpp -I ../include ${switches}
2836
2837 clean:
2838- @rm -vf *.o log_test ../include/log_setup.h ../obj/log_setup.o test_output.log
2839-
2840-
2841+ @rm -vf *.o ../include/logger.h logger_test
2842+ @echo all objects and executables have been erased.
2843
2844
2845=== added file 'cpp/common/logger/logger.cpp'
2846--- cpp/common/logger/logger.cpp 1970-01-01 00:00:00 +0000
2847+++ cpp/common/logger/logger.cpp 2013-08-09 21:47:12 +0000
2848@@ -0,0 +1,141 @@
2849+/***********************************************
2850+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
2851+
2852+ NRTB is free software: you can redistribute it and/or modify
2853+ it under the terms of the GNU General Public License as published by
2854+ the Free Software Foundation, either version 3 of the License, or
2855+ (at your option) any later version.
2856+
2857+ NRTB is distributed in the hope that it will be useful,
2858+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2859+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2860+ GNU General Public License for more details.
2861+
2862+ You should have received a copy of the GNU General Public License
2863+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
2864+
2865+ **********************************************/
2866+
2867+// see base_socket.h for documentation
2868+
2869+#include "logger.h"
2870+#include <fstream>
2871+#include <iomanip>
2872+#include <sstream>
2873+#include <ctime>
2874+#include <unistd.h>
2875+
2876+namespace nrtb
2877+{
2878+
2879+std::string sev2text(log_sev s)
2880+{
2881+ std::string returnme;
2882+ switch (s)
2883+ {
2884+ case log_sev::critical : returnme = "CRITICAL"; break;
2885+ case log_sev::severe : returnme = "SEVERE"; break;
2886+ case log_sev::warning : returnme = "WARNING"; break;
2887+ case log_sev::info : returnme = "INFO"; break;
2888+ case log_sev::trace : returnme = "TRACE"; break;
2889+ default: returnme = "Undefined";
2890+ };
2891+ return returnme;
2892+};
2893+
2894+log_record::log_record(log_sev s, std::string c, std::string m)
2895+{
2896+ created = std::time(NULL);
2897+ severity = s;
2898+ component = c;
2899+ message = m;
2900+};
2901+
2902+void log_recorder::operator()(log_sev sev, std::string msg)
2903+{
2904+ log_record tr(sev, component, msg);
2905+ my_queue.push(tr);
2906+};
2907+
2908+void log_recorder::critical(std::string msg)
2909+{
2910+ (*this)(log_sev::critical,msg);
2911+};
2912+
2913+void log_recorder::severe(std::string msg)
2914+{
2915+ (*this)(log_sev::severe, msg);
2916+};
2917+
2918+void log_recorder::warning(std::string msg)
2919+{
2920+ (*this)(log_sev::warning, msg);
2921+};
2922+
2923+void log_recorder::info(std::string msg)
2924+{
2925+ (*this)(log_sev::info, msg);
2926+};
2927+
2928+void log_recorder::trace(std::string msg)
2929+{
2930+ (*this)(log_sev::trace, msg);
2931+};
2932+
2933+log_file_writer::log_file_writer(log_queue& queue, std::string filename)
2934+ : myqueue(queue)
2935+{
2936+ // start the writer
2937+ writer_process =
2938+ std::thread(log_file_writer::writer_thread,
2939+ std::ref(queue),filename);
2940+};
2941+
2942+void log_file_writer::close()
2943+{
2944+ // Hang around long enough to drain the queue.
2945+ while (myqueue.size())
2946+ usleep(100);
2947+ // Shutdown the queue, terminate the worker thread.
2948+ myqueue.shutdown();
2949+};
2950+
2951+log_file_writer::~log_file_writer()
2952+{
2953+ close();
2954+ // Wait for the worker to close down.
2955+ if (writer_process.joinable())
2956+ writer_process.join();
2957+};
2958+
2959+void log_file_writer::writer_thread(log_queue& q, std::string fname)
2960+{
2961+ bool done {false};
2962+ std::ofstream output;
2963+ output.open(fname);
2964+ while (!done)
2965+ {
2966+ try
2967+ {
2968+ log_record record = q.pop();
2969+ std::tm tm = *std::localtime(&record.created);
2970+ std::stringstream s;
2971+ s << tm.tm_year + 1900
2972+ << "-" << tm.tm_mon + 1
2973+ << "-" << tm.tm_mday
2974+ << ":" << tm.tm_hour
2975+ << ":" << tm.tm_min
2976+ << ":" << tm.tm_sec
2977+ << "\t" << sev2text(record.severity)
2978+ << "\t" << record.component
2979+ << "\t" << record.message;
2980+ output << s.str()
2981+ << std::endl;
2982+ }
2983+ catch (...) { done = true; };
2984+ };
2985+ output.close();
2986+};
2987+
2988+} // namqespace nrtb
2989+
2990
2991=== added file 'cpp/common/logger/logger.h'
2992--- cpp/common/logger/logger.h 1970-01-01 00:00:00 +0000
2993+++ cpp/common/logger/logger.h 2013-08-09 21:47:12 +0000
2994@@ -0,0 +1,76 @@
2995+/***********************************************
2996+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
2997+
2998+ NRTB is free software: you can redistribute it and/or modify
2999+ it under the terms of the GNU General Public License as published by
3000+ the Free Software Foundation, either version 3 of the License, or
3001+ (at your option) any later version.
3002+
3003+ NRTB is distributed in the hope that it will be useful,
3004+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3005+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3006+ GNU General Public License for more details.
3007+
3008+ You should have received a copy of the GNU General Public License
3009+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3010+
3011+ **********************************************/
3012+
3013+#ifndef logger_header
3014+#define logger_header
3015+
3016+#include <string>
3017+#include <chrono>
3018+#include <thread>
3019+#include <ctime>
3020+#include <linear_queue.h>
3021+
3022+namespace nrtb
3023+{
3024+
3025+enum class log_sev {critical,severe,warning,info,trace};
3026+
3027+std::string sev2text(log_sev s);
3028+
3029+struct log_record
3030+{
3031+ log_record(log_sev s, std::string c, std::string m);
3032+ std::time_t created;
3033+ log_sev severity;
3034+ std::string component;
3035+ std::string message;
3036+};
3037+
3038+typedef linear_queue<log_record> log_queue;
3039+
3040+class log_recorder
3041+{
3042+public:
3043+ log_recorder(std::string comp, log_queue & queue):
3044+ component(comp), my_queue(queue) {};
3045+ void operator () (log_sev sev, std::string msg);
3046+ void critical(std::string msg);
3047+ void severe(std::string msg);
3048+ void warning(std::string msg);
3049+ void info(std::string msg);
3050+ void trace(std::string msg);
3051+private:
3052+ log_queue & my_queue;
3053+ std::string component;
3054+};
3055+
3056+class log_file_writer
3057+{
3058+public:
3059+ log_file_writer(log_queue & queue, std::string filename);
3060+ ~log_file_writer();
3061+ void close();
3062+private:
3063+ log_queue & myqueue;
3064+ std::thread writer_process;
3065+ static void writer_thread(log_queue & q, std::string fname);
3066+};
3067+
3068+} // namepace nrtb
3069+
3070+#endif // logger_header
3071
3072=== added file 'cpp/common/logger/logger_test.cpp'
3073--- cpp/common/logger/logger_test.cpp 1970-01-01 00:00:00 +0000
3074+++ cpp/common/logger/logger_test.cpp 2013-08-09 21:47:12 +0000
3075@@ -0,0 +1,105 @@
3076+/***********************************************
3077+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
3078+
3079+ NRTB is free software: you can redistribute it and/or modify
3080+ it under the terms of the GNU General Public License as published by
3081+ the Free Software Foundation, either version 3 of the License, or
3082+ (at your option) any later version.
3083+
3084+ NRTB is distributed in the hope that it will be useful,
3085+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3086+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3087+ GNU General Public License for more details.
3088+
3089+ You should have received a copy of the GNU General Public License
3090+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3091+
3092+ **********************************************/
3093+
3094+#include "logger.h"
3095+#include <sstream>
3096+#include <iostream>
3097+#include <boost/concept_check.hpp>
3098+
3099+using namespace nrtb;
3100+using namespace std;
3101+
3102+int ecount {0};
3103+
3104+string stext_test(string a, log_sev b)
3105+{
3106+ stringstream s;
3107+ s << a << " " << (a == sev2text(b) ? "passed" : "failed");
3108+ if (a != sev2text(b)) ecount++;
3109+ return s.str();
3110+};
3111+
3112+int main()
3113+{
3114+ cout << "=========== logger unit test ============="
3115+ << endl;
3116+
3117+ log_queue test_logger;
3118+ log_recorder log("Unit_Test",test_logger);
3119+ log_file_writer writer(test_logger,"test_log.log");
3120+
3121+ log.trace("Starting");
3122+ for(auto i= 0; i<10; i++)
3123+ {
3124+ stringstream s;
3125+ s << "Log entry " << i;
3126+ log(log_sev::info,s.str());
3127+ };
3128+
3129+ log.trace("sev2test() testing");
3130+ log.info(stext_test("CRITICAL",log_sev::critical));
3131+ log.info(stext_test("SEVERE",log_sev::severe));
3132+ log.info(stext_test("WARNING",log_sev::warning));
3133+ log.info(stext_test("INFO",log_sev::info));
3134+ log.info(stext_test("TRACE",log_sev::trace));
3135+
3136+ log.trace("Shutting down");
3137+ writer.close();
3138+
3139+ bool good = (test_logger.in_count == test_logger.out_count);
3140+ good = good and (ecount == 0);
3141+
3142+ // test status billboard
3143+ cout << test_logger.in_count
3144+ << " : " << test_logger.out_count
3145+ << " : " << ecount
3146+ << endl;
3147+ if (!good)
3148+ cout << "Errors reported.. check log file." << endl;
3149+ cout << "=========== tcp_socket and server test complete ============="
3150+ << endl;
3151+
3152+ return !good; // return code has reversed values.
3153+};
3154+
3155+
3156+
3157+
3158+
3159+
3160+
3161+
3162+
3163+
3164+
3165+
3166+
3167+
3168+
3169+
3170+
3171+
3172+
3173+
3174+
3175+
3176+
3177+
3178+
3179+
3180+
3181
3182=== modified file 'cpp/common/point/Makefile'
3183--- obsolete/Cpp/common/point/Makefile 2012-04-06 17:42:40 +0000
3184+++ cpp/common/point/Makefile 2013-08-09 21:47:12 +0000
3185@@ -16,17 +16,16 @@
3186 #
3187 #***********************************************
3188
3189+switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP
3190+
3191 lib: common_test Makefile
3192 @echo "(2,3.5,7)" | ./common_test
3193 @cp -v triad.h ../include
3194 @echo nrtb::triad build complete
3195
3196-../include/common.h:
3197- @cd ../common_rl; make lib
3198-
3199-common_test: common_test.cpp triad.h Makefile ../include/common.h
3200+common_test: common_test.cpp triad.h Makefile
3201 @rm -vf common_test
3202- g++ -O3 common_test.cpp -I ../include ../obj/common.o -o common_test -std=gnu++0x
3203+ g++ -O3 common_test.cpp -I ../include ../obj/common.o -o common_test ${switches}
3204
3205 clean:
3206 @rm -vf *.o common_test ../include/triad.h
3207
3208=== modified file 'cpp/common/point/common_test.cpp'
3209--- obsolete/Cpp/common/point/common_test.cpp 2011-07-27 02:27:23 +0000
3210+++ cpp/common/point/common_test.cpp 2013-08-09 21:47:12 +0000
3211@@ -32,8 +32,8 @@
3212 cout << "\t" << prompt << " = " << val << endl;
3213 if (val != right)
3214 {
3215- ec++;
3216- cerr << "\t\tTest Failed: Answer should be " << val << endl;
3217+ ec++;
3218+ cerr << "\t\tTest Failed: Answer should be " << val << endl;
3219 }
3220 return ec;
3221 };
3222@@ -43,75 +43,75 @@
3223 cout << "\t" << prompt << " = " << val << endl;
3224 if (val != right)
3225 {
3226- ec++;
3227- cerr << "\t\tTest Failed: Answer should be " << val << endl;
3228+ ec++;
3229+ cerr << "\t\tTest Failed: Answer should be " << val << endl;
3230 }
3231 return ec;
3232 };
3233
3234 int main()
3235 {
3236- ld_triad a(1,2,3);
3237- ld_triad b(3,2,1);
3238- int returnme = 0;
3239+ ld_triad a(1,2,3);
3240+ ld_triad b(3,2,1);
3241+ int returnme = 0;
3242
3243- cout << setprecision(10);
3244- cout << "=== nrtb::triad Unit Test ===" << endl;
3245- cout << "\ta = " << a << "; b = " << b << endl;
3246- // basic operations tests
3247- returnme = test_triad("a + b",a + b,ld_triad(4,4,4),returnme);
3248- returnme = test_triad("a - b",a - b,ld_triad(-2,0,2),returnme);
3249- returnme = test_triad("a * b",a * b,ld_triad(3,4,3),returnme);
3250- returnme = test_triad("a / b",a / b,ld_triad(1.0d/(long double) 3.0,1,3),returnme);
3251- returnme = test_triad("a += b; a",a += b,ld_triad(4,4,4),returnme);
3252- returnme = test_triad("a -= b; a",a -= b,ld_triad(1,2,3),returnme);
3253- returnme = test_triad("a *= b; a",a *= b,ld_triad(3,4,3),returnme);
3254- returnme = test_triad("a /= b; a",a /= b,ld_triad(1,2,3),returnme);
3255- // power test
3256- returnme = test_triad("a.pow(b)",a.pow(b),ld_triad(1,4,3),returnme);
3257- // range test
3258- ld_triad t = b - a;
3259- t *= t;
3260- long double r = sqrt(t.x + t.y + t.z);
3261- returnme = test_ld("a.range(b)",a.range(b),r,returnme);
3262- // magnatude test
3263- returnme = test_ld("a.magnatude()",a.magnatude(),a.range(0),returnme);
3264- // boolean tests
3265- returnme = test_ld("a == a",a == a,1,returnme);
3266- returnme = test_ld("a == b",a == b,0,returnme);
3267- returnme = test_ld("a != b",a != b,1,returnme);
3268- returnme = test_ld("a != a",a != a,0,returnme);
3269- // point/scalar operations
3270- returnme = test_triad("a + 2",a + 2,ld_triad(3,4,5),returnme);
3271- returnme = test_triad("a - 2",a - 2,ld_triad(-1,0,1),returnme);
3272- returnme = test_triad("a * 2",a * 2,ld_triad(2,4,6),returnme);
3273- returnme = test_triad("a / 2",a / 2,ld_triad(0.5,1,1.5),returnme);
3274- returnme = test_triad("a += 2",a += 2,ld_triad(3,4,5),returnme);
3275- returnme = test_triad("a -= 2",a -= 2,ld_triad(1,2,3),returnme);
3276- returnme = test_triad("a *= 2",a *= 2,ld_triad(2,4,6),returnme);
3277- returnme = test_triad("a /= 2",a /= 2,ld_triad(1,2,3),returnme);
3278- returnme = test_triad("a.pow(2)",a.pow(2),ld_triad(1,4,9),returnme);
3279- // normalization test
3280- cout << "\ta.normalize() = " << a.normalize() << endl;
3281- returnme = test_ld("a.normalize().magnatude()",a.normalize().magnatude(),1.0,returnme);
3282- // dot and vector product tests.
3283- returnme = test_ld("a.dot_product(b)",a.dot_product(b),10,returnme);
3284- returnme = test_triad("a.vector_product(b)",a.vector_product(b),
3285- ld_triad(-4,8,-4),returnme);
3286- // string i/o tests, assumes "2,3.5,7) is input.
3287- cout << "\tInput a new value for b \"(2,3.5,7)\": " << flush;
3288- cin >> b; cout << endl;
3289- returnme = test_triad("b",b,ld_triad(2,3.5,7),returnme);
3290- returnme = test_triad("b.from_str(b.to_str(10))",
3291- b.from_str(b.to_str(10)),ld_triad(2,3.5,7),returnme);
3292- // report errors, if any
3293- if (returnme)
3294- {
3295- cerr << "There were " << returnme
3296- << " error(s) found." << endl;
3297- }
3298- cout << "=== nrtb::triad Unit Test Complete ===" << endl;
3299- // return the error count as the exit code
3300- return returnme;
3301+ cout << setprecision(10);
3302+ cout << "=== nrtb::triad Unit Test ===" << endl;
3303+ cout << "\ta = " << a << "; b = " << b << endl;
3304+ // basic operations tests
3305+ returnme = test_triad("a + b",a + b,ld_triad(4,4,4),returnme);
3306+ returnme = test_triad("a - b",a - b,ld_triad(-2,0,2),returnme);
3307+ returnme = test_triad("a * b",a * b,ld_triad(3,4,3),returnme);
3308+ returnme = test_triad("a / b",a / b,ld_triad(1.0d/(long double) 3.0,1,3),returnme);
3309+ returnme = test_triad("a += b; a",a += b,ld_triad(4,4,4),returnme);
3310+ returnme = test_triad("a -= b; a",a -= b,ld_triad(1,2,3),returnme);
3311+ returnme = test_triad("a *= b; a",a *= b,ld_triad(3,4,3),returnme);
3312+ returnme = test_triad("a /= b; a",a /= b,ld_triad(1,2,3),returnme);
3313+ // power test
3314+ returnme = test_triad("a.pow(b)",a.pow(b),ld_triad(1,4,3),returnme);
3315+ // range test
3316+ ld_triad t = b - a;
3317+ t *= t;
3318+ long double r = sqrt(t.x + t.y + t.z);
3319+ returnme = test_ld("a.range(b)",a.range(b),r,returnme);
3320+ // magnatude test
3321+ returnme = test_ld("a.magnatude()",a.magnatude(),a.range(0),returnme);
3322+ // boolean tests
3323+ returnme = test_ld("a == a",a == a,1,returnme);
3324+ returnme = test_ld("a == b",a == b,0,returnme);
3325+ returnme = test_ld("a != b",a != b,1,returnme);
3326+ returnme = test_ld("a != a",a != a,0,returnme);
3327+ // point/scalar operations
3328+ returnme = test_triad("a + 2",a + 2,ld_triad(3,4,5),returnme);
3329+ returnme = test_triad("a - 2",a - 2,ld_triad(-1,0,1),returnme);
3330+ returnme = test_triad("a * 2",a * 2,ld_triad(2,4,6),returnme);
3331+ returnme = test_triad("a / 2",a / 2,ld_triad(0.5,1,1.5),returnme);
3332+ returnme = test_triad("a += 2",a += 2,ld_triad(3,4,5),returnme);
3333+ returnme = test_triad("a -= 2",a -= 2,ld_triad(1,2,3),returnme);
3334+ returnme = test_triad("a *= 2",a *= 2,ld_triad(2,4,6),returnme);
3335+ returnme = test_triad("a /= 2",a /= 2,ld_triad(1,2,3),returnme);
3336+ returnme = test_triad("a.pow(2)",a.pow(2),ld_triad(1,4,9),returnme);
3337+ // normalization test
3338+ cout << "\ta.normalize() = " << a.normalize() << endl;
3339+ returnme = test_ld("a.normalize().magnatude()",a.normalize().magnatude(),1.0,returnme);
3340+ // dot and vector product tests.
3341+ returnme = test_ld("a.dot_product(b)",a.dot_product(b),10,returnme);
3342+ returnme = test_triad("a.vector_product(b)",a.vector_product(b),
3343+ ld_triad(-4,8,-4),returnme);
3344+ // string i/o tests, assumes "2,3.5,7) is input.
3345+ cout << "\tInput a new value for b \"(2,3.5,7)\": " << flush;
3346+ cin >> b; cout << endl;
3347+ returnme = test_triad("b",b,ld_triad(2,3.5,7),returnme);
3348+ returnme = test_triad("b.from_str(b.to_str(10))",
3349+ b.from_str(b.to_str(10)),ld_triad(2,3.5,7),returnme);
3350+ // report errors, if any
3351+ if (returnme)
3352+ {
3353+ cerr << "There were " << returnme
3354+ << " error(s) found." << endl;
3355+ }
3356+ cout << "=== nrtb::triad Unit Test Complete ===" << endl;
3357+ // return the error count as the exit code
3358+ return returnme;
3359
3360 };
3361
3362=== modified file 'cpp/common/point/triad.h'
3363--- obsolete/Cpp/common/point/triad.h 2011-07-27 02:27:23 +0000
3364+++ cpp/common/point/triad.h 2013-08-09 21:47:12 +0000
3365@@ -43,265 +43,265 @@
3366 template <class T>
3367 struct triad
3368 {
3369- /// X coordinate
3370- T x;
3371- /// Y coordinate
3372- T y;
3373- /// Z coordinate
3374- T z;
3375+ /// X coordinate
3376+ T x;
3377+ /// Y coordinate
3378+ T y;
3379+ /// Z coordinate
3380+ T z;
3381
3382- /** Constructor.
3383- **
3384- ** An easy way to create a point at the origin would be
3385- ** "triad<T> a;".
3386- **/
3387- triad(T _x=0, T _y=0, T _z=0);
3388- triad<T> operator + (const triad<T> & a);
3389- triad<T> operator - (const triad<T> & a);
3390- triad<T> operator * (const triad<T> & a);
3391- triad<T> operator / (const triad<T> & a);
3392- triad<T> operator += (const triad<T> & a);
3393- triad<T> operator -= (const triad<T> & a);
3394- triad<T> operator *= (const triad<T> & a);
3395- triad<T> operator /= (const triad<T> & a);
3396- /// returns (pow(x,a.x),pow(y,a.y),pow(z,a.z)).
3397- triad<T> pow(const triad<T> & a);
3398- triad<T> operator + (const T & a);
3399- triad<T> operator - (const T & a);
3400- triad<T> operator * (const T & a);
3401- triad<T> operator / (const T & a);
3402- triad<T> operator += (const T & a);
3403- triad<T> operator -= (const T & a);
3404- triad<T> operator *= (const T & a);
3405- triad<T> operator /= (const T & a);
3406- /// returns (pow(x,a),pow(y,a),pow(z,a)).
3407- triad<T> pow(const T & a);
3408- /** Returns a normalized version of the triad.
3409- **
3410- ** Normalization in this case refers to an operation resulting in a
3411- ** traid where the magnatude of the vector is 1.0 while maintaining the
3412- ** same angular component. For example, given triad<float> a = (1,2,3),
3413- ** a.normalize() = (0.267,0.534,0.802). Of course, the original triad
3414- ** is not modified.
3415- **
3416- ** Normalized triads are very useful when calcuating force or
3417- ** accelleration vectors, for example.
3418- **/
3419- triad<T> normalize();
3420- /// Returns the distance between *this and the supplied argument.
3421- T range(const triad<T> & a);
3422- /// Returns the magnatude of the vector.
3423- T magnatude();
3424- /// Returns the dot (scalar) product of two triads
3425- T dot_product(const triad<T> & a);
3426- /// Returns the vector product of two triads
3427- triad<T> vector_product(const triad<T> & a);
3428- bool operator == (const triad<T> & a);
3429- bool operator != (const triad<T> & a);
3430- /// Loads from a std::string.
3431- triad<T> from_str(const std::string & a);
3432- /// Returns a std::string representation.
3433- std::string to_str(int precision=6);
3434+ /** Constructor.
3435+ **
3436+ ** An easy way to create a point at the origin would be
3437+ ** "triad<T> a;".
3438+ **/
3439+ triad(T _x=0, T _y=0, T _z=0);
3440+ triad<T> operator + (const triad<T> & a);
3441+ triad<T> operator - (const triad<T> & a);
3442+ triad<T> operator * (const triad<T> & a);
3443+ triad<T> operator / (const triad<T> & a);
3444+ triad<T> operator += (const triad<T> & a);
3445+ triad<T> operator -= (const triad<T> & a);
3446+ triad<T> operator *= (const triad<T> & a);
3447+ triad<T> operator /= (const triad<T> & a);
3448+ /// returns (pow(x,a.x),pow(y,a.y),pow(z,a.z)).
3449+ triad<T> pow(const triad<T> & a);
3450+ triad<T> operator + (const T & a);
3451+ triad<T> operator - (const T & a);
3452+ triad<T> operator * (const T & a);
3453+ triad<T> operator / (const T & a);
3454+ triad<T> operator += (const T & a);
3455+ triad<T> operator -= (const T & a);
3456+ triad<T> operator *= (const T & a);
3457+ triad<T> operator /= (const T & a);
3458+ /// returns (pow(x,a),pow(y,a),pow(z,a)).
3459+ triad<T> pow(const T & a);
3460+ /** Returns a normalized version of the triad.
3461+ **
3462+ ** Normalization in this case refers to an operation resulting in a
3463+ ** traid where the magnatude of the vector is 1.0 while maintaining the
3464+ ** same angular component. For example, given triad<float> a = (1,2,3),
3465+ ** a.normalize() = (0.267,0.534,0.802). Of course, the original triad
3466+ ** is not modified.
3467+ **
3468+ ** Normalized triads are very useful when calcuating force or
3469+ ** accelleration vectors, for example.
3470+ **/
3471+ triad<T> normalize();
3472+ /// Returns the distance between *this and the supplied argument.
3473+ T range(const triad<T> & a);
3474+ /// Returns the magnatude of the vector.
3475+ T magnatude();
3476+ /// Returns the dot (scalar) product of two triads
3477+ T dot_product(const triad<T> & a);
3478+ /// Returns the vector product of two triads
3479+ triad<T> vector_product(const triad<T> & a);
3480+ bool operator == (const triad<T> & a);
3481+ bool operator != (const triad<T> & a);
3482+ /// Loads from a std::string.
3483+ triad<T> from_str(const std::string & a);
3484+ /// Returns a std::string representation.
3485+ std::string to_str(int precision=6);
3486 };
3487
3488 template <class T>
3489 triad<T>::triad(T _x, T _y, T _z)
3490 {
3491- x = _x;
3492- y = _y;
3493- z = _z;
3494+ x = _x;
3495+ y = _y;
3496+ z = _z;
3497 };
3498
3499 template <class T>
3500 triad<T> triad<T>::operator + (const triad<T> & a)
3501 {
3502- triad<T> returnme;
3503- returnme.x = x + a.x;
3504- returnme.y = y + a.y;
3505- returnme.z = z + a.z;
3506- return returnme;
3507+ triad<T> returnme;
3508+ returnme.x = x + a.x;
3509+ returnme.y = y + a.y;
3510+ returnme.z = z + a.z;
3511+ return returnme;
3512 };
3513
3514 template <class T>
3515 triad<T> triad<T>::operator - (const triad<T> & a)
3516 {
3517- triad<T> returnme;
3518- returnme.x = x - a.x;
3519- returnme.y = y - a.y;
3520- returnme.z = z - a.z;
3521- return returnme;
3522+ triad<T> returnme;
3523+ returnme.x = x - a.x;
3524+ returnme.y = y - a.y;
3525+ returnme.z = z - a.z;
3526+ return returnme;
3527 };
3528
3529 template <class T>
3530 triad<T> triad<T>::operator * (const triad<T> & a)
3531 {
3532- triad<T> returnme;
3533- returnme.x = x * a.x;
3534- returnme.y = y * a.y;
3535- returnme.z = z * a.z;
3536- return returnme;
3537+ triad<T> returnme;
3538+ returnme.x = x * a.x;
3539+ returnme.y = y * a.y;
3540+ returnme.z = z * a.z;
3541+ return returnme;
3542 };
3543
3544 template <class T>
3545 triad<T> triad<T>::operator / (const triad<T> & a)
3546 {
3547- triad<T> returnme;
3548- returnme.x = x / a.x;
3549- returnme.y = y / a.y;
3550- returnme.z = z / a.z;
3551- return returnme;
3552+ triad<T> returnme;
3553+ returnme.x = x / a.x;
3554+ returnme.y = y / a.y;
3555+ returnme.z = z / a.z;
3556+ return returnme;
3557 };
3558
3559 template <class T>
3560 triad<T> triad<T>::operator += (const triad<T> & a)
3561 {
3562- x += a.x;
3563- y += a.y;
3564- z += a.z;
3565- return *this;
3566+ x += a.x;
3567+ y += a.y;
3568+ z += a.z;
3569+ return *this;
3570 };
3571
3572 template <class T>
3573 triad<T> triad<T>::operator -= (const triad<T> & a)
3574 {
3575- x -= a.x;
3576- y -= a.y;
3577- z -= a.z;
3578- return *this;
3579+ x -= a.x;
3580+ y -= a.y;
3581+ z -= a.z;
3582+ return *this;
3583 };
3584
3585 template <class T>
3586 triad<T> triad<T>::operator *= (const triad<T> & a)
3587 {
3588- x *= a.x;
3589- y *= a.y;
3590- z *= a.z;
3591- return *this;
3592+ x *= a.x;
3593+ y *= a.y;
3594+ z *= a.z;
3595+ return *this;
3596 };
3597
3598 template <class T>
3599 triad<T> triad<T>::operator /= (const triad<T> & a)
3600 {
3601- x /= a.x;
3602- y /= a.y;
3603- z /= a.z;
3604- return *this;
3605+ x /= a.x;
3606+ y /= a.y;
3607+ z /= a.z;
3608+ return *this;
3609 };
3610
3611 template <class T>
3612 triad<T> triad<T>::pow(const triad<T> & a)
3613 {
3614- triad<T> returnme;
3615- returnme.x = ::pow(x,a.x);
3616- returnme.y = ::pow(y,a.y);
3617- returnme.z = ::pow(z,a.z);
3618- return returnme;
3619+ triad<T> returnme;
3620+ returnme.x = ::pow(x,a.x);
3621+ returnme.y = ::pow(y,a.y);
3622+ returnme.z = ::pow(z,a.z);
3623+ return returnme;
3624 };
3625
3626 template <class T>
3627 triad<T> triad<T>::normalize()
3628 {
3629- return (*this / this->magnatude());
3630+ return (*this / this->magnatude());
3631 };
3632
3633 template <class T>
3634 triad<T> triad<T>::operator + (const T & a)
3635 {
3636- triad<T> returnme;
3637- returnme.x = x + a;
3638- returnme.y = y + a;
3639- returnme.z = z + a;
3640- return returnme;
3641+ triad<T> returnme;
3642+ returnme.x = x + a;
3643+ returnme.y = y + a;
3644+ returnme.z = z + a;
3645+ return returnme;
3646 };
3647
3648 template <class T>
3649 triad<T> triad<T>::operator - (const T & a)
3650 {
3651- triad<T> returnme;
3652- returnme.x = x - a;
3653- returnme.y = y - a;
3654- returnme.z = z - a;
3655- return returnme;
3656+ triad<T> returnme;
3657+ returnme.x = x - a;
3658+ returnme.y = y - a;
3659+ returnme.z = z - a;
3660+ return returnme;
3661 };
3662
3663 template <class T>
3664 triad<T> triad<T>::operator * (const T & a)
3665 {
3666- triad<T> returnme;
3667- returnme.x = x * a;
3668- returnme.y = y * a;
3669- returnme.z = z * a;
3670- return returnme;
3671+ triad<T> returnme;
3672+ returnme.x = x * a;
3673+ returnme.y = y * a;
3674+ returnme.z = z * a;
3675+ return returnme;
3676 };
3677
3678 template <class T>
3679 triad<T> triad<T>::operator / (const T & a)
3680 {
3681- triad<T> returnme;
3682- returnme.x = x / a;
3683- returnme.y = y / a;
3684- returnme.z = z / a;
3685- return returnme;
3686+ triad<T> returnme;
3687+ returnme.x = x / a;
3688+ returnme.y = y / a;
3689+ returnme.z = z / a;
3690+ return returnme;
3691 };
3692
3693 template <class T>
3694 triad<T> triad<T>::operator += (const T & a)
3695 {
3696- x += a;
3697- y += a;
3698- z += a;
3699- return *this;
3700+ x += a;
3701+ y += a;
3702+ z += a;
3703+ return *this;
3704 };
3705
3706 template <class T>
3707 triad<T> triad<T>::operator -= (const T & a)
3708 {
3709- x -= a;
3710- y -= a;
3711- z -= a;
3712- return *this;
3713+ x -= a;
3714+ y -= a;
3715+ z -= a;
3716+ return *this;
3717 };
3718
3719 template <class T>
3720 triad<T> triad<T>::operator *= (const T & a)
3721 {
3722- x *= a;
3723- y *= a;
3724- z *= a;
3725- return *this;
3726+ x *= a;
3727+ y *= a;
3728+ z *= a;
3729+ return *this;
3730 };
3731
3732 template <class T>
3733 triad<T> triad<T>::operator /= (const T & a)
3734 {
3735- x /= a;
3736- y /= a;
3737- z /= a;
3738- return *this;
3739+ x /= a;
3740+ y /= a;
3741+ z /= a;
3742+ return *this;
3743 };
3744
3745 template <class T>
3746 triad<T> triad<T>::pow(const T & a)
3747 {
3748- triad<T> returnme;
3749- returnme.x = ::pow(x,a);
3750- returnme.y = ::pow(y,a);
3751- returnme.z = ::pow(z,a);
3752- return returnme;
3753+ triad<T> returnme;
3754+ returnme.x = ::pow(x,a);
3755+ returnme.y = ::pow(y,a);
3756+ returnme.z = ::pow(z,a);
3757+ return returnme;
3758 };
3759
3760 template <class T>
3761 T triad<T>::range(const triad<T> & a)
3762 {
3763- triad<T> offset = *this - a;
3764- offset *= offset;
3765- return sqrt(offset.x + offset.y + offset.z);
3766+ triad<T> offset = *this - a;
3767+ offset *= offset;
3768+ return sqrt(offset.x + offset.y + offset.z);
3769 };
3770
3771 template <class T>
3772 T triad<T>::magnatude()
3773 {
3774- return sqrt((x*x) + (y*y) + (z*z));
3775+ return sqrt((x*x) + (y*y) + (z*z));
3776 };
3777
3778 template <class T>
3779@@ -327,39 +327,39 @@
3780 template <class T>
3781 bool triad<T>::operator == (const triad<T> & a)
3782 {
3783- return ((x == a.x) && (y == a.y) && (z == a.z));
3784+ return ((x == a.x) && (y == a.y) && (z == a.z));
3785 };
3786
3787 template <class T>
3788 bool triad<T>::operator != (const triad<T> & a)
3789 {
3790- return (! (*this == a));
3791+ return (! (*this == a));
3792 };
3793
3794 template <class T>
3795 triad<T> triad<T>::from_str(const std::string & a)
3796 {
3797- std::istringstream t(a.c_str());
3798- t >> *this;
3799- return *this;
3800+ std::istringstream t(a.c_str());
3801+ t >> *this;
3802+ return *this;
3803 };
3804
3805 template <class T>
3806 std::string triad<T>::to_str(int precision)
3807 {
3808- std::stringstream a;
3809- a << std::setprecision(precision) << *this;
3810- std::string returnme;
3811- a >> returnme;
3812- return returnme;
3813+ std::stringstream a;
3814+ a << std::setprecision(precision) << *this;
3815+ std::string returnme;
3816+ a >> returnme;
3817+ return returnme;
3818 };
3819
3820 /// Writes the triad<T> in the format "(x,y,z)" to the output stream.
3821 template <class T>
3822 std::ostream & operator << (std::ostream &f, const triad<T> & a)
3823 {
3824- f << "(" << a.x << "," << a.y << "," << a.z << ")";
3825- return f;
3826+ f << "(" << a.x << "," << a.y << "," << a.z << ")";
3827+ return f;
3828 };
3829
3830 /** Reads the triad<T> from an input stream.
3831@@ -372,22 +372,22 @@
3832 template <class T>
3833 std::istream & operator >> (std::istream &f, triad<T> & a)
3834 {
3835- std::string element;
3836- f >> element;
3837- strlist t = split(element,',');
3838- if (t.size() != 3)
3839- {
3840- a = 0;
3841- }
3842- else
3843- {
3844- std::stringstream transmorgrafier;
3845- transmorgrafier << std::setprecision(30);
3846- if (t[0][0] == '(') { t[0].erase(0,1); };
3847- for(int i=0; i < 3; i++) { transmorgrafier << t[i] << " "; };
3848- transmorgrafier >> a.x >> a.y >> a.z;
3849- };
3850- return f;
3851+ std::string element;
3852+ f >> element;
3853+ strlist t = split(element,',');
3854+ if (t.size() != 3)
3855+ {
3856+ a = 0;
3857+ }
3858+ else
3859+ {
3860+ std::stringstream transmorgrafier;
3861+ transmorgrafier << std::setprecision(30);
3862+ if (t[0][0] == '(') { t[0].erase(0,1); };
3863+ for(int i=0; i < 3; i++) { transmorgrafier << t[i] << " "; };
3864+ transmorgrafier >> a.x >> a.y >> a.z;
3865+ };
3866+ return f;
3867 };
3868
3869 } // namespace nrtb
3870
3871=== modified file 'cpp/common/serializer/Makefile'
3872--- obsolete/Cpp/common/serializer/Makefile 2012-04-06 17:44:53 +0000
3873+++ cpp/common/serializer/Makefile 2013-08-09 21:47:12 +0000
3874@@ -28,8 +28,8 @@
3875
3876 serializer_test: serializer.o serializer_test.cpp
3877 @rm -f serializer_test
3878- g++ -c serializer_test.cpp -I../include -std=gnu++0x
3879- g++ -o serializer_test serializer_test.o serializer.o ../obj/base_thread.o -lpthread ../obj/common.o -std=gnu++0x
3880+ g++ -c serializer_test.cpp -I../include -std=gnu++11
3881+ g++ -o serializer_test serializer_test.o serializer.o -lpthread -std=gnu++11
3882
3883 clean:
3884 @rm -rvf *.o serializer_test ../include/serializer.h ../obj/serializer.o
3885
3886=== modified file 'cpp/common/serializer/serializer.cpp'
3887--- obsolete/Cpp/common/serializer/serializer.cpp 2011-07-30 15:32:43 +0000
3888+++ cpp/common/serializer/serializer.cpp 2013-08-09 21:47:12 +0000
3889@@ -17,7 +17,6 @@
3890 **********************************************/
3891
3892 #include "serializer.h"
3893-#include <base_thread.h>
3894
3895 using namespace nrtb;
3896
3897@@ -38,6 +37,5 @@
3898
3899 unsigned long long serializer::operator()()
3900 {
3901- nrtb::scope_lock mylock(lock);
3902 return counter++;
3903 }
3904
3905=== modified file 'cpp/common/serializer/serializer.h'
3906--- obsolete/Cpp/common/serializer/serializer.h 2011-09-15 01:21:11 +0000
3907+++ cpp/common/serializer/serializer.h 2013-08-09 21:47:12 +0000
3908@@ -18,7 +18,8 @@
3909
3910 #ifndef nrtb_serializer_h
3911 #define nrtb_serializer_h
3912-#include <base_thread.h>
3913+
3914+#include <atomic>
3915
3916 namespace nrtb
3917 {
3918@@ -41,8 +42,7 @@
3919 // functor method, returns the next value in the sequence.
3920 unsigned long long operator ()();
3921 private:
3922- nrtb::mutex lock;
3923- unsigned long long int counter;
3924+ std::atomic<unsigned long long> counter;
3925 };
3926
3927 }
3928
3929=== modified file 'cpp/common/singleton/Makefile'
3930--- obsolete/Cpp/common/singleton/Makefile 2012-04-06 17:46:15 +0000
3931+++ cpp/common/singleton/Makefile 2013-08-09 21:47:12 +0000
3932@@ -16,6 +16,7 @@
3933 #
3934 #***********************************************
3935
3936+switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP
3937
3938 lib: singleton_test
3939 @./singleton_test
3940@@ -24,8 +25,8 @@
3941
3942 singleton_test: singleton_test.cpp Makefile
3943 @rm -f singleton_test
3944- g++ -c singleton_test.cpp -I ../include -std=gnu++0x
3945- g++ -o singleton_test singleton_test.o ../obj/base_thread.o ../obj/common.o ../obj/serializer.o -lpthread -std=gnu++0x
3946+ g++ -c singleton_test.cpp -I ../include ${switches}
3947+ g++ -o singleton_test singleton_test.o ../obj/serializer.o -lpthread ${switches}
3948
3949 clean:
3950 @rm -rvf *.o singleton_test ../include/singleton.h
3951
3952=== modified file 'cpp/common/singleton/singleton.h'
3953--- obsolete/Cpp/common/singleton/singleton.h 2011-08-13 13:13:25 +0000
3954+++ cpp/common/singleton/singleton.h 2013-08-09 21:47:12 +0000
3955@@ -25,7 +25,9 @@
3956 #ifndef nrtb_singleton_h
3957 #define nrtb_singleton_h
3958
3959-#include <base_thread.h>
3960+#include <mutex>
3961+#include <memory>
3962+#include <atomic>
3963
3964 namespace nrtb
3965 {
3966@@ -55,68 +57,70 @@
3967 template <class T, int mytag=0>
3968 class singleton: public T
3969 {
3970- private:
3971- static mutex __mylock;
3972- static singleton * __me;
3973- protected:
3974- singleton() : T() {};
3975- virtual ~singleton() {};
3976- singleton(const singleton &) {};
3977- public:
3978- /** Used to access the object.
3979- **
3980- ** Returns a reference to the instanciated singleton object. If
3981- ** the object has not been accessed before, the object will be
3982- ** instanciated automatically.
3983- **
3984- ** As is usual for the method that provides access to a singleton,
3985- ** this method is static, allowing it to be called via the class
3986- ** name as shown. Remember you can only assign the return value to
3987- ** a reference:
3988- **
3989- ** mytype & a = mytype::get_instance();
3990- **
3991- ** Attempts to make a copy of the instance should throw a compiler
3992- ** error.
3993- **
3994- ** This method is thread safe, but that does not imply that the
3995- ** class returned is thread-safe overall; that would depend on the
3996- ** implementation of the class used to instaciate the template.
3997- **/
3998- static singleton & get_instance()
3999- {
4000- // First test avoids expensive mutex cycle
4001- // if the object is already allocated.
4002- if (!__me)
4003- {
4004- scope_lock lock(__mylock);
4005- // second test required in case multiple threads
4006- // get past the first check.
4007- if (!__me)
4008- {
4009- __me = new singleton;
4010- };
4011- };
4012- return *__me;
4013- };
4014+private:
4015+ static std::mutex __mylock;
4016+ static singleton<T,mytag> * __me ;
4017+protected:
4018+ singleton() : T() {};
4019+ virtual ~singleton() {};
4020+ singleton(const singleton &) = delete;
4021+public:
4022+ /** Used to access the object.
4023+ **
4024+ ** Returns a reference to the instanciated singleton object. If
4025+ ** the object has not been accessed before, the object will be
4026+ ** instanciated automatically.
4027+ **
4028+ ** As is usual for the method that provides access to a singleton,
4029+ ** this method is static, allowing it to be called via the class
4030+ ** name as shown. Remember you can only assign the return value to
4031+ ** a reference:
4032+ **
4033+ ** mytype & a = mytype::get_instance();
4034+ **
4035+ ** Attempts to make a copy of the instance should throw a compiler
4036+ ** error.
4037+ **
4038+ ** This method is thread safe, but that does not imply that the
4039+ ** class returned is thread-safe overall; that would depend on the
4040+ ** implementation of the class used to instaciate the template.
4041+ **/
4042+ static singleton & get_reference()
4043+ {
4044+ // First test avoids expensive mutex cycle
4045+ // if the object is already allocated.
4046+ if (!__me)
4047+ {
4048+ std::unique_lock<std::mutex> lock(__mylock);
4049+ // second test required in case multiple threads
4050+ // get past the first check.
4051+ if (!__me)
4052+ {
4053+ __me = new singleton;
4054+ };
4055+ };
4056+ return *__me;
4057+ };
4058
4059- /** Destructs and deallocates the singleton object.
4060- **
4061- ** After a call to this method, the singleton object will
4062- ** be destructed and deallocated from memory. However, it
4063- ** will be automatically reconstruted and allocated if
4064- ** get_instance() called at any time afterword.
4065- **/
4066- void delete_me()
4067- {
4068- scope_lock lock(__mylock);
4069- if (__me) delete __me;
4070- __me = 0;
4071- };
4072+ /** Destructs and deallocates the singleton object.
4073+ **
4074+ ** After a call to this method, the singleton object will
4075+ ** be destructed and deallocated from memory. However, it
4076+ ** will be automatically reconstruted and allocated if
4077+ ** get_instance() called at any time afterword.
4078+ **/
4079+ void delete_me()
4080+ {
4081+ std::unique_lock<std::mutex> lock(__mylock);
4082+ if (__me) delete __me;
4083+ __me = 0;
4084+ };
4085 };
4086
4087-template <class T, int mytag> mutex singleton<T,mytag>::__mylock;
4088-template <class T, int mytag> singleton<T,mytag> * singleton<T,mytag>::__me = 0;
4089+template <class T, int mytag>
4090+ std::mutex singleton<T,mytag>::__mylock;
4091+template <class T, int mytag>
4092+ singleton<T,mytag> * singleton<T,mytag>::__me;
4093
4094 } // namespace nrtb;
4095
4096
4097=== modified file 'cpp/common/singleton/singleton_test.cpp'
4098--- obsolete/Cpp/common/singleton/singleton_test.cpp 2011-08-13 14:19:56 +0000
4099+++ cpp/common/singleton/singleton_test.cpp 2013-08-09 21:47:12 +0000
4100@@ -32,24 +32,25 @@
4101
4102 cout << "============== singleton unit test ================"
4103 << endl;
4104- int er_count = 0;
4105+ int er_count {0};
4106
4107- sequence_type & a = sequence_type::get_instance();
4108+ sequence_type & a = sequence_type::get_reference();
4109
4110 for (int i=0; i<10; i++)
4111 {
4112- cout << a();
4113+ cout << a();
4114 };
4115
4116- sequence_type & b = sequence_type::get_instance();
4117+ sequence_type & b = sequence_type::get_reference();
4118
4119 if ( b() != 10)
4120 {
4121- er_count++;
4122+ er_count++;
4123 };
4124
4125- cout << "\n=========== singleton test " << (er_count ? "failed" : "passed")
4126- << " =============" << endl;
4127+ cout << "\n=========== singleton test "
4128+ << (er_count ? "failed" : "passed")
4129+ << " =============" << endl;
4130
4131 return er_count;
4132 };
4133
4134=== modified file 'cpp/common/sockets/Makefile'
4135--- obsolete/Cpp/common/sockets/Makefile 2012-03-31 21:56:49 +0000
4136+++ cpp/common/sockets/Makefile 2013-08-09 21:47:12 +0000
4137@@ -16,6 +16,8 @@
4138 #
4139 #***********************************************
4140
4141+switches=-std=gnu++11 -D _GLIBCXX_USE_SCHED_YIELD -D _GLIBCXX_USE_NANOSLEEP
4142+
4143 lib: socket_test
4144 @./socket_test
4145 @cp -v base_socket.h ../include/
4146@@ -24,13 +26,13 @@
4147
4148 socket_test: base_socket.o socket_test.cpp
4149 @rm -f socket_test
4150- g++ -c -O3 socket_test.cpp -I ../include -std=gnu++0x
4151- g++ -o socket_test socket_test.o base_socket.o ../obj/hires_timer.o ../obj/common.o ../obj/base_thread.o -lpthread -std=gnu++0x
4152+ g++ -c -O3 socket_test.cpp -I ../include ${switches}
4153+ g++ -o socket_test socket_test.o base_socket.o ../obj/common.o -lpthread ${switches}
4154
4155
4156 base_socket.o: base_socket.cpp base_socket.h Makefile
4157 @rm -f base_socket.o
4158- g++ -c -O3 base_socket.cpp -I ../include -std=gnu++0x
4159+ g++ -c -O3 base_socket.cpp -I ../include ${switches}
4160
4161 clean:
4162 @rm -vf *.o ../include/base_socket.h socket_test
4163
4164=== modified file 'cpp/common/sockets/base_socket.cpp'
4165--- obsolete/Cpp/common/sockets/base_socket.cpp 2012-04-07 14:16:46 +0000
4166+++ cpp/common/sockets/base_socket.cpp 2013-08-09 21:47:12 +0000
4167@@ -19,11 +19,13 @@
4168 // see base_socket.h for documentation
4169
4170 #include "base_socket.h"
4171+#include <boost/lexical_cast.hpp>
4172 #include <string.h>
4173 #include <errno.h>
4174 #include <arpa/inet.h>
4175 #include <netdb.h>
4176-#include <boost/lexical_cast.hpp>
4177+#include <vector>
4178+#include <regex>
4179
4180 // testing
4181 #include <iostream>
4182@@ -34,554 +36,527 @@
4183 namespace nrtb
4184 {
4185
4186-// added for Solaris 2.6
4187-#ifdef no_inet_aton
4188-int inet_aton(const char * addr, in_addr * inp)
4189-{
4190- // this workaround defines inet_aton in term in_addr. Drawbacks are
4191- // that there is no useful error checking.
4192- inp->s_addr = inet_addr(addr);
4193- return (inp->s_addr != 0);
4194-};
4195-#endif // no_inet_aton
4196-
4197-// added for solaris 2.6
4198-#ifdef no_socklen_t
4199-typedef int socklen_t;
4200-#endif // no_sock_len_t
4201-
4202 int tcp_socket::transmit(const string & data)
4203 {
4204- return send(mysock,data.c_str(),data.length(),MSG_DONTWAIT);
4205+ return send(mysock,data.c_str(),data.length(),MSG_DONTWAIT);
4206 };
4207
4208 int tcp_socket::receive(std::string & data, int limit)
4209 {
4210- errno = 0;
4211- data = "";
4212- // make more room in the input buffer if needed.
4213- int bufsize = limit + 1;
4214- if (bufsize > inbuff.size()) inbuff.resize(bufsize);
4215- // get the data to inbuff
4216- int returnme = recv(mysock,(void *) &(inbuff[0]),limit,0);
4217- // did we get anything?
4218- if (returnme > 0)
4219- {
4220- // yes.. store for the caller.
4221- data.resize(returnme,0);
4222- for (int i=0; i<returnme; i++)
4223- {
4224- data[i] = inbuff[i];
4225- };
4226- }
4227- // ... or was there an error?
4228- else if (errno)
4229- {
4230- // flag it for the caller.
4231- returnme = -1;
4232- };
4233- return returnme;
4234+ errno = 0;
4235+ data = "";
4236+ // make more room in the input buffer if needed.
4237+ int bufsize = limit + 1;
4238+ if (bufsize > inbuff.size()) inbuff.resize(bufsize);
4239+ // get the data to inbuff
4240+ int returnme = recv(mysock,(void *) &(inbuff[0]),limit,0);
4241+ // did we get anything?
4242+ if (returnme > 0)
4243+ {
4244+ // yes.. store for the caller.
4245+ data.resize(returnme,0);
4246+ for (int i=0; i<returnme; i++)
4247+ {
4248+ data[i] = inbuff[i];
4249+ };
4250+ }
4251+ // ... or was there an error?
4252+ else if (errno)
4253+ {
4254+ // flag it for the caller.
4255+ returnme = -1;
4256+ };
4257+ return returnme;
4258 };
4259
4260 tcp_socket::tcp_socket(bool autoclose)
4261 {
4262- close_on_destruct = autoclose;
4263- mysock = socket(AF_INET,SOCK_STREAM,0);
4264- _status = sock_init;
4265- _last_error = 0;
4266+ close_on_destruct = autoclose;
4267+ mysock = socket(AF_INET,SOCK_STREAM,0);
4268+ _status = state::sock_init;
4269+ _last_error = 0;
4270 };
4271
4272 tcp_socket::tcp_socket(int existing_socket, bool autoclose)
4273 {
4274- close_on_destruct = autoclose;
4275- mysock = existing_socket;
4276- _status = sock_connect;
4277- _last_error = 0;
4278+ close_on_destruct = autoclose;
4279+ mysock = existing_socket;
4280+ _status = state::sock_connect;
4281+ _last_error = 0;
4282 };
4283
4284 tcp_socket::~tcp_socket()
4285 {
4286- if (close_on_destruct)
4287- {
4288- try {shutdown(mysock,SHUT_RDWR); } catch (...) {};
4289- try {::close(mysock); } catch (...) {};
4290- _status = sock_undef;
4291- };
4292+ if (close_on_destruct)
4293+ {
4294+ try {shutdown(mysock,SHUT_RDWR); } catch (...) {};
4295+ try {::close(mysock); } catch (...) {};
4296+ _status = state::sock_undef;
4297+ };
4298 };
4299
4300 void tcp_socket::reset()
4301 {
4302- // close the old socket if we can.
4303- try { close(); } catch (tcp_socket::general_exception) {};
4304- // get a new one.
4305- mysock = socket(AF_INET,SOCK_STREAM,0);
4306- // set up the default conditions;
4307- _status = sock_init;
4308- _last_error = 0;
4309+ // close the old socket if we can.
4310+ try { close(); } catch (tcp_socket::general_exception) {}
4311+ // get a new one.
4312+ mysock = socket(AF_INET,SOCK_STREAM,0);
4313+ // set up the default conditions;
4314+ _status = state::sock_init;
4315+ _last_error = 0;
4316 };
4317
4318 sockaddr_in tcp_socket::str_to_sockaddr(const string & address)
4319 {
4320- sockaddr_in in_address;
4321- // init our address structure.
4322- memset(&in_address,0,sizeof(in_address));
4323- //in_address.sin_len = 16;
4324- in_address.sin_family = AF_INET;
4325- // seperate the IP and port addresses.
4326- const int IP = 0;
4327- const int PORT = 1;
4328- strlist addr;
4329- addr = split(address,':');
4330- if (addr.size() != 2)
4331- {
4332- throw bad_address_exception();
4333- };
4334- if (addr[IP] != "*")
4335- {
4336- // first attempt name resolution
4337- hostent * name = gethostbyname(addr[IP].c_str());
4338- if ((name != 0) && (name->h_length > 0))
4339- {
4340- in_address.sin_addr = *( (in_addr *) (name->h_addr_list[0]));
4341- }
4342- else if (!inet_aton(addr[IP].c_str(),&in_address.sin_addr))
4343- {
4344- throw bad_address_exception();
4345- };
4346- };
4347- if (addr[PORT] != "*")
4348- {
4349- // get the good port;
4350- uint16_t port = lexical_cast<uint16_t>(addr[PORT]);
4351- in_address.sin_port = htons(port);
4352- };
4353- return in_address;
4354+ sockaddr_in in_address;
4355+ // init our address structure.
4356+ memset(&in_address,0,sizeof(in_address));
4357+ //in_address.sin_len = 16;
4358+ in_address.sin_family = AF_INET;
4359+ // seperate the IP and port addresses.
4360+ const int IP = 0;
4361+ const int PORT = 1;
4362+ strlist addr;
4363+ addr = split(address,':');
4364+ if (addr.size() != 2)
4365+ {
4366+ throw bad_address_exception();
4367+ };
4368+ if (addr[IP] != "*")
4369+ {
4370+ // first attempt name resolution
4371+ hostent * name = gethostbyname(addr[IP].c_str());
4372+ if ((name != 0) && (name->h_length > 0))
4373+ {
4374+ in_address.sin_addr = *( (in_addr *) (name->h_addr_list[0]));
4375+ }
4376+ else if (!inet_aton(addr[IP].c_str(),&in_address.sin_addr))
4377+ {
4378+ throw bad_address_exception();
4379+ };
4380+ };
4381+ if (addr[PORT] != "*")
4382+ {
4383+ // get the good port;
4384+ uint16_t port = lexical_cast<uint16_t>(addr[PORT]);
4385+ in_address.sin_port = htons(port);
4386+ };
4387+ return in_address;
4388 };
4389
4390 string tcp_socket::sockaddr_to_str(const sockaddr_in & address)
4391 {
4392- // get the IP address.
4393- string returnme = inet_ntoa(address.sin_addr);
4394- // adjust for wild card if appropriate.
4395- if (returnme == "0.0.0.0") { returnme = "*"; };
4396- // get the port address
4397- returnme += ":";
4398- uint16_t myport = ntohs(address.sin_port);
4399- if (myport > 0 )
4400- {
4401- returnme += lexical_cast<string>(myport);
4402- }
4403- else
4404- {
4405- returnme += "*";
4406- };
4407- return returnme;
4408+ // get the IP address.
4409+ string returnme = inet_ntoa(address.sin_addr);
4410+ // adjust for wild card if appropriate.
4411+ if (returnme == "0.0.0.0") { returnme = "*"; };
4412+ // get the port address
4413+ returnme += ":";
4414+ uint16_t myport = ntohs(address.sin_port);
4415+ if (myport > 0 )
4416+ {
4417+ returnme += lexical_cast<string>(myport);
4418+ }
4419+ else
4420+ {
4421+ returnme += "*";
4422+ };
4423+ return returnme;
4424 };
4425
4426 void tcp_socket::bind(const string & address)
4427 {
4428- if (address != "*:*")
4429- {
4430- sockaddr_in in_address = str_to_sockaddr(address);
4431- socklen_t socklen = sizeof(in_address);
4432- // try bind.
4433- if (::bind(mysock, (sockaddr*) &in_address, socklen))
4434- {
4435- // failed in some way.
4436- _last_error = errno;
4437- cant_bind_exception e;
4438- e.store(address);
4439- throw e;
4440- };
4441- }; // nop if "*:*" is passed in.
4442+ if (address != "*:*")
4443+ {
4444+ sockaddr_in in_address = str_to_sockaddr(address);
4445+ socklen_t socklen = sizeof(in_address);
4446+ // try bind.
4447+ if (::bind(mysock, (sockaddr*) &in_address, socklen))
4448+ {
4449+ // failed in some way.
4450+ _last_error = errno;
4451+ cant_bind_exception e;
4452+ e.store(address);
4453+ throw e;
4454+ };
4455+ }; // nop if "*:*" is passed in.
4456 };
4457
4458 void tcp_socket::connect(const string & address, int timeout)
4459 {
4460- sockaddr_in in_address = str_to_sockaddr(address);
4461- if (::connect(mysock, ( sockaddr *) &in_address, sizeof(in_address)))
4462- {
4463- _last_error = errno;
4464- bad_connect_exception e;
4465- e.store(address);
4466- throw e;
4467- }
4468- else
4469- {
4470- _status = sock_connect;
4471- };
4472+ sockaddr_in in_address = str_to_sockaddr(address);
4473+ if (::connect(mysock, ( sockaddr *) &in_address, sizeof(in_address)))
4474+ {
4475+ _last_error = errno;
4476+ bad_connect_exception e;
4477+ e.store(address);
4478+ throw e;
4479+ }
4480+ else
4481+ {
4482+ _status = state::sock_connect;
4483+ };
4484 };
4485
4486 void tcp_socket::close()
4487 {
4488- if (::close(mysock))
4489- {
4490- _last_error = errno;
4491- throw close_exception();
4492- }
4493- else
4494- {
4495- _status = sock_close;
4496- };
4497+ if (::close(mysock))
4498+ {
4499+ _last_error = errno;
4500+ throw close_exception();
4501+ }
4502+ else
4503+ {
4504+ _status = state::sock_close;
4505+ };
4506 };
4507
4508 int tcp_socket::put(string s, int timeout)
4509 {
4510- // set up for the testing loop.
4511- time_t endtime = time(NULL);
4512- int orig_len = s.length();
4513- endtime += timeout;
4514- // Try to send.
4515- bool done = false;
4516- while (!done)
4517- {
4518- // make an attempt.
4519- int results = transmit(s);
4520- // remove the chars already sent from the buffer and set done
4521- // if appropriate.
4522- if (results > 0)
4523- {
4524- s.erase(0,results);
4525- done = (s.length() == 0) ? true : false;
4526- };
4527- // decide what do do about any possible error results.
4528- if (results == -1)
4529- {
4530- switch (errno)
4531- {
4532- case EBADF :
4533- case ENOTSOCK:
4534- {
4535- done = true;
4536- _last_error = errno;
4537- _status = sock_close;
4538- not_open_exception e;
4539- e.store(s);
4540- throw e;
4541- break;
4542- };
4543- case ENOBUFS :
4544- case ENOMEM :
4545- {
4546- done = true;
4547- _last_error = errno;
4548- buffer_full_exception e;
4549- e.store(s);
4550- throw e;
4551- break;
4552- };
4553- case EINTR:
4554- case EAGAIN :
4555-// case EWOULDBLOCK :
4556- {
4557- usleep(50);
4558- break;
4559- };
4560- default :
4561- {
4562- done = true;
4563- _last_error = errno;
4564- general_exception e;
4565- e.store(s);
4566- throw e;
4567- break;
4568- };
4569- }; // switch (errno)
4570- }; // until error,
4571- if ((timeout > 0) && ((time(NULL) >= endtime)))
4572- {
4573- done = true;
4574- };
4575- }; // continue sending until success or error or timeout.
4576- // check for timeout.
4577- int sent = orig_len - s.length();
4578- if (sent != orig_len)
4579- {
4580- timeout_exception e;
4581- e.store(s);
4582- throw e;
4583- };
4584- return sent;
4585+ // set up for the testing loop.
4586+ time_t endtime = time(NULL);
4587+ int orig_len = s.length();
4588+ endtime += timeout;
4589+ // Try to send.
4590+ bool done = false;
4591+ while (!done)
4592+ {
4593+ // make an attempt.
4594+ int results = transmit(s);
4595+ // remove the chars already sent from the buffer and set done
4596+ // if appropriate.
4597+ if (results > 0)
4598+ {
4599+ s.erase(0,results);
4600+ done = (s.length() == 0) ? true : false;
4601+ };
4602+ // decide what do do about any possible error results.
4603+ if (results == -1)
4604+ {
4605+ switch (errno)
4606+ {
4607+ case EBADF :
4608+ case ENOTSOCK:
4609+ {
4610+ done = true;
4611+ _last_error = errno;
4612+ _status = state::sock_close;
4613+ not_open_exception e;
4614+ e.store(s);
4615+ throw e;
4616+ break;
4617+ };
4618+ case ENOBUFS :
4619+ case ENOMEM :
4620+ {
4621+ done = true;
4622+ _last_error = errno;
4623+ buffer_full_exception e;
4624+ e.store(s);
4625+ throw e;
4626+ break;
4627+ };
4628+ case EINTR:
4629+ case EAGAIN :
4630+ {
4631+ usleep(50);
4632+ break;
4633+ };
4634+ default :
4635+ {
4636+ done = true;
4637+ _last_error = errno;
4638+ general_exception e;
4639+ e.store(s);
4640+ throw e;
4641+ break;
4642+ };
4643+ }; // switch (errno)
4644+ }; // until error,
4645+ if ((timeout > 0) && ((time(NULL) >= endtime)))
4646+ {
4647+ done = true;
4648+ };
4649+ }; // continue sending until success or error or timeout.
4650+ // check for timeout.
4651+ int sent = orig_len - s.length();
4652+ if (sent != orig_len)
4653+ {
4654+ timeout_exception e;
4655+ e.store(s);
4656+ throw e;
4657+ };
4658+ return sent;
4659 };
4660
4661 string tcp_socket::get(int maxlen, int timeout)
4662 {
4663-/*
4664-micro_timer run_time;
4665-run_time.start();
4666-std::cerr << "ENTER get(" << maxlen << "," << timeout << ")" << std::endl;
4667-*/
4668- string returnme = "";
4669- returnme.reserve(maxlen);
4670- string in_buffer;
4671- // set out timeout marker.
4672- time_t endtime = time(NULL);
4673- endtime += timeout;
4674- timeval wait;
4675- // input loop
4676- bool done = false;
4677- while (!done)
4678- {
4679- time_t waittime = endtime - time(NULL);
4680- wait.tv_sec = (waittime > 0) ? waittime : 0;
4681- wait.tv_usec = 10;
4682- // set max timeout.
4683- // the assert is used because some platforms may not properly support
4684- // the SO_RCVTIMEO socket option.
4685- setsockopt(mysock,SOL_SOCKET,SO_RCVTIMEO,&wait,sizeof(wait));
4686- // is there any data waiting?
4687- int results = receive(in_buffer,maxlen-returnme.size());
4688- // was there an error?
4689- switch (results)
4690- {
4691- case 0:
4692- {
4693- if (returnme == "")
4694- {
4695- throw not_open_exception();
4696- }
4697- else
4698- {
4699- done = true;
4700- }
4701- break;
4702- }
4703- case -1 :
4704- {
4705- switch (errno)
4706- {
4707- case EBADF :
4708- case ENOTCONN :
4709- case ENOTSOCK :
4710- {
4711- done = true;
4712- _last_error = errno;
4713- _status = sock_close;
4714- if (returnme == "")
4715- {
4716- not_open_exception e;
4717- e.store(returnme);
4718- throw e;
4719- };
4720- break;
4721- }
4722- case EAGAIN : // shouldn't happen, but .....
4723- case EINTR : // this too....
4724- {
4725- if (timeout == 0)
4726- {
4727- done = true;
4728- };
4729- usleep(50);
4730- break;
4731- }
4732- default :
4733- {
4734- done = true;
4735- _last_error = errno;
4736- if (returnme == "")
4737- {
4738- general_exception e;
4739- e.store(returnme);
4740- throw e;
4741- };
4742- break;
4743- }
4744- }; // there was an error.
4745- break;
4746- }
4747- default:
4748- {
4749- returnme += in_buffer;
4750- break;
4751- }
4752- };
4753- // check boundry conditions;
4754- // -- maxlen only effective if maxlen > 0.
4755- if ((maxlen > 0) && (returnme.length() >= maxlen)) { done = true; };
4756- // -- timeout only effective if timeout > 0.
4757- if ((timeout > 0) && (time(NULL) > endtime)) { done = true; };
4758- if (timeout == 0) { done = true; };
4759-/*
4760-std::cerr << "\tstatus: " << returnme.size()
4761-<< ", done = " << done
4762-<< " (" << run_time.interval() << ")"
4763-<< std::endl;
4764-*/
4765- }; // input loop.
4766- // did we time out?
4767- if ((timeout > 0) && (time(NULL) > endtime))
4768- {
4769- timeout_exception e;
4770- e.store(returnme);
4771- throw e;
4772- };
4773- // done!
4774- return returnme;
4775+ string returnme = "";
4776+ returnme.reserve(maxlen);
4777+ string in_buffer;
4778+ // set out timeout marker.
4779+ time_t endtime = time(NULL);
4780+ endtime += timeout;
4781+ timeval wait;
4782+ // input loop
4783+ bool done = false;
4784+ while (!done)
4785+ {
4786+ time_t waittime = endtime - time(NULL);
4787+ wait.tv_sec = (waittime > 0) ? waittime : 0;
4788+ wait.tv_usec = 10;
4789+ // set max timeout.
4790+ // the assert is used because some platforms may not properly support
4791+ // the SO_RCVTIMEO socket option.
4792+ setsockopt(mysock,SOL_SOCKET,SO_RCVTIMEO,&wait,sizeof(wait));
4793+ // is there any data waiting?
4794+ int results = receive(in_buffer,maxlen-returnme.size());
4795+ // was there an error?
4796+ switch (results)
4797+ {
4798+ case 0:
4799+ {
4800+ if (returnme == "")
4801+ {
4802+ throw not_open_exception();
4803+ }
4804+ else
4805+ {
4806+ done = true;
4807+ }
4808+ break;
4809+ }
4810+ case -1 :
4811+ {
4812+ switch (errno)
4813+ {
4814+ case EBADF :
4815+ case ENOTCONN :
4816+ case ENOTSOCK :
4817+ {
4818+ done = true;
4819+ _last_error = errno;
4820+ _status = state::sock_close;
4821+ if (returnme == "")
4822+ {
4823+ not_open_exception e;
4824+ e.store(returnme);
4825+ throw e;
4826+ };
4827+ break;
4828+ }
4829+ case EAGAIN : // shouldn't happen, but .....
4830+ case EINTR : // this too....
4831+ {
4832+ if (timeout == 0)
4833+ {
4834+ done = true;
4835+ };
4836+ usleep(50);
4837+ break;
4838+ }
4839+ default :
4840+ {
4841+ done = true;
4842+ _last_error = errno;
4843+ if (returnme == "")
4844+ {
4845+ general_exception e;
4846+ e.store(returnme);
4847+ throw e;
4848+ };
4849+ break;
4850+ }
4851+ }; // there was an error.
4852+ break;
4853+ }
4854+ default:
4855+ {
4856+ returnme += in_buffer;
4857+ break;
4858+ }
4859+ };
4860+ // check boundry conditions;
4861+ // -- maxlen only effective if maxlen > 0.
4862+ if ((maxlen > 0) && (returnme.length() >= maxlen)) { done = true; };
4863+ // -- timeout only effective if timeout > 0.
4864+ if ((timeout > 0) && (time(NULL) > endtime)) { done = true; };
4865+ if (timeout == 0) { done = true; };
4866+ }; // input loop.
4867+ // did we time out?
4868+ if ((timeout > 0) && (time(NULL) > endtime))
4869+ {
4870+ timeout_exception e;
4871+ e.store(returnme);
4872+ throw e;
4873+ };
4874+ // done!
4875+ return returnme;
4876 };
4877
4878-
4879 string tcp_socket::getln(string eol, int maxlen, int timeout)
4880 {
4881- // args check.
4882- if (eol == "")
4883- {
4884- throw bad_args_exception();
4885- return eol;
4886- };
4887- // setup.
4888- string returnme = "";
4889- returnme.reserve(maxlen);
4890- int targetlen = eol.length();
4891- int searchlen = targetlen - 1;
4892- time_t endtime = time(NULL);
4893- endtime += timeout;
4894- bool done = false;
4895- bool success = false;
4896- // first, get at least as many characters as are in the eol string.
4897- try
4898- {
4899- int wait_time = timeout;
4900- if (timeout < 0) { wait_time = 0; };
4901- returnme = get(targetlen,wait_time);
4902- }
4903- catch (timeout_exception e)
4904- {
4905- // if get timed out we may be done.
4906- if (timeout >= 0) { done = true; };
4907- returnme = e.comment();
4908- };
4909- // We only need to continue if we have not gotten our token yet.
4910- if ((!done) && (returnme.length() >= targetlen))
4911- {
4912-// success = returnme.substr(returnme.length()-targetlen,targetlen) == eol;
4913- success = returnme.find(eol,returnme.length()-targetlen) != string::npos;
4914- };
4915- while (!done && !success)
4916- {
4917- // still more to get, if we have time.
4918- int timeleft = endtime - time(NULL);
4919- timeleft = (timeleft > 0) ? timeleft : 0;
4920- // can we increase our get length?
4921- int getlen = 1;
4922- if (searchlen > 1)
4923- {
4924- // see if a token start is near.
4925- if (returnme.find(eol[0],returnme.length()-searchlen) == string::npos)
4926- {
4927- // great!.. get just less than one token's worth.
4928- getlen = searchlen;
4929- }
4930- };
4931- // okay.. let's get the next chunk
4932- try
4933- {
4934- returnme += get(getlen,timeleft);
4935- }
4936- catch (timeout_exception e)
4937- {
4938- if (timeout >= 0) { done = true; };
4939- };
4940- // check boundary conditions.
4941- // -- did we get it?
4942- if (returnme.length() >= targetlen)
4943- {
4944-// success = returnme.substr(returnme.length()-targetlen,targetlen) == eol;
4945- success = returnme.find(eol,returnme.length()-targetlen) != string::npos;
4946- };
4947- // -- maxlen only effective if maxlen > 0.
4948- if ((maxlen > 0) && (returnme.length() >= maxlen)) { done = true; };
4949- };
4950- // did we error out?
4951- if (!success)
4952- {
4953- // what type of error was it?
4954- if ((maxlen > 0) && (returnme.length() >= maxlen))
4955- {
4956- overrun_exception e;
4957- e.store(returnme);
4958- throw e;
4959- }
4960- else
4961- {
4962- timeout_exception e;
4963- e.store(returnme);
4964- throw e;
4965- };
4966- };
4967- return returnme;
4968+ // args check.
4969+ if (eol == "")
4970+ {
4971+ throw bad_args_exception();
4972+ return eol;
4973+ };
4974+ // setup.
4975+ string returnme = "";
4976+ returnme.reserve(maxlen);
4977+ int targetlen = eol.length();
4978+ int searchlen = targetlen - 1;
4979+ time_t endtime = time(NULL);
4980+ endtime += timeout;
4981+ bool done = false;
4982+ bool success = false;
4983+ // first, get at least as many characters as are in the eol string.
4984+ try
4985+ {
4986+ int wait_time = timeout;
4987+ if (timeout < 0) { wait_time = 0; };
4988+ returnme = get(targetlen,wait_time);
4989+ }
4990+ catch (timeout_exception e)
4991+ {
4992+ // if get timed out we may be done.
4993+ if (timeout >= 0) { done = true; };
4994+ returnme = e.comment();
4995+ };
4996+ // We only need to continue if we have not gotten our token yet.
4997+ if ((!done) && (returnme.length() >= targetlen))
4998+ {
4999+ success = returnme.find(eol,returnme.length()-targetlen) != string::npos;
5000+ };
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: