* 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:
@@ -21,7 +21,7 @@
|
|||||||
#include <Region.h>
|
#include <Region.h>
|
||||||
|
|
||||||
#include "link_message.h"
|
#include "link_message.h"
|
||||||
|
#include "syscalls.h"
|
||||||
|
|
||||||
//#define DEBUG_BPORTLINK
|
//#define DEBUG_BPORTLINK
|
||||||
#ifdef DEBUG_BPORTLINK
|
#ifdef DEBUG_BPORTLINK
|
||||||
@@ -245,9 +245,11 @@ LinkReceiver::ReadFromPort(bigtime_t timeout)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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));
|
// STRACE(("info: LinkReceiver Read()ing %ld bytes...\n", size));
|
||||||
|
ssize_t size = passedSize;
|
||||||
|
|
||||||
if (fReadError < B_OK)
|
if (fReadError < B_OK)
|
||||||
return fReadError;
|
return fReadError;
|
||||||
|
|
||||||
@@ -259,13 +261,49 @@ LinkReceiver::Read(void *data, ssize_t size)
|
|||||||
if (fDataSize == 0 || fReplySize == 0)
|
if (fDataSize == 0 || fReplySize == 0)
|
||||||
return B_NO_INIT; // need to call GetNextReply() first
|
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) {
|
if (fRecvPosition + size > fRecvStart + fReplySize) {
|
||||||
// reading past the end of current message
|
// reading past the end of current message
|
||||||
fReadError = B_BAD_VALUE;
|
fReadError = B_BAD_VALUE;
|
||||||
return 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;
|
fRecvPosition += size;
|
||||||
return fReadError;
|
return fReadError;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,8 +129,11 @@ LinkSender::CancelMessage()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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)
|
if (fCurrentStatus < B_OK)
|
||||||
return fCurrentStatus;
|
return fCurrentStatus;
|
||||||
|
|
||||||
@@ -140,6 +143,12 @@ LinkSender::Attach(const void *data, size_t size)
|
|||||||
if (fCurrentEnd == fCurrentStart)
|
if (fCurrentEnd == fCurrentStart)
|
||||||
return B_NO_INIT; // need to call StartMessage() first
|
return B_NO_INIT; // need to call StartMessage() first
|
||||||
|
|
||||||
|
bool useArea = false;
|
||||||
|
if (size >= kMaxBufferSize) {
|
||||||
|
useArea = true;
|
||||||
|
size = sizeof(area_id);
|
||||||
|
}
|
||||||
|
|
||||||
if (SpaceLeft() < size) {
|
if (SpaceLeft() < size) {
|
||||||
// we have to make space for the data
|
// we have to make space for the data
|
||||||
|
|
||||||
@@ -148,6 +157,20 @@ LinkSender::Attach(const void *data, size_t size)
|
|||||||
return fCurrentStatus = status;
|
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);
|
memcpy(fBuffer + fCurrentEnd, data, size);
|
||||||
fCurrentEnd += size;
|
fCurrentEnd += size;
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <Shape.h>
|
#include <Shape.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
@@ -976,37 +977,27 @@ ServerPicture::DataLength() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define BUFFER_SIZE 4096
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ServerPicture::ImportData(BPrivate::LinkReceiver &link)
|
ServerPicture::ImportData(BPrivate::LinkReceiver &link)
|
||||||
{
|
{
|
||||||
int32 size = 0;
|
int32 size = 0;
|
||||||
link.Read<int32>(&size);
|
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();
|
off_t oldPosition = fData->Position();
|
||||||
fData->Seek(0, SEEK_SET);
|
fData->Seek(0, SEEK_SET);
|
||||||
|
|
||||||
// TODO: Oh yeah... 65kb on the stack...
|
status_t status = B_NO_MEMORY;
|
||||||
char buffer[size];
|
char* buffer = new(std::nothrow) char[size];
|
||||||
status_t read = link.Read(buffer, size);
|
if (buffer) {
|
||||||
if (read < B_OK)
|
status = B_OK;
|
||||||
return (status_t)read;
|
ssize_t read = link.Read(buffer, size);
|
||||||
|
if (read < B_OK || fData->Write(buffer, size) < B_OK)
|
||||||
fData->Write(buffer, size);
|
status = B_ERROR;
|
||||||
|
delete [] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
fData->Seek(oldPosition, SEEK_SET);
|
fData->Seek(oldPosition, SEEK_SET);
|
||||||
|
return status;
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1032,27 +1023,24 @@ ServerPicture::ExportData(BPrivate::PortLink &link)
|
|||||||
off_t size = 0;
|
off_t size = 0;
|
||||||
fData->GetSize(&size);
|
fData->GetSize(&size);
|
||||||
link.Attach<int32>((int32)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.CancelMessage();
|
||||||
link.StartMessage(B_ERROR);
|
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);
|
fData->Seek(oldPosition, SEEK_SET);
|
||||||
|
return status;
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user