60 |
60 |
61 # seek to end of file |
61 # seek to end of file |
62 self.file.seek(0, os.SEEK_END) |
62 self.file.seek(0, os.SEEK_END) |
63 |
63 |
64 # read offset |
64 # read offset |
65 # XXX; why -2 ? |
65 # XXX: hack -1 to get rid of trailing newline |
66 size = offset = self.file.tell() - 2 |
66 size = offset = self.file.tell() - 1 |
67 |
67 |
68 # use this blocksize |
68 # use this blocksize |
69 BLOCKSIZE = 1024 |
69 BLOCKSIZE = 1024 |
70 |
70 |
71 # trailing data |
71 # trailing data |
72 buf = '' |
72 buf = '' |
73 |
73 |
74 # read a block at a time, backwards |
74 # read a block at a time, backwards |
75 while count > 0 and offset >= 0: |
75 while len(lines) < count and offset > 0: |
76 # update offset back one block |
76 # calc new offset + size |
77 offset -= BLOCKSIZE |
77 if offset > BLOCKSIZE : |
78 |
78 # full block |
79 # normalize to zero |
79 offset -= BLOCKSIZE |
80 if offset < 0 : |
80 read_size = BLOCKSIZE |
|
81 |
|
82 else : |
|
83 # partial block |
|
84 read_size = offset |
81 offset = 0 |
85 offset = 0 |
82 |
86 |
83 # seek to offset |
87 # seek to offset |
84 self.file.seek(offset) |
88 self.file.seek(offset) |
85 |
89 |
86 # add the new block to our buffer |
90 # read the data we want |
87 read_buf = self.file.read(BLOCKSIZE) |
91 read_buf = self.file.read(read_size) |
88 |
92 read_len = len(read_buf) |
89 # XXX: trim off extra... |
93 |
90 if len(read_buf) > BLOCKSIZE : |
94 # sanity check |
91 read_buf = read_buf[:BLOCKSIZE] |
95 assert read_len == read_size |
92 |
|
93 # make sure we got the right amount of data |
|
94 assert len(read_buf) == BLOCKSIZE, "read(%d) @ %d/%d -> %d" % (BLOCKSIZE, offset, size, len(read_buf)) |
|
95 |
96 |
96 # add in our previous buf |
97 # add in our previous buf |
97 buf = read_buf + buf |
98 buf = read_buf + buf |
98 |
99 |
99 # split out lines |
100 # split out lines |
100 buf_lines = buf.split(self.sep) |
101 buf_lines = buf.split(self.sep) |
101 |
102 |
102 # keep the first one as our buffer, as it's incomplete |
103 # keep the first one as our buffer, as it's incomplete |
103 buf = buf_lines[0] |
104 buf = buf_lines[0] |
104 |
105 |
105 # add up to count lines to our lines buffer |
106 # prepend up to count lines from the end to our lines buffer |
106 lines = buf_lines[-min(count, len(buf_lines) - 1):] + lines |
107 lines = buf_lines[-min(count, len(buf_lines) - 1):] + lines |
107 |
108 |
108 # update count |
109 # decode |
109 count -= (len(buf_lines) - 1) |
110 # XXX: better queue implementation, plz |
|
111 lines = [line.decode(self.charset) for line in lines] |
110 |
112 |
111 # return the line list |
113 # return the line list |
112 return lines |
114 return lines |
113 |
115 |
114 class LogDirectory (LogSource) : |
116 class LogDirectory (LogSource) : |