11/*
2- * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.66 2007/05/24 18:54:10 tgl Exp $
2+ * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.67 2007/07/06 13:36:55 wieck Exp $
33 *
44 * pgbench: a simple benchmark program for PostgreSQL
55 * written by Tatsuo Ishii
@@ -114,6 +114,8 @@ typedef struct
114114int ecnt ;/* error count */
115115int listen ;/* 0 indicates that an async query has been
116116 * sent */
117+ int sleeping ;/* 1 indicates that the client is napping */
118+ struct timeval until ;/* napping until */
117119Variable * variables ;/* array of variable definitions */
118120int nvariables ;
119121struct timeval txn_begin ;/* used for measuring latencies */
@@ -445,6 +447,20 @@ doCustom(CState * state, int n, int debug)
445447top :
446448commands = sql_files [st -> use_file ];
447449
450+ if (st -> sleeping )
451+ {/* are we sleeping? */
452+ int usec ;
453+ struct timeval now ;
454+
455+ gettimeofday (& now ,NULL );
456+ usec = (st -> until .tv_sec - now .tv_sec )* 1000000 +
457+ st -> until .tv_usec - now .tv_usec ;
458+ if (usec <=0 )
459+ st -> sleeping = 0 ;/* Done sleeping, go ahead with next command */
460+ else
461+ return ;/* Still sleeping, nothing to do here */
462+ }
463+
448464if (st -> listen )
449465{/* are we receiver? */
450466if (commands [st -> state ]-> type == SQL_COMMAND )
@@ -711,6 +727,32 @@ doCustom(CState * state, int n, int debug)
711727
712728st -> listen = 1 ;
713729}
730+ else if (pg_strcasecmp (argv [0 ],"usleep" )== 0 )
731+ {
732+ char * var ;
733+ int usec ;
734+ struct timeval now ;
735+
736+ if (* argv [1 ]== ':' )
737+ {
738+ if ((var = getVariable (st ,argv [1 ]+ 1 ))== NULL )
739+ {
740+ fprintf (stderr ,"%s: undefined variable %s\n" ,argv [0 ],argv [1 ]);
741+ st -> ecnt ++ ;
742+ return ;
743+ }
744+ usec = atoi (var );
745+ }
746+ else
747+ usec = atoi (argv [1 ]);
748+
749+ gettimeofday (& now ,NULL );
750+ st -> until .tv_sec = now .tv_sec + (now .tv_usec + usec ) /1000000 ;
751+ st -> until .tv_usec = (now .tv_usec + usec ) %1000000 ;
752+ st -> sleeping = 1 ;
753+
754+ st -> listen = 1 ;
755+ }
714756
715757gototop ;
716758}
@@ -921,9 +963,21 @@ process_commands(char *buf)
921963fprintf (stderr ,"%s: extra argument \"%s\" ignored\n" ,
922964my_commands -> argv [0 ],my_commands -> argv [j ]);
923965}
966+ else if (pg_strcasecmp (my_commands -> argv [0 ],"usleep" )== 0 )
967+ {
968+ if (my_commands -> argc < 2 )
969+ {
970+ fprintf (stderr ,"%s: missing argument\n" ,my_commands -> argv [0 ]);
971+ return NULL ;
972+ }
973+
974+ for (j = 2 ;j < my_commands -> argc ;j ++ )
975+ fprintf (stderr ,"%s: extra argument \"%s\" ignored\n" ,
976+ my_commands -> argv [0 ],my_commands -> argv [j ]);
977+ }
924978else
925979{
926- fprintf (stderr ,"invalid command %s\n" ,my_commands -> argv [0 ]);
980+ fprintf (stderr ,"Invalid command %s\n" ,my_commands -> argv [0 ]);
927981return NULL ;
928982}
929983}
@@ -1143,6 +1197,9 @@ main(int argc, char **argv)
11431197fd_set input_mask ;
11441198int nsocks ;/* return from select(2) */
11451199int maxsock ;/* max socket number to be waited */
1200+ struct timeval now ;
1201+ struct timeval timeout ;
1202+ int min_usec ;
11461203
11471204#ifdef HAVE_GETRLIMIT
11481205struct rlimit rlim ;
@@ -1526,11 +1583,33 @@ main(int argc, char **argv)
15261583FD_ZERO (& input_mask );
15271584
15281585maxsock = -1 ;
1586+ min_usec = -1 ;
15291587for (i = 0 ;i < nclients ;i ++ )
15301588{
15311589Command * * commands = sql_files [state [i ].use_file ];
15321590
1533- if (state [i ].con && commands [state [i ].state ]-> type != META_COMMAND )
1591+ if (state [i ].sleeping )
1592+ {
1593+ int this_usec ;
1594+ int sock = PQsocket (state [i ].con );
1595+
1596+ if (min_usec < 0 )
1597+ {
1598+ gettimeofday (& now ,NULL );
1599+ min_usec = 0 ;
1600+ }
1601+
1602+ this_usec = (state [i ].until .tv_sec - now .tv_sec )* 1000000 +
1603+ state [i ].until .tv_usec - now .tv_usec ;
1604+
1605+ if (this_usec > 0 && (min_usec == 0 || this_usec < min_usec ))
1606+ min_usec = this_usec ;
1607+
1608+ FD_SET (sock ,& input_mask );
1609+ if (maxsock < sock )
1610+ maxsock = sock ;
1611+ }
1612+ else if (state [i ].con && commands [state [i ].state ]-> type != META_COMMAND )
15341613{
15351614int sock = PQsocket (state [i ].con );
15361615
@@ -1547,8 +1626,18 @@ main(int argc, char **argv)
15471626
15481627if (maxsock != -1 )
15491628{
1550- if ((nsocks = select (maxsock + 1 ,& input_mask , (fd_set * )NULL ,
1551- (fd_set * )NULL , (struct timeval * )NULL ))< 0 )
1629+ if (min_usec >=0 )
1630+ {
1631+ timeout .tv_sec = min_usec /1000000 ;
1632+ timeout .tv_usec = min_usec %1000000 ;
1633+
1634+ nsocks = select (maxsock + 1 ,& input_mask , (fd_set * )NULL ,
1635+ (fd_set * )NULL ,& timeout );
1636+ }
1637+ else
1638+ nsocks = select (maxsock + 1 ,& input_mask , (fd_set * )NULL ,
1639+ (fd_set * )NULL , (struct timeval * )NULL );
1640+ if (nsocks < 0 )
15521641{
15531642if (errno == EINTR )
15541643continue ;
@@ -1557,6 +1646,7 @@ main(int argc, char **argv)
15571646fprintf (stderr ,"select failed: %s\n" ,strerror (errno ));
15581647exit (1 );
15591648}
1649+ #ifdef NOT_USED
15601650else if (nsocks == 0 )
15611651{/* timeout */
15621652fprintf (stderr ,"select timeout\n" );
@@ -1567,6 +1657,7 @@ main(int argc, char **argv)
15671657}
15681658exit (0 );
15691659}
1660+ #endif
15701661}
15711662
15721663/* ok, backend returns reply */