/*
* Dolda Connect - Modular multiuser Direct Connect-style client
- * Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
+ * Copyright (C) 2004 Fredrik Tolf <fredrik@dolda2000.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/** The filename to use for the hash cache (see the FILES section
* for more information). */
{CONF_VAR_STRING, "hashcache", {.str = L"dc-hashcache"}},
+ /** Writes of the hash cache and file lists are delayed for an
+ * amount of time, in order to minimize the time spent on I/O wait
+ * while hashing many small files. This variable sets the amount
+ * of time, in seconds. */
+ {CONF_VAR_INT, "hashwritedelay", {.num = 300}},
+ /** The amount of time, in seconds, to wait before automatically
+ * rescanning the shared directories for changes. Set to zero (the
+ * default) to disable automatic rescanning. (Broken shares are
+ * always rescanned upon detection, regardless of this
+ * setting.) */
+ {CONF_VAR_INT, "rescandelay", {.num = 0}},
{CONF_VAR_END}
};
* job. */
static pid_t hashjob = -1;
struct sharecache *shareroot = NULL;
+static struct timer *scantimer = NULL;
+int sharedfiles = 0;
unsigned long long sharesize = 0;
GCBCHAIN(sharechangecb, unsigned long long);
if((stream = fopen(hcname, "r")) == NULL)
{
flog(LOG_WARNING, "could not open hash cache %s: %s", hcname, strerror(errno));
+ free(hcname);
return;
}
+ free(hcname);
while(hashcache != NULL)
freehashcache(hashcache);
line = 0;
if(!now)
{
if(hashwritetimer == NULL)
- hashwritetimer = timercallback(ntime() + 300, (void (*)(int, void *))hashtimercb, NULL);
+ hashwritetimer = timercallback(ntime() + confgetint("cli", "hashwritedelay"), (void (*)(int, void *))hashtimercb, NULL);
return;
}
if(hashwritetimer != NULL)
if((stream = fopen(hcname, "w")) == NULL)
{
flog(LOG_WARNING, "could not write hash cache %s: %s", hcname, strerror(errno));
+ free(hcname);
return;
}
+ free(hcname);
fprintf(stream, "# Dolda Connect hash cache file\n");
fprintf(stream, "# Generated automatically, do not edit\n");
fprintf(stream, "# Format: DEVICE INODE MTIME [HASH...]\n");
*/
static void checkhashes(void)
{
- struct sharecache *node;
+ struct sharecache *node, *next;
struct hashcache *hc;
char *path;
node = shareroot->child;
- for(node = shareroot->child; node != NULL; node = nextscnode(node))
+ for(node = shareroot->child; node != NULL; node = next)
{
+ next = nextscnode(node);
if(node->f.b.type != FILE_REG)
continue;
if(!node->f.b.hastth)
CBCHAINDOCB(node, share_delete, node);
CBCHAINFREE(node, share_delete);
sharesize -= node->size;
+ if(node->f.b.type == FILE_REG)
+ sharedfiles--;
if(node->path != NULL)
free(node->path);
if(node->name != NULL)
if(S_ISREG(sb.st_mode))
{
sharesize += (n->size = sb.st_size);
+ sharedfiles++;
} else {
n->size = 0;
}
return(1);
}
+static void rescancb(int cancelled, void *uudata)
+{
+ scantimer = NULL;
+ if(!cancelled)
+ {
+ if(scanqueue == NULL)
+ scanshares();
+ else if(confgetint("cli", "rescandelay") > 0)
+ scantimer = timercallback(ntime() + confgetint("cli", "rescandelay"), (void (*)(int, void *))rescancb, NULL);
+ }
+}
+
void scanshares(void)
{
struct sharepoint *cur;
}
queuescan(node);
}
+ if(scantimer != NULL)
+ canceltimer(scantimer);
+ if(confgetint("cli", "rescandelay") > 0)
+ scantimer = timercallback(ntime() + confgetint("cli", "rescandelay"), (void (*)(int, void *))rescancb, NULL);
}
static void preinit(int hup)
}
}
+static int rsdelayupdate(struct configvar *var, void *uudata)
+{
+ if(scantimer != NULL)
+ canceltimer(scantimer);
+ if(confgetint("cli", "rescandelay") > 0)
+ scantimer = timercallback(ntime() + var->val.num, (void (*)(int, void *))rescancb, NULL);
+ return(0);
+}
+
static int init(int hup)
{
struct sharepoint *cur, *next;
}
scanshares();
if(!hup)
+ {
while(doscan(100));
+ CBREG(confgetvar("cli", "rescandelay"), conf_update, rsdelayupdate, NULL, NULL);
+ }
return(0);
}
{
if(hashjob != 0)
kill(hashjob, SIGHUP);
+ if(hashwritetimer != NULL)
+ writehashcache(1);
while(shares != NULL)
freesharepoint(shares);
freecache(shareroot);