1#!/usr/bin/python
2
3import os
4import poplib
5import imaplib
6import thread
7import time
8import sys
9import mailbox
10import random
11from optparse import OptionParser
12
13
14# default number of concurrent clients to create
15CLIENTS = 20
16
17# default number of fetch commands per client
18MESSAGES = 100
19
20# default mailbox to append from
21MAILBOX = os.path.join(os.path.dirname(__file__), "testbox")
22
23# username
24USERNAME = "testuser1"
25
26# password
27PASSWORD = "test"
28
29# number of messages to send per session
30RECONNECT = 5
31
32DEBUG = False
33
34tlocks = {}
35tdict = {}
36
37
38class IMAPClient:
39    def __init__(self, hostname, port):
40        self.conn = imaplib.IMAP4(hostname, port)
41        self.conn.debug = DEBUG
42        self.conn.login(USERNAME, PASSWORD)
43
44    def append(self, message):
45        self.conn.append("INBOX", (), "", message)
46
47    def logout(self):
48        return self.conn.logout()
49
50
51class POPClient:
52    def __init__(self, hostname, port):
53        self.conn = poplib.POP3(hostname, port)
54        self.conn.set_debuglevel(DEBUG)
55        self.conn.user(USERNAME)
56        self.conn.pass_(PASSWORD)
57
58    def check(self):
59        self.conn.stat()
60        self.conn.list()
61        self.conn.uidl()
62
63    def fetch(self):
64        count, size = self.conn.stat()
65        which = int(random.random() * count) + 1
66        self.conn.list(which)
67        self.conn.uidl(which)
68        self.conn.retr(which)
69        self.conn.top(which, 1)
70
71    def logout(self):
72        self.conn.rset()
73        self.conn.quit()
74
75
76def fillmailbox(*args):
77    c = IMAPClient('localhost', 10143)
78    mb = mailbox.mbox(MAILBOX, factory=None, create=False)
79    for msg in mb.values():
80        c.append(msg.as_string())
81        sys.stdout.write('.')
82        sys.stdout.flush()
83    sys.stdout.write('\n')
84    sys.stdout.flush()
85    c.logout()
86
87
88def frontloader(*args):
89    tid = args[0]
90    tlocks[tid].acquire()
91    c = POPClient('localhost', 10110)
92    i = 1
93    while i < MESSAGES:
94        c.check()
95        c.fetch()
96        if not i % RECONNECT:
97            c.logout()
98            c = POPClient('localhost', 10110)
99            sys.stdout.write('_')
100        else:
101            sys.stdout.write('.')
102        sys.stdout.flush()
103        i = i + 1
104        if i >= MESSAGES:
105            break
106
107    c.logout()
108    tlocks[tid].release()
109
110
111if __name__ == '__main__':
112
113    parser = OptionParser()
114    parser.add_option("-c", "--clients", dest="CLIENTS",
115        help="Number of concurrent clients [default: %default]",
116                      default=CLIENTS)
117    parser.add_option("-m", "--mailbox", dest="MAILBOX",
118        help="mailbox to feed to dbmail-deliver",
119                      default=MAILBOX)
120    parser.add_option("-n", "--messages", dest="MESSAGES",
121                      default=MESSAGES,
122                      help="number of messages to fetch [default: %default]")
123    parser.add_option("-u", "--username", dest="USERNAME",
124                      default=USERNAME,
125        help="deliver to username [default: %default]")
126    parser.add_option("-r", "--reconnect", dest="RECONNECT",
127                      default=RECONNECT,
128                      help="Number of messages to fetch before "
129                      "reconnecting [default: %default]")
130
131    (options, args) = parser.parse_args()
132
133    CLIENTS = int(options.CLIENTS)
134    MESSAGES = int(options.MESSAGES)
135    MAILBOX = options.MAILBOX
136    USERNAME = options.USERNAME
137    RECONNECT = int(options.RECONNECT)
138
139    # start the client threads
140    for i in range(0, CLIENTS):
141        tlocks[i] = thread.allocate_lock()
142
143    if MAILBOX:
144        print "Add messages from file %s to INBOX" % (
145            MAILBOX)
146        fillmailbox()
147
148    print "Doing %d fetches per client as %s" % (MESSAGES, USERNAME)
149    print "Starting %d clients" % CLIENTS
150    for i in range(0, CLIENTS):
151        id = thread.start_new_thread(frontloader, (i,))
152        tdict[i] = id
153        time.sleep(1)
154
155    time.sleep(5)
156    # wait for the clients to finish
157    while 1:
158        for i in range(0, CLIENTS):
159            done = []
160            if i in tdict:
161                r = tlocks[i].acquire(0)
162                if r:
163                    sys.stdout.write('Q')
164                    sys.stdout.flush()
165                    tlocks[i].release()
166                    done.append(i)
167            for x in done:
168                del(tlocks[x])
169                del(tdict[x])
170        if len(tdict.items()) == 0:
171            break
172        time.sleep(1)
173
174
175#EOF
176