Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 9 of 9 total
Thread Getting an out of memory error in a stored proc.
Mon, Nov 13 2006 1:10 PMPermanent Link

"Bern Rudisill"
Hello,

I have the following stored proc

procedure TMainForm.ServerEngineServerProcedure(Sender: TObject;
ServerSession:
 TDBISAMSession; const ProcedureName: string);
var
 sPathName, sFileName: string;
begin
 if (AnsiCompareText(ProcedureName, 'UploadFile') = 0) then
   begin
     with ServerSession do
       begin
         sPathName := RemoteParams.ParamByName('PathName').AsString; {
get server path }
         sFileName := RemoteParams.ParamByName('FileName').AsString; {
get file name }
         RemoteParams.ParamByName('ServerFile').SaveToFile(sPathName +
sFileName); { save file to server }
         RemoteParams.Clear;
         with RemoteParams.CreateParam(ftBoolean, 'Result') do
           AsBoolean := FileExists(sPathName + sFileName); { set
result }
       end;
   end
 else
   if (AnsiCompareText(ProcedureName, 'DownloadFile') = 0) then
     begin
       with ServerSession do
         begin
           sPathName := RemoteParams.ParamByName('PathName').AsString;
{ get server path }
           sFileName := RemoteParams.ParamByName('FileName').AsString;
{ get file name }
           RemoteParams.Clear;
           RemoteParams.CreateParam(ftBlob,
'File').LoadFromFile(sPathName + sFileName, ftBlob); { Load file to
send to client }
         with RemoteParams.CreateParam(ftBoolean, 'Result') do
           AsBoolean := FileExists(sPathName + sFileName); { set
result }
         end;
     end;
end;

When I call the 'UploadFile' proc it works perfectly, but when I call
the 'DownloadFile' proc I keep getting an out of memory error. Any Ideas

Here is the code I use to call each procedure from the client

function TForm1.UploadFileToServer(sFileName, sFrom, sTo: string):
Boolean;
begin
 Memo2.Lines.Insert(0, 'Start Uploading: ' + sFileName);
 with DBISAMSession1.RemoteParams do
   begin
     CreateParam(ftString, 'PathName').AsString := sTo; { set server
path }
     CreateParam(ftString, 'FileName').AsString := sFileName; { set
file name }
     Memo2.Lines.Insert(0, 'Start reading into stream');

     CreateParam(ftBlob, 'ServerFile').LoadFromFile(sFrom + sFileName,
ftBlob); { load local file }
     with DBISAMSession1 do
       begin
         try
           Memo2.Lines.Insert(0, 'sending');
           CallRemoteProcedure('UploadFile'); { call function }
           Result := RemoteParams.ParamByName('Result').AsBoolean; {
get result of copy }
         except
           Result := False; { did not work }
         end;
       end;
   end;
 Memo2.Lines.Insert(0, 'Done Uploading: ' + sFileName);
end;

function TForm1.DownLoadFromServer(sFileName, sFrom, sTo: string):
Boolean;
begin
 Memo2.Lines.Insert(0, 'Start Downloading: ' + sFileName);
 with DBISAMSession1.RemoteParams do
   begin
     CreateParam(ftString, 'PathName').AsString := sFrom; { set server
path }
     CreateParam(ftString, 'FileName').AsString := sFileName; { set
file name }
     //      CreateParam(ftBlob, 'ServerFile').LoadFromFile(sFrom +
sFileName, ftBlob); { load local file }

     with DBISAMSession1 do
       begin
         try
           CallRemoteProcedure('DownloadFile'); { call function }
           Result := true;
         except
           Result := False; { did not work }
         end;
       end;
   end;
 Memo2.Lines.Insert(0, 'Done Downloading: ' + sFileName);
end;

Thanks Bern
--
Mon, Nov 13 2006 4:56 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Bern,

<< When I call the 'UploadFile' proc it works perfectly, but when I call the
'DownloadFile' proc I keep getting an out of memory error. Any Ideas >>

How big is the file being transferred ?

Your server-side procedure and the calls look fine, so I don't think that
there's a coding issue.

--
Tim Young
Elevate Software
www.elevatesoft.com

Mon, Nov 13 2006 5:25 PMPermanent Link

"Bern Rudisill"
Tim Young [Elevate Software] wrote:

> Bern,
>
> << When I call the 'UploadFile' proc it works perfectly, but when I
> call the 'DownloadFile' proc I keep getting an out of memory error.
> Any Ideas >>
>
> How big is the file being transferred ?
>
> Your server-side procedure and the calls look fine, so I don't think
> that there's a coding issue.

About 200 megs. I am running the client and server on the same machine
for testing. I can transfer the 200 meg file from the client to the
server with no errors, but I get the error when trying to send the file
from the server to the client.

Bern

--
Tue, Nov 14 2006 9:01 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Bern,

<< About 200 megs. >>

That's your problem.  Your running out of virtual memory address space.

<< I am running the client and server on the same machine for testing. I can
transfer the 200 meg file from the client to the server with no errors, but
I get the error when trying to send the file from the server to the client.
>>

Are you performing one after the other ?  Or separately ?

--
Tim Young
Elevate Software
www.elevatesoft.com

Tue, Nov 14 2006 9:42 AMPermanent Link

"Bern Rudisill"
Tim Young [Elevate Software] wrote:

> Bern,
>
> << About 200 megs. >>
>
> That's your problem.  Your running out of virtual memory address
> space.
>
> << I am running the client and server on the same machine for
> testing. I can transfer the 200 meg file from the client to the
> server with no errors, but I get the error when trying to send the
> file from the server to the client.  >>
>
> Are you performing one after the other ?  Or separately ?


Is there a way to increase the virtual memory address? I don't
understand why the Server would act any different then the Client.

Here is my code that calls the stored procs.

In Client:

procedure TForm1.Button6Click(Sender: TObject);
var
 i: Integer;
 sFrom: string;
 sTo: string;
begin
 txtStart.text := 'Start: ' + timetostr(now);
 DBISAMSession1.RemoteHost := txtRemoteHost.text;
 DBISAMSession1.RemoteAddress := txtRemoteAddress.Text;

 sFrom :=  'C:\Documents and Settings\bernr\Desktop\Test\data\';
 sTo := 'D:\Projects\ExitCare6\ExitCare 6.4\Release\test\';

 for i := 0 to Memo1.lines.Count - 1 do
   begin
     DownLoadFromServer(memo1.lines.Strings[i] + '.blb', sFrom, sTo);
     DownLoadFromServer(memo1.lines.Strings[i] + '.idx', sFrom, sTo);
     DownLoadFromServer(memo1.lines.Strings[i] + '.dat', sFrom, sTo);
   end;
 txtEnd.text := 'Done: ' + timetostr(now);
 showmessage('Done');
end;

function TForm1.DownLoadFromServer(sFileName, sFrom, sTo: string):
Boolean;
begin
 Memo2.Lines.Insert(0, 'Start Downloading: ' + sFileName);
 with DBISAMSession1.RemoteParams do
   begin
     CreateParam(ftString, 'PathName').AsString := sFrom; { set server
path }
     CreateParam(ftString, 'FileName').AsString := sFileName; { set
file name }
     with DBISAMSession1 do
       begin
         try
           CallRemoteProcedure('DownloadFile'); { call function }
           if RemoteParams.ParamByName('Result').AsBoolean = true then
             RemoteParams.ParamByName('File').SaveToFile(sTo +
sFileName); { save file }
//
showmessage(booltostr(RemoteParams.ParamByName('Result').AsBoolean,
true));
           RemoteParams.Clear;
           Result := true;
         except
           Result := False; { did not work }
         end;
       end;
   end;
 Memo2.Lines.Insert(0, 'Done Downloading: ' + sFileName);
end;

Stored Proc in Server:

   if (AnsiCompareText(ProcedureName, 'DownloadFile') = 0) then
     begin
       with ServerSession do
         begin
           sPathName := RemoteParams.ParamByName('PathName').AsString;
{ get server path }
           sFileName := RemoteParams.ParamByName('FileName').AsString;
{ get file name }
           RemoteParams.Clear;
      if FileExists(sPathName + sFileName) then
           begin
           { If the file exists, use the TDBISAMParam
             LoadFromFile method to load the file
             data into the parameter }
           RemoteParams.CreateParam(ftblob,
'File').LoadFromFile(sPathName + sFileName, ftBlob);
           end
        else
           { If the file doesn't exist, just create a NULL
             parameter with the correct result name }
           RemoteParams.CreateParam(ftblob,'File');
           RemoteParams.CreateParam(ftBoolean, 'Result').AsBoolean:=
FileExists(sPathName + sFileName); { set result }
         end;
     end

Is there a better way to copy tables from the server to the local
machine? I thought about embedding an FTP server in the DBISAM server
to copy the files, but would rather do this as a last resort.

Bern




--
Wed, Nov 15 2006 3:56 PMPermanent Link

"Bern Rudisill"
Bern Rudisill wrote:

> Tim Young [Elevate Software] wrote:
>
> > Bern,
> >
> > << About 200 megs. >>
> >
> > That's your problem.  Your running out of virtual memory address
> > space.
> >
> > << I am running the client and server on the same machine for
> > testing. I can transfer the 200 meg file from the client to the
> > server with no errors, but I get the error when trying to send the
> > file from the server to the client.  >>
> >
> > Are you performing one after the other ?  Or separately ?
>
>
> Is there a way to increase the virtual memory address? I don't
> understand why the Server would act any different then the Client.
>
> Here is my code that calls the stored procs.
>
> In Client:
>
> procedure TForm1.Button6Click(Sender: TObject);
> var
>   i: Integer;
>   sFrom: string;
>   sTo: string;
> begin
>   txtStart.text := 'Start: ' + timetostr(now);
>   DBISAMSession1.RemoteHost := txtRemoteHost.text;
>   DBISAMSession1.RemoteAddress := txtRemoteAddress.Text;
>
>   sFrom :=  'C:\Documents and Settings\bernr\Desktop\Test\data\';
>   sTo := 'D:\Projects\ExitCare6\ExitCare 6.4\Release\test\';
>
>   for i := 0 to Memo1.lines.Count - 1 do
>     begin
>       DownLoadFromServer(memo1.lines.Strings[i] + '.blb', sFrom, sTo);
>       DownLoadFromServer(memo1.lines.Strings[i] + '.idx', sFrom, sTo);
>       DownLoadFromServer(memo1.lines.Strings[i] + '.dat', sFrom, sTo);
>     end;
>   txtEnd.text := 'Done: ' + timetostr(now);
>   showmessage('Done');
> end;
>
> function TForm1.DownLoadFromServer(sFileName, sFrom, sTo: string):
> Boolean;
> begin
>   Memo2.Lines.Insert(0, 'Start Downloading: ' + sFileName);
>   with DBISAMSession1.RemoteParams do
>     begin
>       CreateParam(ftString, 'PathName').AsString := sFrom; { set
> server path }
>       CreateParam(ftString, 'FileName').AsString := sFileName; { set
> file name }
>       with DBISAMSession1 do
>         begin
>           try
>             CallRemoteProcedure('DownloadFile'); { call function }
>             if RemoteParams.ParamByName('Result').AsBoolean = true
> then               RemoteParams.ParamByName('File').SaveToFile(sTo +
> sFileName); { save file }
> //
> showmessage(booltostr(RemoteParams.ParamByName('Result').AsBoolean,
> true));
>             RemoteParams.Clear;
>             Result := true;
>           except
>             Result := False; { did not work }
>           end;
>         end;
>     end;
>   Memo2.Lines.Insert(0, 'Done Downloading: ' + sFileName);
> end;
>
> Stored Proc in Server:
>
>     if (AnsiCompareText(ProcedureName, 'DownloadFile') = 0) then
>       begin
>         with ServerSession do
>           begin
>             sPathName :=
> RemoteParams.ParamByName('PathName').AsString; { get server path }
>             sFileName :=
> RemoteParams.ParamByName('FileName').AsString; { get file name }
>             RemoteParams.Clear;
>        if FileExists(sPathName + sFileName) then
>             begin
>             { If the file exists, use the TDBISAMParam
>               LoadFromFile method to load the file
>               data into the parameter }
>             RemoteParams.CreateParam(ftblob,
> 'File').LoadFromFile(sPathName + sFileName, ftBlob);
>             end
>          else
>             { If the file doesn't exist, just create a NULL
>               parameter with the correct result name }
>             RemoteParams.CreateParam(ftblob,'File');
>             RemoteParams.CreateParam(ftBoolean, 'Result').AsBoolean:=
> FileExists(sPathName + sFileName); { set result }
>           end;
>       end
>
> Is there a better way to copy tables from the server to the local
> machine? I thought about embedding an FTP server in the DBISAM server
> to copy the files, but would rather do this as a last resort.
>
> Bern



--

A Little more Info, I went stepping trough the dbisamsv code and found
the error is happening on line # 5890
Pack((RecordBuffer+Offset)^,(FLDCHG_DATA+DataSize)), which is weird
because it seems to of had no error when it called the pack procedure
on the actual blob. once it gets into the pack procedure the actual
like that is erroring out is line # 1287
ResizeSendBuffer(FPackPos+SizeOf(Integer)+BufferSize);
FPack = 193096762
Sizeof(Integer)=4
BufferSize=3

Total=193096769

I stopped tracing it there.





Wed, Nov 15 2006 4:18 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Bern,

<< A Little more Info, I went stepping trough the dbisamsv code and found
the error is happening on line # 5890
Pack((RecordBuffer+Offset)^,(FLDCHG_DATA+DataSize)), which is weird because
it seems to of had no error when it called the pack procedure on the actual
blob. once it gets into the pack procedure the actual like that is erroring
out is line # 1287 ResizeSendBuffer(FPackPos+SizeOf(Integer)+BufferSize);
FPack = 193096762 Sizeof(Integer)=4 BufferSize=3

Total=193096769

I stopped tracing it there. >>

It is trying to resize the comms buffer that is already 193 megs or so,
which means that close to 400 megs of contiguous address space will be
required out of the 2 Gigs of virtual address space.  There's a good chance
that there will never be that much contiguous address space available, hence
the out of memory error.   You probably need to start looking at an option
that doesn't involve buffering the entire 200 meg file during transmission.
The parameter streaming in DBISAM is only intended to be used with small
files (0-10 megs).

--
Tim Young
Elevate Software
www.elevatesoft.com

Wed, Nov 15 2006 6:20 PMPermanent Link

"Bern Rudisill"
Tim Young [Elevate Software] wrote:

> Bern,
>
> << A Little more Info, I went stepping trough the dbisamsv code and
> found the error is happening on line # 5890
> Pack((RecordBuffer+Offset)^,(FLDCHG_DATA+DataSize)), which is weird
> because it seems to of had no error when it called the pack procedure
> on the actual blob. once it gets into the pack procedure the actual
> like that is erroring out is line # 1287
> ResizeSendBuffer(FPackPos+SizeOf(Integer)+BufferSize); FPack =
> 193096762 Sizeof(Integer)=4 BufferSize=3
>
> Total=193096769
>
> I stopped tracing it there. >>
>
> It is trying to resize the comms buffer that is already 193 megs or
> so, which means that close to 400 megs of contiguous address space
> will be required out of the 2 Gigs of virtual address space.  There's
> a good chance that there will never be that much contiguous address
> space available, hence the out of memory error.   You probably need
> to start looking at an option that doesn't involve buffering the
> entire 200 meg file during transmission. The parameter streaming in
> DBISAM is only intended to be used with small files (0-10 megs).

I can understand that, but what I don't understand is why it works
sending a 200m filed to the server but not from the server. Remember
both the client and server are running on the same system.

Do you happen to have any suggestions on how to copy tables from the
server to the local system? We do this so that they always read from
the local system to limit network bandwith and for speed. I am thinking
about embedding an FTP or HTTP server with the DBISAM server for file
transfers.

Would ElevateDB handle this better?

--
Thu, Nov 16 2006 3:45 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Bern,

<< I can understand that, but what I don't understand is why it works
sending a 200m filed to the server but not from the server. Remember both
the client and server are running on the same system. >>

It doesn't matter - they're two different processes, hence they will have
two completely-separate virtual address spaces.

<< I am thinking about embedding an FTP or HTTP server with the DBISAM
server for file transfers. >>

That might be the best option for now.  Either that, or stream chunks of the
records from one table to the other instead of trying to transfer the whole
table like a file.  However, that will most likely take a bit longer.

<< Would ElevateDB handle this better? >>

Not at the moment, no.  However, we do have plans to add file-transfer
capabilities at some point.

--
Tim Young
Elevate Software
www.elevatesoft.com

Image