Changeset: 4f7f8cf9b789 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=4f7f8cf9b789
Modified Files:
clients/Tests/exports.stable.out
clients/mapilib/mapi.c
common/stream/stream.c
gdk/gdk_atomic.h
gdk/gdk_hash.c
gdk/gdk_orderidx.c
gdk/gdk_private.h
gdk/gdk_system.c
gdk/gdk_system.h
gdk/gdk_utils.c
monetdb5/mal/mal.c
monetdb5/modules/mal/remote.c
sql/backends/monet5/sql_scenario.c
Branch: default
Log Message:
Merge with Apr2019 branch.
diffs (truncated from 1103 to 300 lines):
diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -317,6 +317,8 @@ void *MT_thread_getdata(void);
const char *MT_thread_getname(void);
bool MT_thread_init(void);
void MT_thread_setdata(void *data);
+void MT_thread_setlockwait(MT_Lock *lock);
+void MT_thread_setsemawait(MT_Sema *sema);
void OIDXdestroy(BAT *b);
ssize_t OIDfromStr(const char *src, size_t *len, oid **dst, bool external);
ssize_t OIDtoStr(str *dst, size_t *len, const oid *src, bool external);
diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -733,6 +733,9 @@
#define MAPIBLKSIZE 256 /* minimum buffer shipped */
+/* number of elements in an array */
+#define NELEM(arr) (sizeof(arr) / sizeof(arr[0]))
+
/* information about the columns in a result set */
struct MapiColumn {
char *tablename;
@@ -1138,7 +1141,7 @@ wsaerror(int err)
{
int i;
- for (i = 0; i < sizeof(wsaerrlist) / sizeof(wsaerrlist[0]); i++)
+ for (i = 0; i < NELEM(wsaerrlist); i++)
if (wsaerrlist[i].e == err)
return wsaerrlist[i].m;
return "Unknown error";
@@ -2237,7 +2240,7 @@ mapi_reconnect(Mapi mid)
socks[i].owner =
st.st_uid;
socks[i++].port =
atoi(e->d_name + 11);
}
- if (i == sizeof(socks) /
sizeof(socks[0]))
+ if (i == NELEM(socks))
break;
}
closedir(d);
@@ -2775,7 +2778,7 @@ mapi_reconnect(Mapi mid)
break;
case '^':
r = mid->redirects;
- m = sizeof(mid->redirects) /
sizeof(mid->redirects[0]) - 1;
+ m = NELEM(mid->redirects) - 1;
while (*r != NULL && m > 0) {
m--;
r++;
diff --git a/common/stream/stream.c b/common/stream/stream.c
--- a/common/stream/stream.c
+++ b/common/stream/stream.c
@@ -2736,7 +2736,21 @@ socket_wstream(SOCKET sock, const char *
/* streams working on an open file pointer */
#ifdef _MSC_VER
-/* special case code for reading from/writing to a Windows cmd window */
+/* special case code for reading from/writing to a Windows console and
+ * for reading from a Windows pipe
+ *
+ * For reading from and writing to the console we can use a wide
+ * character interface which means that we are independent of the code
+ * page being used. We can translate the wide characters (which are
+ * Unicode code points) easily to UTF-8.
+ *
+ * Both for reading from the console and from a pipe, we avoid hanging
+ * (waiting for input) in the read function. Instead, we only call
+ * the read function when we know there is input available. This is
+ * to prevent a deadlock situation, especially for reading from pipes,
+ * when another thread were to also interact with pipes (as happend in
+ * the scipy Python module as used in the sql/backends/monet5/pyapi05
+ * test). */
struct console {
HANDLE h;
@@ -2760,6 +2774,8 @@ console_read(stream *restrict s, void *r
if (n == 0)
return 0;
if (c->rd == c->len) {
+ while (WaitForSingleObject(c->h, INFINITE) == WAIT_TIMEOUT)
+ ;
if (!ReadConsoleW(c->h, c->wbuf, 8192, &c->len, NULL)) {
s->errnr = MNSTR_READ_ERROR;
return -1;
@@ -2914,6 +2930,58 @@ console_write(stream *restrict s, const
return (ssize_t) ((p - (const unsigned char *) buf) / elmsize);
}
+static ssize_t
+pipe_read(stream *restrict s, void *restrict buf, size_t elmsize, size_t cnt)
+{
+ HANDLE h = s->stream_data.p;
+ size_t n = elmsize * cnt;
+ unsigned char *p = buf;
+ DWORD nread;
+
+ if (h == NULL) {
+ s->errnr = MNSTR_READ_ERROR;
+ return -1;
+ }
+ if (n == 0)
+ return 0;
+ for (;;) {
+ DWORD ret = PeekNamedPipe(h, NULL, 0, NULL, &nread, NULL);
+ if (ret == 0) {
+ if (GetLastError() == ERROR_BROKEN_PIPE)
+ return 0;
+ s->errnr = MNSTR_READ_ERROR;
+ return -1;
+ }
+ if (nread > 0)
+ break;
+ Sleep(100);
+ }
+ if ((size_t) nread < n)
+ n = (size_t) nread;
+ if (!ReadFile(h, buf, (DWORD) n, &nread, NULL)) {
+ s->errnr = MNSTR_READ_ERROR;
+ return -1;
+ }
+ /* when in text mode, convert \r\n line endings to \n */
+ if (!s->binary) {
+ char *p1, *p2, *pe;
+
+ p1 = buf;
+ pe = p1 + nread;
+ while (p1 < pe && *p1 != '\r')
+ p1++;
+ p2 = p1;
+ while (p1 < pe) {
+ if (*p1 == '\r' /*&& p1[1] == '\n'*/)
+ nread--;
+ else
+ *p2++ = *p1;
+ p1++;
+ }
+ }
+ return nread / elmsize;
+}
+
static void
console_destroy(stream *s)
{
@@ -3008,26 +3076,43 @@ file_rastream(FILE *restrict fp, const c
}
}
#ifdef _MSC_VER
- if (fileno(fp) == 0 && isatty(0)) {
- struct console *c = malloc(sizeof(struct console));
- if (c == NULL) {
- destroy(s);
- return NULL;
+ if (fp == stdin) {
+ HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
+
+ switch (GetFileType(h)) {
+ case FILE_TYPE_PIPE:
+ s->stream_data.p = h;
+ s->read = pipe_read;
+ s->write = NULL;
+ s->destroy = destroy;
+ s->close = NULL;
+ s->flush = NULL;
+ s->fsync = NULL;
+ s->fgetpos = NULL;
+ s->fsetpos = NULL;
+ break;
+ case FILE_TYPE_CHAR: {
+ struct console *c = malloc(sizeof(struct console));
+ if (c == NULL) {
+ destroy(s);
+ return NULL;
+ }
+ s->stream_data.p = c;
+ *c = (struct console) {
+ .h = h,
+ };
+ s->read = console_read;
+ s->write = NULL;
+ s->destroy = console_destroy;
+ s->close = NULL;
+ s->flush = NULL;
+ s->fsync = NULL;
+ s->fgetpos = NULL;
+ s->fsetpos = NULL;
+ s->isutf8 = true;
+ break;
}
- s->stream_data.p = c;
- *c = (struct console) {
- .h = GetStdHandle(STD_INPUT_HANDLE),
- };
- s->read = console_read;
- s->write = NULL;
- s->destroy = console_destroy;
- s->close = NULL;
- s->flush = NULL;
- s->fsync = NULL;
- s->fgetpos = NULL;
- s->fsetpos = NULL;
- s->isutf8 = true;
- return s;
+ }
}
#endif
return s;
diff --git a/gdk/gdk_atomic.h b/gdk/gdk_atomic.h
--- a/gdk/gdk_atomic.h
+++ b/gdk/gdk_atomic.h
@@ -64,9 +64,7 @@
#define ATOMIC_TAS(var, lck) (AO_test_and_set_full(&var) != AO_TS_CLEAR)
#define ATOMIC_ISSET(var, lck) (var != AO_TS_CLEAR)
-#else
-
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) &&
!defined(NO_ATOMIC_INSTRUCTIONS)
+#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) &&
!defined(NO_ATOMIC_INSTRUCTIONS)
#include <intrin.h>
@@ -273,8 +271,6 @@ static inline bool
}
#define ATOMIC_ISSET(var, lck) __ATOMIC_ISSET(&var, &(lck).lock)
-#endif
-
#endif /* LIBATOMIC_OPS */
#endif /* _GDK_ATOMIC_H_ */
diff --git a/gdk/gdk_hash.c b/gdk/gdk_hash.c
--- a/gdk/gdk_hash.c
+++ b/gdk/gdk_hash.c
@@ -170,73 +170,78 @@ BATcheckhash(BAT *b)
bool ret;
lng t = 0;
- ACCELDEBUG t = GDKusec();
- MT_lock_set(&GDKhashLock(b->batCacheid));
- ACCELDEBUG t = GDKusec() - t;
+ /* we don't need the lock just to read the value b->thash */
if (b->thash == (Hash *) 1) {
- Hash *h;
- const char *nme = BBP_physical(b->batCacheid);
- int fd;
+ /* but when we want to change it, we need the lock */
+ ACCELDEBUG t = GDKusec();
+ MT_lock_set(&GDKhashLock(b->batCacheid));
+ ACCELDEBUG t = GDKusec() - t;
+ /* if still 1 now that we have the lock, we can update */
+ if (b->thash == (Hash *) 1) {
+ Hash *h;
+ int fd;
- b->thash = NULL;
- if ((h = GDKzalloc(sizeof(*h))) != NULL &&
- (h->heap.farmid = BBPselectfarm(b->batRole, b->ttype,
hashheap)) >= 0) {
- stpconcat(h->heap.filename, nme, ".thash", NULL);
+ b->thash = NULL;
+ if ((h = GDKzalloc(sizeof(*h))) != NULL &&
+ (h->heap.farmid = BBPselectfarm(b->batRole,
b->ttype, hashheap)) >= 0) {
+ const char *nme = BBP_physical(b->batCacheid);
+ stpconcat(h->heap.filename, nme, ".thash",
NULL);
- /* check whether a persisted hash can be found */
- if ((fd = GDKfdlocate(h->heap.farmid, nme, "rb+",
"thash")) >= 0) {
- size_t hdata[HASH_HEADER_SIZE];
- struct stat st;
+ /* check whether a persisted hash can be found
*/
+ if ((fd = GDKfdlocate(h->heap.farmid, nme,
"rb+", "thash")) >= 0) {
+ size_t hdata[HASH_HEADER_SIZE];
+ struct stat st;
- if (read(fd, hdata, sizeof(hdata)) ==
sizeof(hdata) &&
- hdata[0] == (
+ if (read(fd, hdata, sizeof(hdata)) ==
sizeof(hdata) &&
+ hdata[0] == (
#ifdef PERSISTENTHASH
- ((size_t) 1 << 24) |
+ ((size_t) 1 << 24) |
#endif
- HASH_VERSION) &&
- hdata[4] == (size_t) BATcount(b) &&
- fstat(fd, &st) == 0 &&
- st.st_size >= (off_t) (h->heap.size =
h->heap.free = (hdata[1] + hdata[2]) * hdata[3] + HASH_HEADER_SIZE *
SIZEOF_SIZE_T) &&
- HEAPload(&h->heap, nme, "thash", false) ==
GDK_SUCCEED) {
- h->lim = (BUN) hdata[1];
- h->type = ATOMtype(b->ttype);
- h->mask = (BUN) (hdata[2] - 1);
- h->width = (int) hdata[3];
- switch (h->width) {
- case BUN2:
- h->nil = (BUN) BUN2_NONE;
- break;
- case BUN4:
- h->nil = (BUN) BUN4_NONE;
- break;
+ HASH_VERSION) &&
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list