From 70cac98b6e1871cf93b379a4834de1778853de86 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 17 Nov 2005 17:41:02 +0000 Subject: r11760: fix sequential reads in the eventlog; event viewer is behaving better now as well but needs more testing (This used to be commit ba2f94aeae1f8e69d53fc360785adf222a8c9c6e) --- source3/rpc_server/srv_eventlog_nt.c | 186 ++++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 81 deletions(-) (limited to 'source3/rpc_server') diff --git a/source3/rpc_server/srv_eventlog_nt.c b/source3/rpc_server/srv_eventlog_nt.c index 6413221031..0f0b73029a 100644 --- a/source3/rpc_server/srv_eventlog_nt.c +++ b/source3/rpc_server/srv_eventlog_nt.c @@ -28,6 +28,7 @@ typedef struct { char *logname; TDB_CONTEXT *tdb; + uint32 current_record; uint32 num_records; uint32 oldest_entry; uint32 flags; @@ -130,6 +131,45 @@ static BOOL elog_validate_logname( const char *name ) return False; } +/******************************************************************** +********************************************************************/ + +static BOOL get_num_records_hook( EVENTLOG_INFO * info ) +{ + int next_record; + int oldest_record; + + if ( !info->tdb ) { + DEBUG( 10, ( "No open tdb for %s\n", info->logname ) ); + return False; + } + + /* lock the tdb since we have to get 2 records */ + + tdb_lock_bystring( info->tdb, EVT_NEXT_RECORD, 1 ); + next_record = tdb_fetch_int32( info->tdb, EVT_NEXT_RECORD); + oldest_record = tdb_fetch_int32( info->tdb, EVT_OLDEST_ENTRY); + tdb_unlock_bystring( info->tdb, EVT_NEXT_RECORD); + + DEBUG( 8, + ( "Oldest Record %d; Next Record %d\n", oldest_record, + next_record ) ); + + info->num_records = ( next_record - oldest_record ); + info->oldest_entry = oldest_record; + + return True; +} + +/******************************************************************** + ********************************************************************/ + +static BOOL get_oldest_entry_hook( EVENTLOG_INFO * info ) +{ + /* it's the same thing */ + return get_num_records_hook( info ); +} + /******************************************************************** ********************************************************************/ @@ -199,6 +239,15 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn return NT_STATUS_NO_MEMORY; } + /* set the initial current_record pointer */ + + if ( !get_oldest_entry_hook( elog ) ) { + DEBUG(3,("elog_open: Successfully opened eventlog but can't " + "get any information on internal records!\n")); + } + + elog->current_record = elog->oldest_entry; + return NT_STATUS_OK; } @@ -397,45 +446,6 @@ static BOOL sync_eventlog_params( EVENTLOG_INFO *info ) return True; } -/******************************************************************** -********************************************************************/ - -static BOOL get_num_records_hook( EVENTLOG_INFO * info ) -{ - int next_record; - int oldest_record; - - if ( !info->tdb ) { - DEBUG( 10, ( "No open tdb for %s\n", info->logname ) ); - return False; - } - - /* lock the tdb since we have to get 2 records */ - - tdb_lock_bystring( info->tdb, EVT_NEXT_RECORD, 1 ); - next_record = tdb_fetch_int32( info->tdb, EVT_NEXT_RECORD); - oldest_record = tdb_fetch_int32( info->tdb, EVT_OLDEST_ENTRY); - tdb_unlock_bystring( info->tdb, EVT_NEXT_RECORD); - - DEBUG( 8, - ( "Oldest Record %d; Next Record %d\n", oldest_record, - next_record ) ); - - info->num_records = ( next_record - oldest_record ); - info->oldest_entry = oldest_record; - - return True; -} - -/******************************************************************** - ********************************************************************/ - -static BOOL get_oldest_entry_hook( EVENTLOG_INFO * info ) -{ - /* it's the same thing */ - return get_num_records_hook( info ); -} - /******************************************************************** ********************************************************************/ @@ -661,71 +671,85 @@ NTSTATUS _eventlog_read_eventlog( pipes_struct * p, { EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle ); Eventlog_entry entry, *ee_new; - uint32 num_records_read = 0; prs_struct *ps; int bytes_left, record_number; - TDB_CONTEXT *tdb; - info->flags = q_u->flags; ps = &p->out_data.rdata; + uint32 elog_read_type, elog_read_dir; bytes_left = q_u->max_read_size; - tdb = info->tdb; - if ( !tdb ) { + + if ( !info->tdb ) return NT_STATUS_ACCESS_DENIED; + + /* check for valid flags. Can't use the sequential and seek flags together */ + + elog_read_type = q_u->flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ); + elog_read_dir = q_u->flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ); + + if ( elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) + || elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ) ) + { + DEBUG(3,("_eventlog_read_eventlog: Invalid flags [0x%x] for ReadEventLog\n", q_u->flags)); + return NT_STATUS_INVALID_PARAMETER; } - /* DEBUG(8,("Bytes left is %d\n",bytes_left)); */ + /* a sequential read should ignore the offset */ - record_number = q_u->offset; + if ( elog_read_type & EVENTLOG_SEQUENTIAL_READ ) + record_number = info->current_record; + else + record_number = q_u->offset; while ( bytes_left > 0 ) { - if ( get_eventlog_record - ( ps, tdb, record_number, &entry ) ) { - DEBUG( 8, - ( "Retrieved record %d\n", record_number ) ); + + /* assume that when the record fetch fails, that we are done */ + + if ( !get_eventlog_record ( ps, info->tdb, record_number, &entry ) ) + break; + + DEBUG( 8, ( "Retrieved record %d\n", record_number ) ); - /* Now see if there is enough room to add */ - ee_new = read_package_entry( ps, q_u, r_u,&entry ); - if ( !ee_new ) - return NT_STATUS_NO_MEMORY; - - if ( r_u->num_bytes_in_resp + ee_new->record.length > - q_u->max_read_size ) { - r_u->bytes_in_next_record = - ee_new->record.length; - - /* response would be too big to fit in client-size buffer */ + /* Now see if there is enough room to add */ + + if ( !(ee_new = read_package_entry( ps, q_u, r_u,&entry )) ) + return NT_STATUS_NO_MEMORY; + + if ( r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size ) { + r_u->bytes_in_next_record = ee_new->record.length; + + /* response would be too big to fit in client-size buffer */ - bytes_left = 0; - break; - } + bytes_left = 0; + break; + } - add_record_to_resp( r_u, ee_new ); - bytes_left -= ee_new->record.length; - ZERO_STRUCT( entry ); - num_records_read = - r_u->num_records - num_records_read; + add_record_to_resp( r_u, ee_new ); + bytes_left -= ee_new->record.length; + ZERO_STRUCT( entry ); + num_records_read = r_u->num_records - num_records_read; - DEBUG( 10, - ( "_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n", - num_records_read, r_u->num_records, - r_u->num_bytes_in_resp, - q_u->max_read_size ) ); - } else { - DEBUG( 8, ( "get_eventlog_record returned NULL\n" ) ); - return NT_STATUS_NO_MEMORY; /* wrong error - but return one anyway */ - } - + DEBUG( 10, ( "_eventlog_read_eventlog: read [%d] records for a total " + "of [%d] records using [%d] bytes out of a max of [%d].\n", + num_records_read, r_u->num_records, + r_u->num_bytes_in_resp, + q_u->max_read_size ) ); if ( info->flags & EVENTLOG_FORWARDS_READ ) record_number++; else record_number--; + + /* update the eventlog record pointer */ + + info->current_record = record_number; } - - return NT_STATUS_OK; + + /* crazy by WinXP uses NT_STATUS_BUFFER_TOO_SMALL to + say when there are no more records */ + + return (num_records_read ? NT_STATUS_OK : NT_STATUS_BUFFER_TOO_SMALL); } /******************************************************************** -- cgit