Date:	Sunday February 15, 2004 @ 19:45
Author:	cameron

Update of /home/netrek/cvsroot/Vanilla/ntserv
In directory swashbuckler.real-time.com:/var/tmp/cvs-serv6142/ntserv

Modified Files:
	Makefile.in data.c db.c getname.c getpath.c 
Log Message:
add player file index support

****************************************

Index: Vanilla/ntserv/Makefile.in
diff -u Vanilla/ntserv/Makefile.in:1.5 Vanilla/ntserv/Makefile.in:1.6
--- Vanilla/ntserv/Makefile.in:1.5	Wed Sep 24 04:20:19 2003
+++ Vanilla/ntserv/Makefile.in	Sun Feb 15 19:45:47 2004
@@ -73,6 +73,9 @@
 commands.o: $(PMAKE) ${srcdir}/commands.c
 	$(CC) $(CFLAGS) $(DEP) -c ${srcdir}/commands.c
 
+db.o: ($PMAKE) db.c
+	$(CC) $(CFLAGS) $(DEP) `glib-config --cflags` -c $db.c
+
 cflags:
 	echo "static char cflags[]=\"$(CFLAGS) $(LIBS)\";" >../cflags.h
 
Index: Vanilla/ntserv/data.c
diff -u Vanilla/ntserv/data.c:1.19 Vanilla/ntserv/data.c:1.20
--- Vanilla/ntserv/data.c:1.19	Mon Jul  7 17:19:55 2003
+++ Vanilla/ntserv/data.c	Sun Feb 15 19:45:47 2004
@@ -1,4 +1,4 @@
-/* $Id: data.c,v 1.19 2003/07/07 22:19:55 ahn Exp $
+/* $Id: data.c,v 1.20 2004/02/16 01:45:47 cameron Exp $
  */
 
 #include "copyright.h"
@@ -237,6 +237,7 @@
 char Robot[FNAMESIZE];
 char LogFileName[FNAMESIZE];
 char PlayerFile[FNAMESIZE];
+char PlayerIndexFile[FNAMESIZE];
 char ConqFile[FNAMESIZE];
 char SysDef_File[FNAMESIZE];
 char Time_File[FNAMESIZE];
Index: Vanilla/ntserv/db.c
diff -u Vanilla/ntserv/db.c:1.1 Vanilla/ntserv/db.c:1.2
--- Vanilla/ntserv/db.c:1.1	Wed Sep 24 04:14:02 2003
+++ Vanilla/ntserv/db.c	Sun Feb 15 19:45:47 2004
@@ -11,7 +11,11 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/time.h>
+#include <time.h>
 #include <fcntl.h>
+#ifdef PLAYER_INDEX
+#include <gdbm.h>
+#endif
 #include "defs.h"
 #include INC_STRINGS
 #include INC_UNISTD
@@ -19,35 +23,169 @@
 #include "data.h"
 #include "salt.h"
 
+/* support for timing requires glib, not expected to remain */
+#define DB_TIMING 1
+#ifdef DB_TIMING
+#include <glib.h>
+#endif
+
+#ifdef PLAYER_INDEX
+
+/* fetch the offset to a player from the index database */
+static off_t db_index_fetch(char *namePick, struct statentry *player) {
+  GDBM_FILE dbf;
+  datum key, content;
+  off_t position;
+
+  /* open the player index database */
+  dbf = gdbm_open(PlayerIndexFile, 0, GDBM_WRCREAT, 0644, NULL);
+  if (dbf == NULL) {
+    ERROR(1,("db.c: db_index_fetch: gdbm_open('%s'): '%s', '%s'\n",
+	     PlayerIndexFile, gdbm_strerror(gdbm_errno), strerror(errno)));
+    return -1;
+  }
+  ERROR(8,("db.c: db_index_fetch: gdbm_open('%s'): ok\n", 
+	   PlayerIndexFile));
+
+  /* fetch the database entry for this player name */
+  key.dptr = namePick;
+  key.dsize = strlen(namePick);
+  content = gdbm_fetch(dbf, key);
+
+  /* player index may not contain this player, that's fine */
+  if (content.dptr == NULL) {
+    ERROR(8,("db.c: db_index_fetch: gdbm_fetch('%s'): not found in index\n",
+	     namePick));
+    gdbm_close(dbf);
+    return -1;
+  }
+
+  if (content.dsize != sizeof(off_t)) {
+    ERROR(8,("db.c: db_index_fetch: gdbm_fetch('%s'): dsize [%d] not sizeof(off_t) [%d]\n",
+	     namePick, content.dsize, sizeof(off_t)));
+    gdbm_close(dbf);
+    return -1;
+  }
+
+  /* return the position from the database entry */
+  position = *((off_t *) content.dptr);
+  free(content.dptr);
+  gdbm_close(dbf);
+  ERROR(8,("db.c: db_index_fetch: gdbm_fetch('%s'): index says position '%d'\n",
+	   namePick, position));
+  return position;
+}
+
+/* store the offset to a player into the index database */
+static void db_index_store(struct statentry *player, off_t position) {
+  GDBM_FILE dbf;
+  datum key, content;
+
+  /* open the player index database */
+  dbf = gdbm_open(PlayerIndexFile, 0, GDBM_WRCREAT, 0644, NULL);
+  if (dbf == NULL) { return; }
+
+  /* prepare the key and content pair from name and position */
+  key.dptr = player->name;
+  key.dsize = strlen(player->name);
+  content.dptr = (char *) &position;
+  content.dsize = sizeof(position);
+
+  /* store this key and position */
+  if (gdbm_store(dbf, key, content, GDBM_REPLACE) < 0) {
+    ERROR(8,("db.c: db_index_store: gdbm_store('%s' -> '%d'): %s, %s\n", 
+	     player->name, position, gdbm_strerror(gdbm_errno), 
+	     strerror(errno)));
+    gdbm_close(dbf);
+    return;
+  }
+
+  ERROR(8,("db.c: db_index_store: gdbm_store('%s' -> '%d'): ok\n", 
+	   player->name, position));
+  gdbm_close(dbf);
+}
 
+#endif
 
 /* given a name, find the player in the file, return position */
 int findplayer(char *namePick, struct statentry *player) {
-  int position, plfd;
+  off_t position;
+  int fd;
+#ifdef DB_TIMING
+  GTimer *timer = g_timer_new();
+#endif
 
-  /* open the player file to find the player */
-  plfd = open(PlayerFile, O_RDONLY, 0644);
-  if (plfd < 0) {
-    ERROR(1,("I cannot open the player file!\n"));
-    ERROR(1,("Error number: %d\n", errno));
+  /* open the player file */
+  fd = open(PlayerFile, O_RDONLY, 0644);
+  if (fd < 0) {
+    ERROR(1,("db.c: findplayer: open('%s'): '%s'\n", PlayerFile, 
+	     strerror(errno)));
     strcpy(player->name, namePick);
+#ifdef DB_TIMING
+    g_timer_destroy(timer);
+#endif
     return -1;
   }
 
+#ifdef PLAYER_INDEX
+  /* use the index as a hint as to position in the player file */
+  position = db_index_fetch(namePick, player);
+
+  /* if an index entry was present, read the entry to check it's right */
+  if (position != -1) {
+    lseek(fd, position * sizeof(struct statentry), SEEK_SET);
+    if (read(fd, (char *) player, sizeof(struct statentry)) < 0) {
+      /* read failed for some reason */
+      ERROR(1,("db.c: findplayer: read: '%s'\n", strerror(errno)));
+      strcpy(player->name, "");
+    }
+    /* check the entry in the main file matches what the index said */
+    if (strcmp(namePick, player->name)==0) {
+      close(fd);
+      ERROR(8,("db.c: findplayer: ok, '%s' is indeed at position '%d'\n", 
+	       namePick, position));
+#ifdef DB_TIMING
+      ERROR(8,("db.c: timing, cached resolution, %f\n", g_timer_elapsed(timer, NULL)));
+      g_timer_destroy(timer);
+#endif      
+      return position;
+    }
+    /* otherwise there's an inconsistency that we can recover from */
+    ERROR(2,("db.c: findplayer: player index inconsistent with player file, entered name '%s', index says position '%d', but file entry name '%s'\n", namePick, position, player->name));
+    /* return file to start for sequential search */
+    lseek(fd, 0, SEEK_SET);
+  }
+#endif
+
   /* sequential search of player file */
   position = 0;
-  while (read(plfd, (char *) player, sizeof(struct statentry)) ==
+  while (read(fd, (char *) player, sizeof(struct statentry)) ==
 	 sizeof(struct statentry)) {
     if (strcmp(namePick, player->name)==0) {
-      close(plfd);
+      close(fd);
+#ifdef PLAYER_INDEX
+      db_index_store(player, position);
+#endif
+      ERROR(8,("db.c: findplayer: '%s' found in sequential scan at position '%d'\n", 
+	       namePick, position));
+#ifdef DB_TIMING
+      ERROR(8,("db.c: timing, sequential resolution, %f\n", g_timer_elapsed(timer, NULL)));
+      g_timer_destroy(timer);
+#endif      
       return position;
     }
     position++;
   }
 
   /* not found, return failure */
-  close(plfd);
+  close(fd);
   strcpy(player->name, namePick);
+  ERROR(8,("db.c: findplayer: '%s' not found in sequential scan\n", 
+	   namePick));
+#ifdef DB_TIMING
+  ERROR(8,("db.c: timing, sequential failure, %f\n", g_timer_elapsed(timer, NULL)));
+  g_timer_destroy(timer);
+#endif      
   return -1;
 }
 
@@ -55,6 +193,7 @@
 {
     int fd;
     if (me->p_pos < 0) return;
+    ERROR(8,("db.c: savepass: saving to position '%d'\n", me->p_pos));
     fd = open(PlayerFile, O_WRONLY, 0644);
     if (fd >= 0) {
 	lseek(fd, me->p_pos * sizeof(struct statentry) +
@@ -95,12 +234,24 @@
 
 int newplayer(struct statentry *player)
 {
-  int plfd, file_pos;
+  int fd, offset, position;
+
+  ERROR(8,("db.c: newplayer: adding '%s'\n", player->name));
+
+  fd = open(PlayerFile, O_RDWR|O_CREAT, 0644);
+  if (fd < 0) return -1;
+  if ((offset = lseek(fd, 0, SEEK_END)) < 0) return -1;
+  write(fd, (char *) player, sizeof(struct statentry));
+  close(fd);
+  position = offset / sizeof(struct statentry);
+
+  ERROR(8,("db.c: newplayer: sizeof '%d' offset '%d' position '%d'\n", 
+	   sizeof(struct statentry), offset, position));
+
+#ifdef PLAYER_INDEX
+  /* do not create an index entry until the character name is reused,
+     because not all characters are re-used */
+#endif
 
-  plfd = open(PlayerFile, O_RDWR|O_CREAT, 0644);
-  if (plfd < 0) return -1;
-  if ((file_pos = lseek(plfd, 0, SEEK_END)) < 0) return -1;
-  write(plfd, (char *) &player, sizeof(struct statentry));
-  close(plfd);
-  return file_pos / sizeof(struct statentry);
+  return position;
 }
Index: Vanilla/ntserv/getname.c
diff -u Vanilla/ntserv/getname.c:1.13 Vanilla/ntserv/getname.c:1.14
--- Vanilla/ntserv/getname.c:1.13	Sat Aug 23 01:14:19 2003
+++ Vanilla/ntserv/getname.c	Sun Feb 15 19:45:47 2004
@@ -68,12 +68,10 @@
 	readFromClient();
     }
 
-    /*
     ERROR(8,("handleLogin: %s %s %s\n", 
 	     passPick[15] == 0 ? "attempt" : "query", namePick, passPick));
-    */
 
-    if ((strcmp(namePick, "Guest")==0 || strcmp(namePick, "guest")==0) &&
+    if (streq(namePick, "Guest") || streq(namePick, "guest") &&
 	!lockout()) {
 
     handlelogin_guest:
@@ -83,7 +81,7 @@
 	  flushSockBuf();
 	  return;
 	}
-	/* todo: we don't check for existing players on INL robot entry */
+	/* todo: we don't check for existing guests on INL robot entry */
 
 	hourratio=5;
 	MZERO(&player.stats, sizeof(struct stats));
@@ -132,13 +130,13 @@
     hourratio=1;
 
     /* We look for the guy in the stat file */
-    if (strcmp(player.name, namePick) != 0) {
+    if (!streq(player.name, namePick)) {
         position = findplayer(namePick, &player);
     } 
 
     /* Was this just a query? */
     if (passPick[15]!=0) {
-	if (position== -1) {
+	if (position == -1) {
 	    sendClientLogin(NULL);
 	} else {
 	    sendClientLogin(&player.stats);
@@ -164,7 +162,7 @@
 #endif
 
     /* A new guy? */
-    if ((position== -1) && !lockout()) {
+    if ((position == -1) && !lockout()) {
 	strcpy(player.name, namePick);
 	/* Linux: compiler warnings with -Wall here, as crypt is in unistd.h
 	   but needs _XOPEN_SOURCE defined, which then breaks lots of other
@@ -202,10 +200,10 @@
 	 !streq(player.password, (char *) crypt(passPick, player.password)))) {
 	    sendClientLogin(NULL);
 	    flushSockBuf();
-	    /* ERROR(8,("handleLogin: password-failure namePick=%s passPick=%s file=%s newstyle=%s oldstyle=%s\n", namePick, passPick, player.password, newpass, (char *) crypt(passPick, player.password))); */
+	    ERROR(8,("handleLogin: password-failure namePick=%s passPick=%s file=%s newstyle=%s oldstyle=%s\n", namePick, passPick, player.password, newpass, (char *) crypt(passPick, player.password)));
 	    return;
     }
-    /* ERROR(8,("handleLogin: password-success namePick=%s passPick=%s file=%s newstyle=%s oldstyle=%s\n", namePick, passPick, player.password, newpass, (char *) crypt(passPick, player.password))); */
+    ERROR(8,("handleLogin: password-success namePick=%s passPick=%s file=%s newstyle=%s oldstyle=%s\n", namePick, passPick, player.password, newpass, (char *) crypt(passPick, player.password)));
     sendClientLogin(&player.stats);
     strcpy(me->p_name, namePick);
     me->p_pos=position;
Index: Vanilla/ntserv/getpath.c
diff -u Vanilla/ntserv/getpath.c:1.6 Vanilla/ntserv/getpath.c:1.7
--- Vanilla/ntserv/getpath.c:1.6	Mon Jul  7 17:19:55 2003
+++ Vanilla/ntserv/getpath.c	Sun Feb 15 19:45:47 2004
@@ -41,6 +41,8 @@
 
    sprintf(PlayerFile,"%s/%s",path,N_PLAYERFILE);
 
+   sprintf(PlayerIndexFile,"%s/%s",path,N_PLAYERINDEXFILE);
+
    sprintf(ConqFile,"%s/%s",path,N_CONQFILE);
 
    sprintf(SysDef_File,"%s/%s",path,N_SYSDEF_FILE);

_______________________________________________
vanilla-devel mailing list
vanilla-devel at us.netrek.org
https://mailman.real-time.com/mailman/listinfo/vanilla-devel