LocalMacroSpaceManager.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.ibm.com/developerworks/oss/CPLv1.0.htm */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 
40 #include "LocalAPIManager.hpp"
41 #include "SysLibrary.hpp"
42 #include "ClientMessage.hpp"
43 #include "SysFile.hpp"
44 #include "rexx.h"
45 #include <stdio.h>
46 
47 
48 /**
49  * Destructor to force the macro space file to close.
50  */
52 {
53  // we're being terminated with the file still open...delete, and
54  // erase the file we have so far.
55  if (fileInst != NULL)
56  {
57 
58  fileInst->close();
59  // if we were trying to create this file, erase the
60  // partially created one.
61  if (creating)
62  {
63  remove(fileName);
64  }
65  }
66 }
67 
68 /**
69  * Explicitly close the macro space file.
70  */
72 {
73  fileInst->close();
74  delete fileInst;
75  fileInst = NULL;
76 }
77 
78 
79 /**
80  * Open a macrospace file for loading.
81  *
82  * @return The count of macros in the file.
83  */
85 {
86  MacroSpaceFileHeader header;
87  bool opened;
88 
89  // open the file
90  fileInst = new SysFile();
92  if (opened == false)
93  {
94  throw new ServiceException(FILE_CREATION_ERROR, "Unable to open macrospace file");
95  }
96  creating = false; // we're just reading this
97  read(&header, sizeof(header)); // read the header information
98 
99  if (memcmp(header.version, RXVERSION, RXVERSIZE) != 0)
100  {
101  throw new ServiceException(MACROSPACE_VERSION_ERROR, "Incompatible macro space version");
102  }
103 
104  if (header.magicNumber != SIGNATURE)
105  {
106  throw new ServiceException(MACROSPACE_SIGNATURE_ERROR, "Incompatible macro space signature");
107  }
108  descriptorBase = sizeof(header); // now mark the position of the descriptors
109  // and the calculated start position of the
110  // image data.
111  imageBase = sizeof(MacroSpaceDescriptor) * header.count;
112 
113  return header.count; // we have a size, return it.
114 }
115 
116 
117 /**
118  * Retrieve the next macro from the macrospace file.
119  *
120  * @param name The returned macro name.
121  * @param image The macro image information.
122  * @param order The macro ordering information.
123  */
124 void MacroSpaceFile::nextMacro(char *name, ManagedRxstring &image, size_t &order)
125 {
129 
130  read(&desc, sizeof(desc));
131  strcpy(name, desc.name);
132  order = desc.position;
134  imageBase += desc.imageSize;
135  read(image, desc.imageSize);
136 }
137 
138 
139 /**
140  * Step to the next macro, reading the information if it
141  * is in the target list.
142  *
143  * @param names The table of names.
144  * @param name The returned name, if read.
145  * @param image The macro image (if read).
146  * @param order The macro order information.
147  */
148 void MacroSpaceFile::nextMacro(NameTable names, char *name, ManagedRxstring &image, size_t &order)
149 {
153 
154  read(&desc, sizeof(desc));
155 
156  // we only read the image data in if this is in the requested list
157  if (names.inTable(desc.name))
158  {
159  strcpy(name, desc.name);
160  order = desc.position;
162  imageBase += desc.imageSize;
163  read(image, desc.imageSize);
164  }
165  else
166  {
167  // even though not reading this, we need to update the read position
168  imageBase += desc.imageSize;
169 
170  }
171 }
172 
173 
174 /**
175  * Explicitly set the file postion.
176  *
177  * @param p The new file position.
178  */
180 {
181  int64_t position;
182  if (fileInst->seek(p, SEEK_SET, position) == false)
183  {
184  throw new ServiceException(FILE_READ_ERROR, "Error reading from macrospace file");
185  }
186 }
187 
188 
189 /**
190  * Create a macro space file with an initial header table
191  * for the indicated number of macros.
192  *
193  * @param count The number of macros to store in the file.
194  */
195 void MacroSpaceFile::create(size_t count)
196 {
197  bool opened;
198  // create the file
199  fileInst = new SysFile;
201 
202  if (opened == false)
203  {
204  throw new ServiceException(FILE_CREATION_ERROR, "Unable to create macrospace file");
205  }
206  creating = true;
207 
208  MacroSpaceFileHeader header(count);
209  write(&header, sizeof(header));
210 }
211 
212 /**
213  * Write a macro descriptor out to the file.
214  *
215  * @param name The name of the macro to write.
216  * @param size The size of the macro being written.
217  * @param order The macro order information.
218  */
219 void MacroSpaceFile::writeMacroDescriptor(const char *name, size_t size, size_t order)
220 {
221  MacroSpaceDescriptor desc(name, size, order);
222 
223  write(&desc, sizeof(desc));
224 }
225 
226 
227 /**
228  * Write a buffer of data to the macro file.
229  *
230  * @param data The data buffer pointer.
231  * @param length The length to write.
232  */
233 void MacroSpaceFile::write(const void *data, size_t length)
234 {
235  size_t bytesWritten;
236  fileInst->write((const char *)data, length, bytesWritten);
237  if (bytesWritten != (size_t)length)
238  {
239  throw new ServiceException(FILE_WRITE_ERROR, "Error writing to macrospace file");
240  }
241 }
242 
243 
244 /**
245  * Read a buffer of data from the macrospace file.
246  *
247  * @param data The target data buffer.
248  * @param length The size to read.
249  */
250 void MacroSpaceFile::read(void *data, size_t length)
251 {
252  size_t bytesRead;
253  fileInst->read((char *)data, length, bytesRead);
254  if (bytesRead != (size_t)length)
255  {
256  throw new ServiceException(FILE_READ_ERROR, "Error reading from macrospace file");
257  }
258 }
259 
260 
261 /**
262  * Read a buffer of data into a managed RXSTRING structure.
263  *
264  * @param data The target RXSTRING
265  * @param length The length to read.
266  */
267 void MacroSpaceFile::read(ManagedRxstring &data, size_t length)
268 {
269  data.ensureCapacity(length);
270  read(data.strptr, length);
271  data.strlength = length;
272 }
273 
274 
276 {
277  // no state in this
278 }
279 
280 
281 /**
282  * Load a macrospace file into our space.
283  *
284  * @param target The target file name.
285  */
287 {
288  // now open and read the file header
289  MacroSpaceFile file(target);
290  // validate the file
291  size_t count = file.openForLoading();
292 
293  ManagedRxstring image; // this is outside the loop, which gives us the chance to reuse the buffer
294 
295  for (size_t i = 0; i < count; i++)
296  {
297  char macroName[MacroSpaceDescriptor::MACRONAMESIZE];
298  size_t order;
299 
300  file.nextMacro(macroName, image, order);
301 
302  ClientMessage message(MacroSpaceManager, ADD_MACRO, macroName);
303  message.parameter1 = image.strlength;
304  message.parameter2 = order;
305  // attach the queue item to the message.
306  message.setMessageData(image.strptr, image.strlength);
307 
308  // request the next one.
309  message.send();
310  // NB: The only error that can occur here is a critical exception. We don't
311  // need to check the return
312  }
313  file.close();
314  return RXMACRO_OK;
315 }
316 
317 
318 /**
319  * Load a macrospace file, using just the subset of names
320  * in the file.
321  *
322  * @param target The target macrospace file.
323  * @param nameList The list of names to load.
324  * @param nameCount The number of items to load.
325  */
326 RexxReturnCode LocalMacroSpaceManager::loadMacroSpace(const char *target, const char **nameList, size_t nameCount)
327 {
328  NameTable names(nameList, nameCount);
329 
330  // now open and read the file header
331  MacroSpaceFile file(target);
332  // validate the file
333  size_t count = file.openForLoading();
334 
335  ManagedRxstring image; // this is outside the loop, which gives us the chance to reuse the buffer
336 
337  for (size_t i = 0; i < count; i++)
338  {
339  char macroName[MacroSpaceDescriptor::MACRONAMESIZE];
340  size_t order;
341 
342  file.nextMacro(names, macroName, image, order);
343 
344  ClientMessage message(MacroSpaceManager, ADD_MACRO, macroName);
345  message.parameter1 = image.strlength;
346  message.parameter2 = order;
347 
348  // attach the queue item to the message.
349  message.setMessageData(image.strptr, image.strlength);
350 
351  // request the next one.
352  message.send();
353  // NB: The only error that can occur here is a critical exception. We don't
354  // need to check the return
355  }
356  file.close();
357  return RXMACRO_OK;
358 }
359 
360 
361 /**
362  * Save the currently loaded macros into a file.
363  *
364  * @param target The target file name.
365  */
367 {
369 
370  message.send();
371 
372  // we're empty, no point in this.
373  if (message.parameter1 == 0)
374  {
375  return RXMACRO_OK;
376  }
377 
378  // now open and write the file header
379  MacroSpaceFile file(target);
380  file.create(message.parameter1);
382 
383  for (;;)
384  {
385  // request the next one.
386  message.send();
387  if (message.result == NO_MORE_MACROS)
388  {
389  break;
390  }
391  file.writeMacroDescriptor(message.nameArg, message.parameter1, message.parameter2);
392  }
393  // now iterate the images
394  message.operation = ITERATE_MACROS;
395  message.send();
396 
397  message.operation = NEXT_MACRO_IMAGE;
398  for (;;)
399  {
400  // request the next one.
401  message.send();
402  if (message.result == NO_MORE_MACROS)
403  {
404  break;
405  }
406  file.write(message.getMessageData(), message.getMessageDataLength());
407  // explicitly free this since we're going to be reusing the message
408  // instance.
409  message.freeMessageData();
410  }
411  // all done!
412  file.close();
413  return RXMACRO_OK;
414 }
415 
416 
417 /**
418  * Retrieve a macro from the daemon server.
419  *
420  * @param target The target macro name.
421  * @param image The returned image data.
422  */
424 {
426 
427  // request, then receive the image data
428  message.send();
429  RexxReturnCode ret = mapReturnResult(message);
430  // if this worked, transfer the image data
431  if (ret == RXMACRO_OK)
432  {
433  message.transferMessageData(image);
434  }
435  return ret;
436 }
437 
438 /**
439  * Save the currently loaded macrospace using a subset of the
440  * loaded macros.
441  *
442  * @param target The file target.
443  * @param names The list of names.
444  * @param count The number of names in the list.
445  */
446 RexxReturnCode LocalMacroSpaceManager::saveMacroSpace(const char *target, const char **names, size_t count)
447 {
448  // now open and write the file header
449  MacroSpaceFile file(target);
450  file.create(count);
451  size_t i;
452 
454 
455  for (i = 0; i < count; i++)
456  {
457  strcpy(message.nameArg, names[i]);
458  // request the next one.
459  message.send();
460  // if not there, time to bail out
461  if (message.result == MACRO_DOES_NOT_EXIST)
462  {
463  return mapReturnResult(message);
464  }
465  file.writeMacroDescriptor(message.nameArg, message.parameter1, message.parameter2);
466  }
467  // now iterate the images
468  message.operation = GET_MACRO_IMAGE;
469 
470  for (i = 0; i < count; i++)
471  {
472  strcpy(message.nameArg, names[i]);
473  // request the next one. This will throw an exception if it doesn't exist.
474  message.send();
475  // if not there, time to bail out
476  if (message.result == MACRO_DOES_NOT_EXIST)
477  {
478  return mapReturnResult(message);
479  }
480  file.write(message.getMessageData(), message.getMessageDataLength());
481  // release the macro image data
482  message.freeMessageData();
483  }
484  // all done!
485  file.close();
486  return RXMACRO_OK;
487 }
488 
489 
490 /**
491  * Clear all macros from the macro space.
492  */
494 {
496  message.send();
497  return mapReturnResult(message);
498 }
499 
500 
501 /**
502  * Remove a macro from the macrospace.
503  *
504  * @param name The name of the macro to remove.
505  */
507 {
509  message.send();
510  return mapReturnResult(message);
511 }
512 
513 
514 /**
515  * Check the macro space for a give item, returning
516  * the order information.
517  *
518  * @param name The name to check.
519  * @param pos
520  */
522 {
524  message.send();
525  *pos = message.parameter1;
526  return mapReturnResult(message);
527 }
528 
529 
530 /**
531  * Change the search order for a macro item.
532  *
533  * @param name The name of the target macro.
534  * @param pos The new search order.
535  */
537 {
539  message.parameter1 = pos;
540  message.send();
541  return mapReturnResult(message);
542 }
543 
544 
545 /**
546  * Load a macro from a file and store into the macrospace.
547  *
548  * @param name The name of the macro.
549  * @param sourceFile The target source file.
550  * @param position The macro search position.
551  */
552 RexxReturnCode LocalMacroSpaceManager::addMacroFromFile(const char *name, const char *sourceFile, size_t position)
553 {
554  ManagedRxstring imageData;
555 
556  // translate the image
557  translateRexxProgram(sourceFile, imageData);
558  return addMacro(name, imageData, position);
559 }
560 
561 
562 /**
563  * Add a macro from image data into the macrospace.
564  *
565  * @param name The name of the macro.
566  * @param imageData The source image data
567  * @param position The search order position.
568  */
569 RexxReturnCode LocalMacroSpaceManager::addMacro(const char *name, ManagedRxstring &imageData, size_t position)
570 {
571  ClientMessage message(MacroSpaceManager, ADD_MACRO, name);
572  // attach the image data
573  message.setMessageData(imageData.strptr, imageData.strlength);
574  // set the additional arguments
575  message.parameter1 = imageData.strlength;
576  message.parameter2 = position; // make sure we have the add order
577 
578  message.send();
579  return mapReturnResult(message);
580 }
581 
582 
583 /**
584  * Translate a source file into a Rexx program.
585  *
586  * @param sourceFile The source file name.
587  * @param imageData The returned image data.
588  */
589 void LocalMacroSpaceManager::translateRexxProgram(const char *sourceFile, ManagedRxstring &imageData)
590 {
591  bool opened;
592 
593  SysFile *fileInst = new SysFile;
594  opened = fileInst->open(sourceFile, RX_O_RDONLY, 0, RX_SH_DENYWR);
595  if (opened == false)
596  {
597  throw new ServiceException(MACRO_SOURCE_NOT_FOUND, "Unable to open macrospace source file");
598  }
599 
600  int64_t fsize;
601  if (fileInst->getSize(fsize) == false)
602  {
603  throw new ServiceException(MACRO_SOURCE_READ_ERROR, "Unable to read macrospace source file");
604  }
605 
606  // we define imageData outside this block and sourceData inside. Once we've
607  // translated the file, we're finished with the source, so it can be released
608  // once we exit the block.
609  {
610  SysLibrary lib;
611  if (!lib.load("rexx"))
612  {
613  throw new ServiceException(MACRO_TRANSLATION_ERROR, "Unable to compile Rexx program");
614  }
615 
616  void *proc = lib.getProcedure("RexxTranslateInstoreProgram");
617  if (proc == NULL)
618  {
619  throw new ServiceException(MACRO_TRANSLATION_ERROR, "Unable to compile Rexx program");
620  }
621 
622  RexxReturnCode (RexxEntry *compiler)(const char *, CONSTRXSTRING *, RXSTRING *);
623 
624  compiler = (RexxReturnCode (RexxEntry *)(const char *, CONSTRXSTRING *, RXSTRING *))proc;
625 
626  ManagedRxstring sourceData;
627  readRxstringFromFile(fileInst, sourceData, (size_t)fsize);
628  fileInst->close();
629  imageData.strptr = NULL;
630  imageData.strlength = 0;
631 
632  RexxReturnCode rc = (*compiler)(sourceFile, (CONSTRXSTRING *)&sourceData, (RXSTRING *)&imageData);
633  if (rc != 0)
634  {
635  throw new ServiceException(MACRO_TRANSLATION_ERROR, "Unable to compile Rexx program");
636  }
637  }
638 }
639 
640 /**
641  * Read a buffer of data from a file and return in a
642  * ManagedRxString.
643  *
644  * @param fileInst The source file.
645  * @param target The rxstring used to return the file data.
646  * @param size The size to read.
647  */
649 {
650  size_t bytesRead;
651 
652  target.strlength = size;
653  if (size > 0) // if bytes to read */
654  {
655  target.ensureCapacity(size);
656 
657  fileInst->read(target.strptr, size, bytesRead);
658  if (bytesRead != size)
659  {
660  throw new ServiceException(MACROSPACE_FILE_READ_ERROR, "Unable to read macro space file");
661  }
662  }
663 }
664 
665 
666 /**
667  * Translate a service exception into the appropriate
668  * API return code.
669  *
670  * @param e The returned exception.
671  *
672  * @return The return code corresponding to the exception information.
673  */
675 {
676  switch (e->getErrorCode())
677  {
681 
683  case FILE_CREATION_ERROR:
685  case FILE_READ_ERROR:
686  case FILE_WRITE_ERROR:
687  return RXMACRO_FILE_ERROR;
688 
692 
694  return RXMACRO_NOT_FOUND;
695 
696  case MACRO_LOAD_REXX:
697  default:
698  return RXMACRO_NO_STORAGE;
699  }
700 }
701 
702 
703 /**
704  * Process an result returned from the server and
705  * map it into an API return code.
706  *
707  * @param m The return message.
708  *
709  * @return The mapped return code.
710  */
712 {
713  switch (m.result)
714  {
715  // this is generally the only error returned by the server
717  return RXMACRO_NOT_FOUND;
718  default:
719  return RXMACRO_OK;
720  }
721 }
#define RXVERSIZE
#define RXVERSION
#define SIGNATURE
@ FILE_READ_ERROR
@ MACROSPACE_FILE_READ_ERROR
@ MACROSPACE_SIGNATURE_ERROR
@ MACRO_SOURCE_READ_ERROR
@ FILE_WRITE_ERROR
@ MACRO_SOURCE_NOT_FOUND
@ MACRO_LOAD_REXX
@ MACRO_TRANSLATION_ERROR
@ FILE_CREATION_ERROR
@ MACROSPACE_VERSION_ERROR
@ MACRO_DOES_NOT_EXIST
@ NO_MORE_MACROS
@ CLEAR_MACRO_SPACE
@ QUERY_MACRO
@ NEXT_MACRO_DESCRIPTOR
@ GET_MACRO_DESCRIPTOR
@ GET_MACRO_IMAGE
@ REMOVE_MACRO
@ REORDER_MACRO
@ NEXT_MACRO_IMAGE
@ ADD_MACRO
@ ITERATE_MACRO_DESCRIPTORS
@ ITERATE_MACROS
@ MacroSpaceManager
RexxReturnCode addMacro(const char *name, ManagedRxstring &imageData, size_t position)
RexxReturnCode mapReturnResult(ServiceMessage &m)
RexxReturnCode removeMacro(const char *name)
void readRxstringFromFile(SysFile *file, ManagedRxstring &target, size_t size)
RexxReturnCode queryMacro(const char *target, size_t *pos)
RexxReturnCode loadMacroSpace(const char *target)
RexxReturnCode getMacro(const char *target, RXSTRING &image)
void translateRexxProgram(const char *sourcefile, ManagedRxstring &imageData)
virtual RexxReturnCode processServiceException(ServiceException *e)
RexxReturnCode saveMacroSpace(const char *target)
RexxReturnCode reorderMacro(const char *target, size_t pos)
RexxReturnCode addMacroFromFile(const char *name, const char *sourceFile, size_t position)
void create(size_t count)
void setFilePosition(size_t p)
void nextMacro(char *name, ManagedRxstring &image, size_t &order)
void write(const void *data, size_t length)
void read(void *data, size_t length)
void writeMacroDescriptor(const char *name, size_t size, size_t order)
void ensureCapacity(size_t size)
Definition: Rxstring.hpp:82
bool inTable(const char *name)
size_t strlength
Definition: Rxstring.hpp:49
char * strptr
Definition: Rxstring.hpp:50
ErrorCode getErrorCode()
size_t getMessageDataLength()
ServerOperation operation
void setMessageData(void *data, size_t length)
char nameArg[NAMESIZE]
void transferMessageData(RXSTRING &data)
uintptr_t parameter1
void * getMessageData()
ServiceReturn result
uintptr_t parameter2
bool getSize(int64_t &size)
bool seek(int64_t offset, int direction, int64_t &position)
bool close()
bool open(const char *name, int openFlags, int openMode, int shareMode)
bool read(char *buf, size_t len, size_t &bytesRead)
bool write(const char *data, size_t len, size_t &bytesWritten)
void * getProcedure(const char *name)
bool load(const char *name)
int RexxReturnCode
Definition: rexx.h:73
#define RexxEntry
Definition: rexx.h:235
#define RXMACRO_NO_STORAGE
Definition: rexxapidefs.h:227
#define RXMACRO_NOT_FOUND
Definition: rexxapidefs.h:228
#define RXMACRO_OK
Definition: rexxapidefs.h:226
#define RXMACRO_SOURCE_NOT_FOUND
Definition: rexxapidefs.h:233
#define RXMACRO_FILE_ERROR
Definition: rexxapidefs.h:231
#define RXMACRO_SIGNATURE_ERROR
Definition: rexxapidefs.h:232
#define RX_O_WRONLY
#define RX_S_IWRITE
#define RX_O_TRUNC
#define RX_S_IREAD
#define RX_O_RDONLY
#define RX_SH_DENYRW
#define RX_SH_DENYWR
#define RX_O_CREAT
signed __int64 int64_t