* first implementation of passing data via area to app_server
this makes printing of large images work, fixes task #1067 git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27214 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
953cb30447
commit
4e61552ecd
@ -21,7 +21,7 @@
|
||||
#include <Region.h>
|
||||
|
||||
#include "link_message.h"
|
||||
|
||||
#include "syscalls.h"
|
||||
|
||||
//#define DEBUG_BPORTLINK
|
||||
#ifdef DEBUG_BPORTLINK
|
||||
@ -245,9 +245,11 @@ LinkReceiver::ReadFromPort(bigtime_t timeout)
|
||||
|
||||
|
||||
status_t
|
||||
LinkReceiver::Read(void *data, ssize_t size)
|
||||
LinkReceiver::Read(void *data, ssize_t passedSize)
|
||||
{
|
||||
// STRACE(("info: LinkReceiver Read()ing %ld bytes...\n", size));
|
||||
ssize_t size = passedSize;
|
||||
|
||||
if (fReadError < B_OK)
|
||||
return fReadError;
|
||||
|
||||
@ -259,13 +261,49 @@ LinkReceiver::Read(void *data, ssize_t size)
|
||||
if (fDataSize == 0 || fReplySize == 0)
|
||||
return B_NO_INIT; // need to call GetNextReply() first
|
||||
|
||||
bool useArea = false;
|
||||
if ((size_t)size >= kMaxBufferSize) {
|
||||
useArea = true;
|
||||
size = sizeof(area_id);
|
||||
}
|
||||
|
||||
if (fRecvPosition + size > fRecvStart + fReplySize) {
|
||||
// reading past the end of current message
|
||||
fReadError = B_BAD_VALUE;
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
memcpy(data, fRecvBuffer + fRecvPosition, size);
|
||||
if (useArea) {
|
||||
area_id sourceArea;
|
||||
memcpy((void*)&sourceArea, fRecvBuffer + fRecvPosition, size);
|
||||
|
||||
area_info areaInfo;
|
||||
if (get_area_info(sourceArea, &areaInfo) < B_OK)
|
||||
fReadError = B_BAD_VALUE;
|
||||
|
||||
if (fReadError >= B_OK) {
|
||||
thread_info threadInfo;
|
||||
get_thread_info(find_thread(NULL), &threadInfo);
|
||||
|
||||
void* areaAddress = NULL;
|
||||
if (areaInfo.team != threadInfo.team) {
|
||||
sourceArea = _kern_transfer_area(sourceArea, &areaAddress,
|
||||
B_ANY_ADDRESS, threadInfo.team);
|
||||
|
||||
if (sourceArea < B_OK)
|
||||
fReadError = sourceArea;
|
||||
} else {
|
||||
areaAddress = areaInfo.address;
|
||||
}
|
||||
|
||||
if (areaAddress && sourceArea >= B_OK) {
|
||||
memcpy(data, areaAddress, passedSize);
|
||||
delete_area(sourceArea);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memcpy(data, fRecvBuffer + fRecvPosition, size);
|
||||
}
|
||||
fRecvPosition += size;
|
||||
return fReadError;
|
||||
}
|
||||
|
@ -129,8 +129,11 @@ LinkSender::CancelMessage()
|
||||
|
||||
|
||||
status_t
|
||||
LinkSender::Attach(const void *data, size_t size)
|
||||
LinkSender::Attach(const void *passedData, size_t passedSize)
|
||||
{
|
||||
size_t size = passedSize;
|
||||
const void* data = passedData;
|
||||
|
||||
if (fCurrentStatus < B_OK)
|
||||
return fCurrentStatus;
|
||||
|
||||
@ -140,6 +143,12 @@ LinkSender::Attach(const void *data, size_t size)
|
||||
if (fCurrentEnd == fCurrentStart)
|
||||
return B_NO_INIT; // need to call StartMessage() first
|
||||
|
||||
bool useArea = false;
|
||||
if (size >= kMaxBufferSize) {
|
||||
useArea = true;
|
||||
size = sizeof(area_id);
|
||||
}
|
||||
|
||||
if (SpaceLeft() < size) {
|
||||
// we have to make space for the data
|
||||
|
||||
@ -148,6 +157,20 @@ LinkSender::Attach(const void *data, size_t size)
|
||||
return fCurrentStatus = status;
|
||||
}
|
||||
|
||||
area_id senderArea = -1;
|
||||
if (useArea) {
|
||||
void* address = NULL;
|
||||
off_t alignedSize = (passedSize + B_PAGE_SIZE) & ~(B_PAGE_SIZE - 1);
|
||||
senderArea = create_area("LinkSenderArea", &address, B_ANY_ADDRESS,
|
||||
alignedSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
|
||||
if (senderArea < B_OK)
|
||||
return senderArea;
|
||||
|
||||
data = &senderArea;
|
||||
memcpy(address, passedData, passedSize);
|
||||
}
|
||||
|
||||
memcpy(fBuffer + fCurrentEnd, data, size);
|
||||
fCurrentEnd += size;
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <List.h>
|
||||
#include <Shape.h>
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
#include <stack>
|
||||
|
||||
@ -976,37 +977,27 @@ ServerPicture::DataLength() const
|
||||
}
|
||||
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
|
||||
status_t
|
||||
ServerPicture::ImportData(BPrivate::LinkReceiver &link)
|
||||
{
|
||||
int32 size = 0;
|
||||
link.Read<int32>(&size);
|
||||
|
||||
if (size >= 65536) {
|
||||
//TODO: Pass via an area.
|
||||
// Ideally the Link** api would allow to write partial messages,
|
||||
// so that a big picture could be written in chunks of 4096 bytes
|
||||
// or so
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
off_t oldPosition = fData->Position();
|
||||
fData->Seek(0, SEEK_SET);
|
||||
|
||||
// TODO: Oh yeah... 65kb on the stack...
|
||||
char buffer[size];
|
||||
status_t read = link.Read(buffer, size);
|
||||
if (read < B_OK)
|
||||
return (status_t)read;
|
||||
|
||||
fData->Write(buffer, size);
|
||||
status_t status = B_NO_MEMORY;
|
||||
char* buffer = new(std::nothrow) char[size];
|
||||
if (buffer) {
|
||||
status = B_OK;
|
||||
ssize_t read = link.Read(buffer, size);
|
||||
if (read < B_OK || fData->Write(buffer, size) < B_OK)
|
||||
status = B_ERROR;
|
||||
delete [] buffer;
|
||||
}
|
||||
|
||||
fData->Seek(oldPosition, SEEK_SET);
|
||||
|
||||
return B_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -1032,27 +1023,24 @@ ServerPicture::ExportData(BPrivate::PortLink &link)
|
||||
off_t size = 0;
|
||||
fData->GetSize(&size);
|
||||
link.Attach<int32>((int32)size);
|
||||
if (size >= 65536) {
|
||||
//TODO: Pass via an area
|
||||
|
||||
status_t status = B_NO_MEMORY;
|
||||
char* buffer = new(std::nothrow) char[size];
|
||||
if (buffer) {
|
||||
status = B_OK;
|
||||
ssize_t read = fData->Read(buffer, size);
|
||||
if (read < B_OK || link.Attach(buffer, read) < B_OK)
|
||||
status = B_ERROR;
|
||||
delete [] buffer;
|
||||
}
|
||||
|
||||
if (status < B_OK) {
|
||||
link.CancelMessage();
|
||||
link.StartMessage(B_ERROR);
|
||||
return B_ERROR;
|
||||
}
|
||||
// TODO: Oh yeah... 65kb on the stack...
|
||||
char buffer[size];
|
||||
ssize_t read = fData->Read(buffer, size);
|
||||
if (read < B_OK)
|
||||
return (status_t)read;
|
||||
if (link.Attach(buffer, read) < B_OK) {
|
||||
//
|
||||
link.CancelMessage();
|
||||
link.StartMessage(B_ERROR);
|
||||
};
|
||||
|
||||
|
||||
fData->Seek(oldPosition, SEEK_SET);
|
||||
|
||||
return B_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user