1 /*--------------------------------------------------------------------------
2  Copyright 1999, Dan Kegel http://www.kegel.com/
3  See the file COPYING
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 --------------------------------------------------------------------------*/
19 
20 #ifndef robouser_h
21 #define robouser_h
22 
23 #include "eclock.h"					/* for clock_t - should be eclock_t */
24 #include "ftp_client_pipe.h"
25 #include "Sked.h"
26 #include <stddef.h>
27 #include <stdio.h>
28 
29 class Platoon;
30 /**--------------------------------------------------------------------------
31  Module to simulate FTP users.
32 --------------------------------------------------------------------------*/
33 class robouser_t : public ftp_client_pipe_datainterface_t, public SkedClient {
34 
35 public:
36 	/** stages in a robot's life cycle.
37 	 * Order is extremely important; see Platoon::sumInState() and
38 	 * Platoon::startUser(), which assume any state between CONNECT and
39 	 * GETTING (numerically) is alive...
40 	 */
41 	enum state_t {UNINIT,CONNECT,CONNECTING,START_TYPE,FINISH_TYPE,GET,GETTING,
42 		STOPPED};
43 	/// number of possible values of state_t
44 	static const int NUMSTATES = (((int) STOPPED)+1);
45 
46 private:
47 /* Private data members - all start with m_ */
48 	/// this struct's index in outer container
49 	int m_user;
50 
51 	/** The Platoon to which this robot belongs */
52 	Platoon *m_platoon;
53 
54 	/** where the robot is in its life cycle */
55 	state_t m_state;
56 
57 /* variables to support statistics gathering */
58 	/** when current fetch started */
59 	clock_t m_startedAt;
60 	/** so far from current file */
61 	size_t m_bytesFetched;
62 	/** number of 'packets' read so far */
63 	int m_reads;
64 
65 	/** The FTP connection to the server. */
66 	ftp_client_pipe_t m_fcp;
67 
68 
69 	/// cached value of eclock_hertz()
70 	static int s_hertz;
71 /* Public instance methods (needed by Platoon) */
72 public:
73 	/**----------------------------------------------------------------------
74 	 Constructor is public, but only Platoon::startUser should call it.
75 	----------------------------------------------------------------------*/
robouser_t(Platoon * platoon)76 	robouser_t(Platoon *platoon) { m_state = UNINIT; m_platoon = platoon; }
77 
78 	/**----------------------------------------------------------------------
79 	 Start an already-allocated robouser on its tiny-brained way.
80 	 usernum is the index of this object in an outer container.
81 
82 	 Returns 0 on success, Unix error code on failure.
83 	----------------------------------------------------------------------*/
84 	int start(int usernum);
85 
86 	/**----------------------------------------------------------------------
87 	 Shut down the fcp connection.
88 	----------------------------------------------------------------------*/
shutDown()89 	void shutDown() { m_fcp.shutdown(); }
90 
getUser()91 	int getUser() { return m_user; }
92 
93 /* Private instance methods */
94 private:
95 	/**----------------------------------------------------------------------
96 	 Pick a random file from the set we know are on the server.
97 	 For now, a bogus implementation.
98 	 Later on, we will probably expand m_filename as a template.
99 	----------------------------------------------------------------------*/
100 	void pick_random_file(char *fname);
101 
102 	/**----------------------------------------------------------------------
103 	 Jump to the given state.
104 	 Adjust counts.
105 	----------------------------------------------------------------------*/
106 	void gotoState(state_t newstate);
107 
108 	/**----------------------------------------------------------------------
109 	 Shut down one user.  Opposite of start().
110 	 Call after QUIT succeeds, or connection-fatal error detected.
111 	----------------------------------------------------------------------*/
112 	void stop();
113 
114 /* Callback functions - called by Sked and ftp_client_proto only */
115 
116     /**----------------------------------------------------------------------
117      When the time specified by addClient() has elapsed, Sked calls this method.
118     ----------------------------------------------------------------------*/
119     void skedCallback(clock_t now);
120 
121 	/**----------------------------------------------------------------------
122 	 Callback function.
123 	 Called internally by ftp_client_pipe_t::notifyPollEvent().
124 	 The operating system has told us that our data file descriptor
125 	 is ready for I/O.  This function performs the desired I/O.
126 	----------------------------------------------------------------------*/
127 	int handle_data_io(int fd, short revents, clock_t now);
128 
129 	/**----------------------------------------------------------------------
130 	 Callback function.  When any command (cd, ls, get, put, ...) finishes,
131 	 ftp_client_pipe_t::notifyPollEvent() calls this function called to alert us.
132 	----------------------------------------------------------------------*/
133 	void ftpCmdDone(int xerr, int status, const char *buf);
134 
135 	/// Get an integer that identifies this object.  Used in log messages.
getID(void)136 	int getID(void) { return m_user; }
137 };
138 
139 #endif
140