Mercurial > hg > truffle
annotate agent/src/os/win32/IOBuf.cpp @ 1631:56cc7e01da2f
Added tag hs19-b03 for changeset ad1977f08c4d
author | trims |
---|---|
date | Fri, 09 Jul 2010 00:31:01 -0700 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 #include <stdio.h> | |
26 | |
27 // This file is currently used for os/solaris/agent too. At some point in time | |
28 // the source will be reorganized to avoid these ifdefs. | |
29 | |
30 #ifdef __sun | |
31 #include <string.h> | |
32 #include <inttypes.h> | |
33 #include <sys/byteorder.h> | |
34 #endif | |
35 | |
36 #include "IOBuf.hpp" | |
37 | |
38 // Formats for printing pointers | |
39 #ifdef _LP64 | |
40 # define INTPTR_FORMAT "0x%016lx" | |
41 #else /* ! _LP64 */ | |
42 # define INTPTR_FORMAT "0x%08lx" | |
43 #endif /* _LP64 */ | |
44 | |
45 // Uncomment the #define below to get messages on stderr | |
46 // #define DEBUGGING | |
47 | |
48 IOBuf::IOBuf(int inLen, int outLen) { | |
49 inBuf = new Buffer(inLen); | |
50 outBuf = new Buffer(outLen); | |
51 fd = INVALID_SOCKET; | |
52 outHandle = NULL; | |
53 usingSocket = true; | |
54 reset(); | |
55 } | |
56 | |
57 IOBuf::~IOBuf() { | |
58 delete inBuf; | |
59 delete outBuf; | |
60 } | |
61 | |
62 void | |
63 IOBuf::setSocket(SOCKET sock) { | |
64 fd = sock; | |
65 usingSocket = true; | |
66 } | |
67 | |
68 // Reading/writing files is only needed and used on windows. | |
69 #ifdef WIN32 | |
70 void | |
71 IOBuf::setOutputFileHandle(HANDLE handle) { | |
72 outHandle = handle; | |
73 usingSocket = false; | |
74 } | |
75 #endif | |
76 | |
77 void | |
78 IOBuf::reset() { | |
79 gotDataLastTime = false; | |
80 state = TEXT_STATE; | |
81 binPos = 0; | |
82 binLength = 0; | |
83 } | |
84 | |
85 IOBuf::ReadLineResult | |
86 IOBuf::tryReadLine() { | |
87 return doReadLine(false); | |
88 } | |
89 | |
90 char* | |
91 IOBuf::readLine() { | |
92 ReadLineResult rr = doReadLine(true); | |
93 if (rr != RL_GOT_DATA) { | |
94 return NULL; | |
95 } | |
96 return getLine(); | |
97 } | |
98 | |
99 IOBuf::ReadLineResult | |
100 IOBuf::doReadLine(bool shouldWait) { | |
101 | |
102 if (!usingSocket) { | |
103 return IOBuf::RL_ERROR; | |
104 } | |
105 | |
106 if (gotDataLastTime) { | |
107 curLine.clear(); | |
108 } | |
109 | |
110 int c; | |
111 do { | |
112 c = readChar(shouldWait); | |
113 if (c >= 0) { | |
114 Action act = processChar((char) c); | |
115 if (act == GOT_LINE) { | |
116 curLine.push_back('\0'); | |
117 gotDataLastTime = true; | |
118 return IOBuf::RL_GOT_DATA; | |
119 } else if (act == SKIP_EOL_CHAR) { | |
120 // Do nothing | |
121 } else { | |
122 curLine.push_back((char) c); | |
123 } | |
124 } | |
125 } while (shouldWait || c >= 0); | |
126 | |
127 gotDataLastTime = false; | |
128 return IOBuf::RL_NO_DATA; | |
129 } | |
130 | |
131 bool | |
132 IOBuf::flushImpl(bool moreDataToCome) { | |
133 int numWritten = 0; | |
134 | |
135 #ifdef WIN32 | |
136 // When running on Windows and using IOBufs for inter-process | |
137 // communication, we need to write metadata into the stream | |
138 // indicating how many bytes are coming down. Five bytes are written | |
139 // per flush() call, four containing the integer number of bytes | |
140 // coming (not including the five-byte header) and one (a 0 or 1) | |
141 // indicating whether there is more data coming. | |
142 if (!usingSocket) { | |
143 int numToWrite = outBuf->drainRemaining(); | |
144 char moreToCome = (moreDataToCome ? 1 : 0); | |
145 DWORD numBytesWritten; | |
146 if (!WriteFile(outHandle, &numToWrite, sizeof(int), &numBytesWritten, NULL)) { | |
147 return false; | |
148 } | |
149 if (numBytesWritten != sizeof(int)) { | |
150 return false; | |
151 } | |
152 if (!WriteFile(outHandle, &moreToCome, 1, &numBytesWritten, NULL)) { | |
153 return false; | |
154 } | |
155 if (numBytesWritten != 1) { | |
156 return false; | |
157 } | |
158 } | |
159 #endif | |
160 | |
161 while (outBuf->drainRemaining() != 0) { | |
162 #ifdef DEBUGGING | |
163 fprintf(stderr, "Flushing %d bytes\n", outBuf->drainRemaining()); | |
164 #endif | |
165 if (usingSocket) { | |
166 numWritten = send(fd, outBuf->drainPos(), outBuf->drainRemaining(), 0); | |
167 } else { | |
168 #ifdef WIN32 | |
169 DWORD numBytesWritten; | |
170 if (!WriteFile(outHandle, outBuf->drainPos(), outBuf->drainRemaining(), &numBytesWritten, NULL)) { | |
171 numWritten = -1; | |
172 } else { | |
173 numWritten = numBytesWritten; | |
174 } | |
175 #endif | |
176 } | |
177 if (numWritten != -1) { | |
178 #ifdef DEBUGGING | |
179 fprintf(stderr, "Flushed %d bytes\n", numWritten); | |
180 #endif | |
181 outBuf->incrDrainPos(numWritten); | |
182 } else { | |
183 return false; | |
184 } | |
185 } | |
186 | |
187 outBuf->compact(); | |
188 | |
189 return true; | |
190 } | |
191 | |
192 int | |
193 IOBuf::readChar(bool block) { | |
194 do { | |
195 int c = inBuf->readByte(); | |
196 if (c >= 0) { | |
197 return c; | |
198 } | |
199 // See whether we need to compact the input buffer | |
200 if (inBuf->remaining() < inBuf->size() / 2) { | |
201 inBuf->compact(); | |
202 } | |
203 // See whether socket is ready | |
204 fd_set fds; | |
205 FD_ZERO(&fds); | |
206 FD_SET(fd, &fds); | |
207 struct timeval timeout; | |
208 timeout.tv_sec = 0; | |
209 timeout.tv_usec = 0; | |
210 if (block || select(1 + fd, &fds, NULL, NULL, &timeout) > 0) { | |
211 if (block || FD_ISSET(fd, &fds)) { | |
212 #ifdef DEBUGGING | |
213 int b = (block ? 1 : 0); | |
214 fprintf(stderr, "calling recv: block = %d\n", b); | |
215 #endif | |
216 // Read data from socket | |
217 int numRead = recv(fd, inBuf->fillPos(), inBuf->remaining(), 0); | |
218 if (numRead < 0) { | |
219 #ifdef DEBUGGING | |
220 fprintf(stderr, "recv failed\n"); | |
221 #endif | |
222 return -1; | |
223 } | |
224 inBuf->incrFillPos(numRead); | |
225 } | |
226 } | |
227 } while (block); | |
228 | |
229 return inBuf->readByte(); | |
230 } | |
231 | |
232 char* | |
233 IOBuf::getLine() { | |
234 #ifdef DEBUGGING | |
235 fprintf(stderr, "Returning (first 10 chars) \"%.10s\"\n", curLine.begin()); | |
236 #endif | |
237 return curLine.begin(); | |
238 } | |
239 | |
240 bool | |
241 IOBuf::flush() { | |
242 return flushImpl(false); | |
243 } | |
244 | |
245 bool | |
246 IOBuf::writeString(const char* str) { | |
247 int len = strlen(str); | |
248 | |
249 if (len > outBuf->size()) { | |
250 return false; | |
251 } | |
252 | |
253 if (len > outBuf->remaining()) { | |
254 if (!flushImpl(true)) { | |
255 return false; | |
256 } | |
257 } | |
258 | |
259 // NOTE we do not copy the null terminator of the string. | |
260 | |
261 strncpy(outBuf->fillPos(), str, len); | |
262 outBuf->incrFillPos(len); | |
263 return true; | |
264 } | |
265 | |
266 bool | |
267 IOBuf::writeInt(int val) { | |
268 char buf[128]; | |
269 sprintf(buf, "%d", val); | |
270 return writeString(buf); | |
271 } | |
272 | |
273 bool | |
274 IOBuf::writeUnsignedInt(unsigned int val) { | |
275 char buf[128]; | |
276 sprintf(buf, "%u", val); | |
277 return writeString(buf); | |
278 } | |
279 | |
280 bool | |
281 IOBuf::writeBoolAsInt(bool val) { | |
282 if (val) { | |
283 return writeString("1"); | |
284 } else { | |
285 return writeString("0"); | |
286 } | |
287 } | |
288 | |
289 bool | |
290 IOBuf::writeAddress(void* val) { | |
291 char buf[128]; | |
292 sprintf(buf, INTPTR_FORMAT, val); | |
293 return writeString(buf); | |
294 } | |
295 | |
296 bool | |
297 IOBuf::writeSpace() { | |
298 return writeString(" "); | |
299 } | |
300 | |
301 bool | |
302 IOBuf::writeEOL() { | |
303 return writeString("\n\r"); | |
304 } | |
305 | |
306 bool | |
307 IOBuf::writeBinChar(char c) { | |
308 return writeBinBuf((char*) &c, sizeof(c)); | |
309 } | |
310 | |
311 bool | |
312 IOBuf::writeBinUnsignedShort(unsigned short i) { | |
313 i = htons(i); | |
314 return writeBinBuf((char*) &i, sizeof(i)); | |
315 } | |
316 | |
317 bool | |
318 IOBuf::writeBinUnsignedInt(unsigned int i) { | |
319 i = htonl(i); | |
320 return writeBinBuf((char*) &i, sizeof(i)); | |
321 } | |
322 | |
323 bool | |
324 IOBuf::writeBinBuf(char* buf, int size) { | |
325 while (size > 0) { | |
326 int spaceRemaining = outBuf->remaining(); | |
327 if (spaceRemaining == 0) { | |
328 if (!flushImpl(true)) { | |
329 return false; | |
330 } | |
331 spaceRemaining = outBuf->remaining(); | |
332 } | |
333 int toCopy = (size > spaceRemaining) ? spaceRemaining : size; | |
334 memcpy(outBuf->fillPos(), buf, toCopy); | |
335 outBuf->incrFillPos(toCopy); | |
336 buf += toCopy; | |
337 size -= toCopy; | |
338 if (size > 0) { | |
339 if (!flushImpl(true)) { | |
340 return false; | |
341 } | |
342 } | |
343 } | |
344 return true; | |
345 } | |
346 | |
347 #ifdef WIN32 | |
348 IOBuf::FillState | |
349 IOBuf::fillFromFileHandle(HANDLE fh, DWORD* numBytesRead) { | |
350 int totalToRead; | |
351 char moreToCome; | |
352 | |
353 outBuf->compact(); | |
354 | |
355 DWORD numRead; | |
356 if (!ReadFile(fh, &totalToRead, sizeof(int), &numRead, NULL)) { | |
357 return FAILED; | |
358 } | |
359 if (numRead != sizeof(int)) { | |
360 return FAILED; | |
361 } | |
362 if (!ReadFile(fh, &moreToCome, 1, &numRead, NULL)) { | |
363 return FAILED; | |
364 } | |
365 if (numRead != 1) { | |
366 return FAILED; | |
367 } | |
368 if (outBuf->remaining() < totalToRead) { | |
369 return FAILED; | |
370 } | |
371 | |
372 int tmp = totalToRead; | |
373 | |
374 while (totalToRead > 0) { | |
375 if (!ReadFile(fh, outBuf->fillPos(), totalToRead, &numRead, NULL)) { | |
376 return FAILED; | |
377 } | |
378 outBuf->incrFillPos((int) numRead); | |
379 totalToRead -= numRead; | |
380 } | |
381 | |
382 *numBytesRead = tmp; | |
383 return ((moreToCome == 0) ? DONE : MORE_DATA_PENDING); | |
384 } | |
385 #endif | |
386 | |
387 bool | |
388 IOBuf::isBinEscapeChar(char c) { | |
389 return (c == '|'); | |
390 } | |
391 | |
392 IOBuf::Action | |
393 IOBuf::processChar(char c) { | |
394 Action action = NO_ACTION; | |
395 switch (state) { | |
396 case TEXT_STATE: { | |
397 // Looking for text char, bin escape char, or EOL | |
398 if (isBinEscapeChar(c)) { | |
399 #ifdef DEBUGGING | |
400 fprintf(stderr, "[a: '%c'] ", inBuf[0]); | |
401 #endif | |
402 binPos = 0; | |
403 #ifdef DEBUGGING | |
404 fprintf(stderr, "[b: '%c'] ", inBuf[0]); | |
405 #endif | |
406 binLength = 0; | |
407 #ifdef DEBUGGING | |
408 fprintf(stderr, "[c: '%c'] ", inBuf[0]); | |
409 #endif | |
410 state = BIN_STATE; | |
411 #ifdef DEBUGGING | |
412 fprintf(stderr, "[d: '%c'] ", inBuf[0]); | |
413 #endif | |
414 #ifdef DEBUGGING | |
415 fprintf(stderr, "\nSwitching to BIN_STATE\n"); | |
416 #endif | |
417 } else if (isEOL(c)) { | |
418 state = EOL_STATE; | |
419 action = GOT_LINE; | |
420 #ifdef DEBUGGING | |
421 fprintf(stderr, "\nSwitching to EOL_STATE (GOT_LINE)\n"); | |
422 #endif | |
423 } | |
424 #ifdef DEBUGGING | |
425 else { | |
426 fprintf(stderr, "'%c' ", c); | |
427 fflush(stderr); | |
428 } | |
429 #endif | |
430 break; | |
431 } | |
432 | |
433 case BIN_STATE: { | |
434 // Seeking to finish read of input | |
435 if (binPos < 4) { | |
436 int cur = c & 0xFF; | |
437 binLength <<= 8; | |
438 binLength |= cur; | |
439 ++binPos; | |
440 } else { | |
441 #ifdef DEBUGGING | |
442 fprintf(stderr, "Reading binary byte %d of %d\n", | |
443 binPos - 4, binLength); | |
444 #endif | |
445 ++binPos; | |
446 if (binPos == 4 + binLength) { | |
447 state = TEXT_STATE; | |
448 #ifdef DEBUGGING | |
449 fprintf(stderr, "Switching to TEXT_STATE\n"); | |
450 #endif | |
451 } | |
452 } | |
453 break; | |
454 } | |
455 | |
456 case EOL_STATE: { | |
457 // More EOL characters just cause us to re-enter this state | |
458 if (isEOL(c)) { | |
459 action = SKIP_EOL_CHAR; | |
460 } else if (isBinEscapeChar(c)) { | |
461 binPos = 0; | |
462 binLength = 0; | |
463 state = BIN_STATE; | |
464 } else { | |
465 state = TEXT_STATE; | |
466 #ifdef DEBUGGING | |
467 fprintf(stderr, "'%c' ", c); | |
468 fflush(stderr); | |
469 #endif | |
470 } | |
471 break; | |
472 } | |
473 | |
474 } // switch | |
475 | |
476 return action; | |
477 } | |
478 | |
479 | |
480 bool | |
481 IOBuf::isEOL(char c) { | |
482 #ifdef WIN32 | |
483 return ((c == '\n') || (c == '\r')); | |
484 #elif defined(__sun) | |
485 return c == '\n'; | |
486 #else | |
487 #error Please port isEOL() to your platform | |
488 return false; | |
489 #endif | |
490 } |