Now reads in all saved previous sessions, and also prefetches main (named) sessions

like the boot process. Prefetching standard apps does not work yet.
Note, since it always just caches the whole file regardless of what part of it had
been read (missing stuff here, and in the file cache), and since our I/O scheduler
doesn't do anything yet, it might end up slower than just reading the stuff one by
one.
Also, it currently let the triggering app/session wait while it's prefetching the
data. So although it is working, it doesn't work great at all.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13905 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-08-05 11:55:32 +00:00
parent eab435cd59
commit eeed33b66c

View File

@ -16,6 +16,7 @@
#include "launch_speedup.h"
#include <KernelExport.h>
#include <Node.h>
#include <util/kernel_cpp.h>
#include <util/khash.h>
@ -23,10 +24,8 @@
#include <thread.h>
#include <team.h>
#include <file_cache.h>
//#include <fs/fd.h>
//#include <fs/KPath.h>
#include <generic_syscall.h>
#include <Node.h>
#include <syscalls.h>
#include <unistd.h>
#include <stdlib.h>
@ -89,6 +88,7 @@ class Session {
status_t LoadFromDirectory(int fd);
status_t Save();
void Prefetch();
Session *&Next() { return fNext; }
static uint32 NextOffset() { return offsetof(Session, fNext); }
@ -255,6 +255,28 @@ start_session(team_id team, mount_id device, vnode_id node, const char *name,
return NULL;
}
// let's see if there is a prefetch session for this session
Session *prefetchSession;
if (session->IsMainSession()) {
// search for session by name
for (prefetchSession = sMainPrefetchSessions;
prefetchSession != NULL;
prefetchSession = prefetchSession->Next()) {
if (!strcmp(prefetchSession->Name(), name)) {
// found session!
break;
}
}
} else {
// ToDo: search for session by device/node ID
prefetchSession = NULL;
}
if (prefetchSession != NULL) {
TRACE(("found prefetch session %s\n", prefetchSession->Name()));
prefetchSession->Prefetch();
}
if (team >= B_OK)
hash_insert(sTeamHash, session);
@ -273,6 +295,38 @@ team_gone(team_id team, void *_session)
}
static bool
parse_node_ref(const char *string, node_ref &ref, const char **_end = NULL)
{
// parse node ref
char *end;
ref.device = strtol(string, &end, 0);
if (end == NULL || ref.device == 0)
return false;
ref.node = strtoull(end + 1, &end, 0);
if (_end)
*_end = end;
return true;
}
static struct node *
new_node(mount_id device, vnode_id id)
{
struct node *node = new ::node;
if (node == NULL)
return NULL;
node->ref.device = device;
node->ref.node = id;
node->timestamp = system_time();
return node;
}
static void
load_prefetch_data()
{
@ -286,7 +340,6 @@ load_prefetch_data()
continue;
Session *session = new Session(dirent->d_name);
dprintf("%s\n", dirent->d_name);
if (session->LoadFromDirectory(dir->fd) != B_OK) {
delete session;
@ -348,13 +401,8 @@ Session::Session(const char *name)
fNodeRef.device = -1;
fNodeRef.node = -1;
if (isdigit(name[0])) {
// parse node ref
char *end;
fNodeRef.device = strtol(name, &end, 0);
if (end != NULL)
fNodeRef.node = strtoull(end + 1, NULL, 0);
}
if (isdigit(name[0]))
parse_node_ref(name, fNodeRef);
strlcpy(fName, name, B_OS_NAME_LENGTH);
}
@ -374,7 +422,7 @@ Session::~Session()
//TRACE((" node %ld:%Ld\n", node->ref.device, node->ref.node));
free(node);
}
hash_uninit(fNodeHash);
} else {
// ... from the list
@ -424,14 +472,10 @@ Session::AddNode(mount_id device, vnode_id id)
return;
}
node = new ::node;
node = new_node(device, id);
if (node == NULL)
return;
node->ref.device = device;
node->ref.node = id;
node->timestamp = system_time();
hash_insert(fNodeHash, node);
fNodeCount++;
}
@ -448,10 +492,67 @@ Session::RemoveNode(mount_id device, vnode_id id)
}
status_t
Session::LoadFromDirectory(int fd)
void
Session::Prefetch()
{
return B_ERROR;
if (fNodes == NULL || fNodeHash != NULL)
return;
for (struct node *node = fNodes; node != NULL; node = node->next) {
cache_prefetch(node->ref.device, node->ref.node, 0, ~0UL);
}
}
status_t
Session::LoadFromDirectory(int directoryFD)
{
TRACE(("load session %s\n", Name()));
int fd = _kern_open(directoryFD, Name(), O_RDONLY, 0);
if (fd < B_OK)
return fd;
struct stat stat;
if (fstat(fd, &stat) != 0) {
close(fd);
return errno;
}
if (stat.st_size > 32768) {
// for safety reasons
// ToDo: make a bit larger later
close(fd);
return B_BAD_DATA;
}
char *buffer = (char *)malloc(stat.st_size);
if (buffer == NULL) {
close(fd);
return B_NO_MEMORY;
}
if (read(fd, buffer, stat.st_size) < stat.st_size) {
free(buffer);
close(fd);
return B_ERROR;
}
const char *line = buffer;
node_ref nodeRef;
while (parse_node_ref(line, nodeRef, &line)) {
struct node *node = new_node(nodeRef.device, nodeRef.node);
if (node != NULL) {
// note: this reverses the order of the nodes in the file
node->next = fNodes;
fNodes = node;
}
line++;
}
free(buffer);
close(fd);
return B_OK;
}