Count number of lines (can be expensive).

def _iterate_lines(self):
        """Count number of lines (can be expensive)."""
        self._num_lines = 0
        self._restarts = []
        self._rs_state = []

        ln = 0
        for ln, line in enumerate(self.filehandle):
            line = line.decode("utf-8", "replace")
            if (self._has_level is None and
                    line[28:31].strip() in LogEvent.log_levels and
                    line[31:39].strip() in LogEvent.log_components):
                self._has_level = True

            # find version string (fast check to eliminate most lines)
            if "version" in line[:100]:
                logevent = LogEvent(line)
                restart = self._check_for_restart(logevent)
                if restart:
                    self._restarts.append((restart, logevent))

            if "starting :" in line or "starting:" in line:
                # look for hostname, port
                match = re.search('port=(?P<port>\d+).*host=(?P<host>\S+)',
                                  line)
                if match:
                    self._hostname = match.group('host')
                    self._port = match.group('port')

            """ For 3.0 the "[initandlisten] options:" long entry contained the
                "engine" field if WiredTiger was the storage engine. There were
                only two engines, MMAPv1 and WiredTiger
            """
            if "[initandlisten] options:" in line:
                match = re.search('replSet: "(?P<replSet>\S+)"', line)
                if match:
                    self._repl_set = match.group('replSet')

                match = re.search('engine: "(?P<engine>\S+)"', line)
                if match:
                    self._storage_engine = match.group('engine')
                else:
                    self._storage_engine = 'mmapv1'

            """ For 3.2 the "[initandlisten] options:" no longer contains the
                "engine" field So now we have to look for the "[initandlisten]
                wiredtiger_open config:" which was present in 3.0, but would
                now tell us definitively that wiredTiger is being used
            """
            if "[initandlisten] wiredtiger_open config:" in line:
                self._storage_engine = 'wiredTiger'

            if "command admin.$cmd command: { replSetInitiate:" in line:
                match = re.search('{ _id: "(?P<replSet>\S+)", '
                                  'members: (?P<replSetMembers>[^]]+ ])', line)
                if match:
                    self._repl_set = match.group('replSet')
                    self._repl_set_members = match.group('replSetMembers')

            # Replica set config logging in MongoDB 3.0+
            new_config = ("New replica set config in use: ")
            if new_config in line:
                match = re.search('{ _id: "(?P<replSet>\S+)", '
                                  'version: (?P<replSetVersion>\d+), '
                                  '(protocolVersion: (?P<replSetProtocol>\d+), )?'
                                  'members: (?P<replSetMembers>[^]]+ ])', line)
                if match:
                    self._repl_set = match.group('replSet')
                    self._repl_set_members = match.group('replSetMembers')
                    self._repl_set_protocol = match.group('replSetProtocol')
                    self._repl_set_version = match.group('replSetVersion')

            # if ("is now in state" in line and
            #        next(state for state in states if line.endswith(state))):
            if "is now in state" in line:
                tokens = line.split()
                # 2.6
                if tokens[1].endswith(']'):
                    pos = 4
                else:
                    pos = 5
                host = tokens[pos]
                rs_state = tokens[-1]
                state = (host, rs_state, LogEvent(line))
                self._rs_state.append(state)
                continue

            if "[rsMgr] replSet" in line:
                tokens = line.split()
                if self._hostname:
                    host = self._hostname + ':' + self._port
                else:
                    host = os.path.basename(self.name)
                host += ' (self)'
                if tokens[-1] in self.states:
                    rs_state = tokens[-1]
                else:
                    # 2.6
                    if tokens[1].endswith(']'):
                        pos = 2
                    else:
                        pos = 6
                    rs_state = ' '.join(tokens[pos:])

                state = (host, rs_state, LogEvent(line))
                self._rs_state.append(state)
                continue

        self._num_lines = ln + 1

        # reset logfile
        self.filehandle.seek(0)